mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 04:36:43 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7ab54da8c4 | |||
| 2cce29e858 | |||
| ef1223391b | |||
| fb98a797ba | |||
| 6be31bdeb2 | |||
| 1d4ee0c33e | |||
| a3e102e456 | |||
| 21dcac9fac | |||
| f0ee82fdd2 | |||
| 0c6a098af9 | |||
| 5bf359d34f | |||
| 6d784f2444 | |||
| 835bf1e77f |
23
Changelog.md
23
Changelog.md
@ -2,6 +2,27 @@
|
||||
|
||||
Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
||||
|
||||
## [Bridge 1.8.7] James
|
||||
|
||||
### Changed
|
||||
* GODT-1201: Update gopenpgp to 2.1.10.
|
||||
|
||||
### Fixed
|
||||
* GODT-1193: Do not doubly encode parts.
|
||||
|
||||
|
||||
## [Bridge 1.8.6] James
|
||||
|
||||
### Removed
|
||||
* GODT-1187: Remove IMAP/SMTP blocking when no internet.
|
||||
|
||||
### Changed
|
||||
* GODT-1166: Reduce the number of auth for live test.
|
||||
|
||||
### Fixed
|
||||
* GODT-1193: Do not use message.Read permit non-UTF-8 charsets.
|
||||
|
||||
|
||||
## [Bridge 1.8.5] James
|
||||
|
||||
### Fixed
|
||||
@ -14,7 +35,7 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
||||
### Added
|
||||
* GODT-1155: Update gopenpgp v2.1.9 and use go-srp.
|
||||
* GODT-1044: Lite parser for appended messages.
|
||||
* GODT-1183: Add test for getting contact emails by email
|
||||
* GODT-1183: Add test for getting contact emails by email.
|
||||
* GODT-1184: Preserve signatures in externally signed messages.
|
||||
|
||||
### Changed
|
||||
|
||||
2
Makefile
2
Makefile
@ -10,7 +10,7 @@ TARGET_OS?=${GOOS}
|
||||
.PHONY: build build-ie build-nogui build-ie-nogui build-launcher build-launcher-ie versioner hasher
|
||||
|
||||
# Keep version hardcoded so app build works also without Git repository.
|
||||
BRIDGE_APP_VERSION?=1.8.5+git
|
||||
BRIDGE_APP_VERSION?=1.8.7+git
|
||||
IE_APP_VERSION?=1.3.3+git
|
||||
APP_VERSION:=${BRIDGE_APP_VERSION}
|
||||
SRC_ICO:=logo.ico
|
||||
|
||||
5
go.mod
5
go.mod
@ -19,7 +19,7 @@ require (
|
||||
github.com/ProtonMail/go-rfc5322 v0.8.0
|
||||
github.com/ProtonMail/go-srp v0.0.0-20210514134713-bd9454f3fa01
|
||||
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.1.9
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.1.10
|
||||
github.com/PuerkitoBio/goquery v1.5.1
|
||||
github.com/abiosoft/ishell v2.0.0+incompatible
|
||||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db // indirect
|
||||
@ -59,6 +59,8 @@ require (
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/therecipe/qt v0.0.0-20200701200531-7f61353ee73e
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200904063919-c0c124a5770d // indirect
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200904063919-c0c124a5770d // indirect
|
||||
github.com/urfave/cli/v2 v2.2.0
|
||||
github.com/vmihailenco/msgpack/v5 v5.1.3
|
||||
go.etcd.io/bbolt v1.3.5
|
||||
@ -71,5 +73,6 @@ require (
|
||||
replace (
|
||||
github.com/docker/docker-credential-helpers => github.com/ProtonMail/docker-credential-helpers v1.1.0
|
||||
github.com/emersion/go-imap => github.com/ProtonMail/go-imap v0.0.0-20201228133358-4db68cea0cac
|
||||
github.com/emersion/go-message => github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753
|
||||
github.com/jameskeane/bcrypt => github.com/ProtonMail/bcrypt v0.0.0-20210511135022-227b4adcab57
|
||||
)
|
||||
|
||||
18
go.sum
18
go.sum
@ -20,6 +20,8 @@ github.com/ProtonMail/go-imap v0.0.0-20201228133358-4db68cea0cac h1:2xU3QncAiS/W
|
||||
github.com/ProtonMail/go-imap v0.0.0-20201228133358-4db68cea0cac/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU=
|
||||
github.com/ProtonMail/go-imap-id v0.0.0-20190926060100-f94a56b9ecde h1:5koQozTDELymYOyFbQ/VSubexAEXzDR8qGM5mO8GRdw=
|
||||
github.com/ProtonMail/go-imap-id v0.0.0-20190926060100-f94a56b9ecde/go.mod h1:795VPXcRUIQ9JyMNHP4el582VokQfippgjkQP3Gk0r0=
|
||||
github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297x0QLU80G5I6aLYUu3JYNSpo8j5fkXtFDW0=
|
||||
github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a h1:W6RrgN/sTxg1msqzFFb+G80MFmpjMw61IU+slm+wln4=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
|
||||
github.com/ProtonMail/go-rfc5322 v0.8.0 h1:7emrf75n3CDIduQflx7aT1nJa5h/kGsiFKUYX/+IAkU=
|
||||
@ -28,8 +30,8 @@ github.com/ProtonMail/go-srp v0.0.0-20210514134713-bd9454f3fa01 h1:sRxNvPGnJFh6y
|
||||
github.com/ProtonMail/go-srp v0.0.0-20210514134713-bd9454f3fa01/go.mod h1:jOXzdvWTILIJzl83yzi/EZcnnhpI+A/5EyflaeVfi/0=
|
||||
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5 h1:Uga1DHFN4GUxuDQr0F71tpi8I9HqPIlZodZAI1lR6VQ=
|
||||
github.com/ProtonMail/go-vcard v0.0.0-20180326232728-33aaa0a0c8a5/go.mod h1:oeP9CMN+ajWp5jKp1kue5daJNwMMxLF+ujPaUIoJWlA=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.1.9 h1:MdvkFBP8ldOHYOoaVct9LO+Zv5rl6VdeN1QurntRmkc=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.1.9/go.mod h1:CHIXesUdnPxIxtJTg2P/cxoA0cvUwIBpZIS8SsY82QA=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.1.10 h1:WPwpzVQFvzzFIzHCsJ1RzuVkN4JsMIydl/0vc05yU0E=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.1.10/go.mod h1:CHIXesUdnPxIxtJTg2P/cxoA0cvUwIBpZIS8SsY82QA=
|
||||
github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
|
||||
@ -81,15 +83,11 @@ github.com/emersion/go-imap-unselect v0.0.0-20171113212723-b985794e5f26 h1:FiSb8
|
||||
github.com/emersion/go-imap-unselect v0.0.0-20171113212723-b985794e5f26/go.mod h1:+gnnZx3Mg3MnCzZrv0eZdp5puxXQUgGT/6N6L7ShKfM=
|
||||
github.com/emersion/go-mbox v1.0.2 h1:tE/rT+lEugK9y0myEymCCHnwlZN04hlXPrbKkxRBA5I=
|
||||
github.com/emersion/go-mbox v1.0.2/go.mod h1:Yp9IVuuOYLEuMv4yjgDHvhb5mHOcYH6x92Oas3QqEZI=
|
||||
github.com/emersion/go-message v0.11.1/go.mod h1:C4jnca5HOTo4bGN9YdqNQM9sITuT3Y0K6bSUw9RklvY=
|
||||
github.com/emersion/go-message v0.12.1-0.20201221184100-40c3f864532b h1:xYuhW6egTaCP+zjbUcfoy/Dr3ASdVPR9W7fmkHvZHPE=
|
||||
github.com/emersion/go-message v0.12.1-0.20201221184100-40c3f864532b/go.mod h1:N1JWdZQ2WRUalmdHAX308CWBq747VJ8oUorFI3VCBwU=
|
||||
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-smtp v0.14.0 h1:RYW203p+EcPjL8Z/ZpT9lZ6iOc8MG1MQzEx1UKEkXlA=
|
||||
github.com/emersion/go-smtp v0.14.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||
github.com/emersion/go-vcard v0.0.0-20190105225839-8856043f13c5 h1:n9qx98xiS5V4x2WIpPC2rr9mUM5ri9r/YhCEKbhCHro=
|
||||
@ -176,9 +174,6 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/martinlindhe/base36 v1.0.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8=
|
||||
github.com/martinlindhe/base36 v1.1.0 h1:cIwvvwYse/0+1CkUPYH5ZvVIYG3JrILmQEIbLuar02Y=
|
||||
github.com/martinlindhe/base36 v1.1.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
@ -260,6 +255,10 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/therecipe/qt v0.0.0-20200701200531-7f61353ee73e h1:G0DQ/TRQyrEZjtLlLwevFjaRiG8eeCMlq9WXQ2OO2bk=
|
||||
github.com/therecipe/qt v0.0.0-20200701200531-7f61353ee73e/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us=
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200904063919-c0c124a5770d h1:hAZyEG2swPRWjF0kqqdGERXUazYnRJdAk4a58f14z7Y=
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200904063919-c0c124a5770d/go.mod h1:7m8PDYDEtEVqfjoUQc2UrFqhG0CDmoVJjRlQxexndFc=
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200904063919-c0c124a5770d h1:AJRoBel/g9cDS+yE8BcN3E+TDD/xNAguG21aoR8DAIE=
|
||||
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200904063919-c0c124a5770d/go.mod h1:mH55Ek7AZcdns5KPp99O0bg+78el64YCYWHiQKrOdt4=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
@ -356,6 +355,7 @@ golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190909214602-067311248421/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69 h1:yBHHx+XZqXJBm6Exke3N7V9gnlsyXxoCPEb1yVenjfk=
|
||||
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@ -23,13 +23,11 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
imapid "github.com/ProtonMail/go-imap-id"
|
||||
"github.com/ProtonMail/proton-bridge/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/internal/config/useragent"
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/internal/imap/id"
|
||||
"github.com/ProtonMail/proton-bridge/internal/imap/idle"
|
||||
"github.com/ProtonMail/proton-bridge/internal/imap/uidplus"
|
||||
@ -43,43 +41,58 @@ import (
|
||||
"github.com/emersion/go-imap/backend"
|
||||
imapserver "github.com/emersion/go-imap/server"
|
||||
"github.com/emersion/go-sasl"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type imapServer struct {
|
||||
panicHandler panicHandler
|
||||
server *imapserver.Server
|
||||
userAgent *useragent.UserAgent
|
||||
eventListener listener.Listener
|
||||
debugClient bool
|
||||
debugServer bool
|
||||
port int
|
||||
isRunning atomic.Value
|
||||
// Server takes care of IMAP listening serving. It implements serverutil.Server.
|
||||
type Server struct {
|
||||
panicHandler panicHandler
|
||||
userAgent *useragent.UserAgent
|
||||
debugClient bool
|
||||
debugServer bool
|
||||
port int
|
||||
|
||||
server *imapserver.Server
|
||||
controller serverutil.Controller
|
||||
}
|
||||
|
||||
// NewIMAPServer constructs a new IMAP server configured with the given options.
|
||||
func NewIMAPServer(panicHandler panicHandler, debugClient, debugServer bool, port int, tls *tls.Config, imapBackend backend.Backend, userAgent *useragent.UserAgent, eventListener listener.Listener) *imapServer { // nolint[golint]
|
||||
s := imapserver.New(imapBackend)
|
||||
s.Addr = fmt.Sprintf("%v:%v", bridge.Host, port)
|
||||
s.TLSConfig = tls
|
||||
s.AllowInsecureAuth = true
|
||||
s.ErrorLog = newServerErrorLogger("server-imap")
|
||||
s.AutoLogout = 30 * time.Minute
|
||||
|
||||
if debugServer {
|
||||
fmt.Println("THE LOG WILL CONTAIN **DECRYPTED** MESSAGE DATA")
|
||||
log.Warning("================================================")
|
||||
log.Warning("THIS LOG WILL CONTAIN **DECRYPTED** MESSAGE DATA")
|
||||
log.Warning("================================================")
|
||||
func NewIMAPServer(
|
||||
panicHandler panicHandler,
|
||||
debugClient, debugServer bool,
|
||||
port int,
|
||||
tls *tls.Config,
|
||||
imapBackend backend.Backend,
|
||||
userAgent *useragent.UserAgent,
|
||||
eventListener listener.Listener,
|
||||
) *Server {
|
||||
server := &Server{
|
||||
panicHandler: panicHandler,
|
||||
userAgent: userAgent,
|
||||
debugClient: debugClient,
|
||||
debugServer: debugServer,
|
||||
port: port,
|
||||
}
|
||||
|
||||
server.server = newGoIMAPServer(tls, imapBackend, server.Address(), userAgent)
|
||||
server.controller = serverutil.NewController(server, eventListener)
|
||||
return server
|
||||
}
|
||||
|
||||
func newGoIMAPServer(tls *tls.Config, backend backend.Backend, address string, userAgent *useragent.UserAgent) *imapserver.Server {
|
||||
server := imapserver.New(backend)
|
||||
server.TLSConfig = tls
|
||||
server.AllowInsecureAuth = true
|
||||
server.ErrorLog = serverutil.NewServerErrorLogger(serverutil.IMAP)
|
||||
server.AutoLogout = 30 * time.Minute
|
||||
server.Addr = address
|
||||
|
||||
serverID := imapid.ID{
|
||||
imapid.FieldName: "ProtonMail Bridge",
|
||||
imapid.FieldVendor: "Proton Technologies AG",
|
||||
imapid.FieldSupportURL: "https://protonmail.com/support",
|
||||
}
|
||||
|
||||
s.EnableAuth(sasl.Login, func(conn imapserver.Conn) sasl.Server {
|
||||
server.EnableAuth(sasl.Login, func(conn imapserver.Conn) sasl.Server {
|
||||
return sasl.NewLoginServer(func(address, password string) error {
|
||||
user, err := conn.Server().Backend.Login(nil, address, password)
|
||||
if err != nil {
|
||||
@ -93,7 +106,7 @@ func NewIMAPServer(panicHandler panicHandler, debugClient, debugServer bool, por
|
||||
})
|
||||
})
|
||||
|
||||
s.Enable(
|
||||
server.Enable(
|
||||
idle.NewExtension(),
|
||||
imapmove.NewExtension(),
|
||||
id.NewExtension(serverID, userAgent),
|
||||
@ -103,87 +116,35 @@ func NewIMAPServer(panicHandler panicHandler, debugClient, debugServer bool, por
|
||||
uidplus.NewExtension(),
|
||||
)
|
||||
|
||||
server := &imapServer{
|
||||
panicHandler: panicHandler,
|
||||
server: s,
|
||||
userAgent: userAgent,
|
||||
eventListener: eventListener,
|
||||
debugClient: debugClient,
|
||||
debugServer: debugServer,
|
||||
port: port,
|
||||
}
|
||||
server.isRunning.Store(false)
|
||||
return server
|
||||
}
|
||||
|
||||
func (s *imapServer) HandlePanic() { s.panicHandler.HandlePanic() }
|
||||
func (s *imapServer) IsRunning() bool { return s.isRunning.Load().(bool) }
|
||||
func (s *imapServer) Port() int { return s.port }
|
||||
// ListenAndServe will run server and all monitors.
|
||||
func (s *Server) ListenAndServe() { s.controller.ListenAndServe() }
|
||||
|
||||
// ListenAndServe starts the server and keeps it on based on internet
|
||||
// availability.
|
||||
func (s *imapServer) ListenAndServe() {
|
||||
serverutil.ListenAndServe(s, s.eventListener)
|
||||
}
|
||||
// Close turns off server and monitors.
|
||||
func (s *Server) Close() { s.controller.Close() }
|
||||
|
||||
// ListenRetryAndServe will start listener. If port is occupied it will try
|
||||
// again after coolDown time. Once listener is OK it will serve.
|
||||
func (s *imapServer) ListenRetryAndServe(retries int, retryAfter time.Duration) {
|
||||
if s.IsRunning() {
|
||||
return
|
||||
}
|
||||
s.isRunning.Store(true)
|
||||
// Implements serverutil.Server interface.
|
||||
|
||||
l := log.WithField("address", s.server.Addr)
|
||||
l.Info("IMAP server is starting")
|
||||
listener, err := net.Listen("tcp", s.server.Addr)
|
||||
if err != nil {
|
||||
s.isRunning.Store(false)
|
||||
if retries > 0 {
|
||||
l.WithError(err).WithField("retries", retries).Warn("IMAP listener failed")
|
||||
time.Sleep(retryAfter)
|
||||
s.ListenRetryAndServe(retries-1, retryAfter)
|
||||
return
|
||||
}
|
||||
func (Server) Protocol() serverutil.Protocol { return serverutil.IMAP }
|
||||
func (s *Server) UseSSL() bool { return false }
|
||||
func (s *Server) Address() string { return fmt.Sprintf("%s:%d", bridge.Host, s.port) }
|
||||
func (s *Server) TLSConfig() *tls.Config { return s.server.TLSConfig }
|
||||
func (s *Server) HandlePanic() { s.panicHandler.HandlePanic() }
|
||||
|
||||
l.WithError(err).Error("IMAP listener failed")
|
||||
s.eventListener.Emit(events.ErrorEvent, "IMAP failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
func (s *Server) DebugServer() bool { return s.debugServer }
|
||||
func (s *Server) DebugClient() bool { return s.debugClient }
|
||||
|
||||
err = s.server.Serve(&connListener{
|
||||
Listener: listener,
|
||||
server: s,
|
||||
userAgent: s.userAgent,
|
||||
})
|
||||
// Serve returns error every time, even after closing the server.
|
||||
// User shouldn't be notified about error if server shouldn't be running,
|
||||
// but it should in case it was not closed by `s.Close()`.
|
||||
if err != nil && s.IsRunning() {
|
||||
s.isRunning.Store(false)
|
||||
l.WithError(err).Error("IMAP server failed")
|
||||
s.eventListener.Emit(events.ErrorEvent, "IMAP failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
defer s.server.Close() //nolint[errcheck]
|
||||
func (s *Server) SetLoggers(localDebug, remoteDebug io.Writer) {
|
||||
s.server.Debug = imap.NewDebugWriter(localDebug, remoteDebug)
|
||||
|
||||
l.Info("IMAP server stopped")
|
||||
}
|
||||
|
||||
// Stops the server.
|
||||
func (s *imapServer) Close() {
|
||||
if !s.IsRunning() {
|
||||
return
|
||||
}
|
||||
s.isRunning.Store(false)
|
||||
|
||||
log.Info("Closing IMAP server")
|
||||
if err := s.server.Close(); err != nil {
|
||||
log.WithError(err).Error("Failed to close the connection")
|
||||
if !s.userAgent.HasClient() {
|
||||
s.userAgent.SetClient("UnknownClient", "0.0.1")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *imapServer) DisconnectUser(address string) {
|
||||
func (s *Server) DisconnectUser(address string) {
|
||||
log.Info("Disconnecting all open IMAP connections for ", address)
|
||||
s.server.ForEachConn(func(conn imapserver.Conn) {
|
||||
connUser := conn.Context().User
|
||||
@ -195,60 +156,5 @@ func (s *imapServer) DisconnectUser(address string) {
|
||||
})
|
||||
}
|
||||
|
||||
// connListener sets debug loggers on server containing fields with local
|
||||
// and remote addresses right after new connection is accepted.
|
||||
type connListener struct {
|
||||
net.Listener
|
||||
|
||||
server *imapServer
|
||||
userAgent *useragent.UserAgent
|
||||
}
|
||||
|
||||
func (l *connListener) Accept() (net.Conn, error) {
|
||||
conn, err := l.Listener.Accept()
|
||||
|
||||
if err == nil && (l.server.debugServer || l.server.debugClient) {
|
||||
debugLog := log
|
||||
if addr := conn.LocalAddr(); addr != nil {
|
||||
debugLog = debugLog.WithField("loc", addr.String())
|
||||
}
|
||||
if addr := conn.RemoteAddr(); addr != nil {
|
||||
debugLog = debugLog.WithField("rem", addr.String())
|
||||
}
|
||||
|
||||
var localDebug, remoteDebug io.Writer
|
||||
if l.server.debugServer {
|
||||
localDebug = debugLog.WithField("pkg", "imap/server").WriterLevel(logrus.DebugLevel)
|
||||
}
|
||||
if l.server.debugClient {
|
||||
remoteDebug = debugLog.WithField("pkg", "imap/client").WriterLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
l.server.server.Debug = imap.NewDebugWriter(localDebug, remoteDebug)
|
||||
}
|
||||
|
||||
if !l.userAgent.HasClient() {
|
||||
l.userAgent.SetClient("UnknownClient", "0.0.1")
|
||||
}
|
||||
|
||||
return conn, err
|
||||
}
|
||||
|
||||
// serverErrorLogger implements go-imap/logger interface.
|
||||
type serverErrorLogger struct {
|
||||
tag string
|
||||
}
|
||||
|
||||
func newServerErrorLogger(tag string) *serverErrorLogger {
|
||||
return &serverErrorLogger{tag}
|
||||
}
|
||||
|
||||
func (s *serverErrorLogger) Printf(format string, args ...interface{}) {
|
||||
err := fmt.Sprintf(format, args...)
|
||||
log.WithField("pkg", s.tag).Error(err)
|
||||
}
|
||||
|
||||
func (s *serverErrorLogger) Println(args ...interface{}) {
|
||||
err := fmt.Sprintln(args...)
|
||||
log.WithField("pkg", s.tag).Error(err)
|
||||
}
|
||||
func (s *Server) Serve(listener net.Listener) error { return s.server.Serve(listener) }
|
||||
func (s *Server) StopServe() error { return s.server.Close() }
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package imap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/internal/config/useragent"
|
||||
"github.com/ProtonMail/proton-bridge/internal/serverutil/mocks"
|
||||
imapserver "github.com/emersion/go-imap/server"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestIMAPServerTurnOffAndOnAgain(t *testing.T) {
|
||||
r := require.New(t)
|
||||
ts := mocks.NewTestServer(12345)
|
||||
|
||||
server := imapserver.New(nil)
|
||||
server.Addr = fmt.Sprintf("%v:%v", bridge.Host, ts.WantPort)
|
||||
|
||||
s := &imapServer{
|
||||
panicHandler: ts.PanicHandler,
|
||||
server: server,
|
||||
port: ts.WantPort,
|
||||
eventListener: ts.EventListener,
|
||||
userAgent: useragent.New(),
|
||||
}
|
||||
s.isRunning.Store(false)
|
||||
|
||||
r.True(ts.IsPortFree())
|
||||
|
||||
go s.ListenAndServe()
|
||||
ts.RunServerTests(r)
|
||||
}
|
||||
117
internal/serverutil/controller.go
Normal file
117
internal/serverutil/controller.go
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package serverutil
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Controller will make sure that server is listening and serving and if needed
|
||||
// users are disconnected.
|
||||
type Controller interface {
|
||||
ListenAndServe()
|
||||
Close()
|
||||
}
|
||||
|
||||
// NewController return simple server controller.
|
||||
func NewController(s Server, l listener.Listener) Controller {
|
||||
log := logrus.WithField("pkg", "serverutil").WithField("protocol", s.Protocol())
|
||||
c := &controller{
|
||||
server: s,
|
||||
signals: l,
|
||||
log: log,
|
||||
closeDisconnectUsers: make(chan void),
|
||||
}
|
||||
|
||||
if s.DebugServer() {
|
||||
fmt.Println("THE LOG WILL CONTAIN **DECRYPTED** MESSAGE DATA")
|
||||
log.Warning("================================================")
|
||||
log.Warning("THIS LOG WILL CONTAIN **DECRYPTED** MESSAGE DATA")
|
||||
log.Warning("================================================")
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
type void struct{}
|
||||
|
||||
type controller struct {
|
||||
server Server
|
||||
signals listener.Listener
|
||||
log *logrus.Entry
|
||||
|
||||
closeDisconnectUsers chan void
|
||||
}
|
||||
|
||||
func (c *controller) Close() {
|
||||
c.closeDisconnectUsers <- void{}
|
||||
if err := c.server.StopServe(); err != nil {
|
||||
c.log.WithError(err).Error("Issue when closing server")
|
||||
}
|
||||
}
|
||||
|
||||
// ListenAndServe starts the server and keeps it on based on internet
|
||||
// availability. It also monitors and disconnect users if requested.
|
||||
func (c *controller) ListenAndServe() {
|
||||
go monitorDisconnectedUsers(c.server, c.signals, c.closeDisconnectUsers)
|
||||
|
||||
defer c.server.HandlePanic()
|
||||
|
||||
l := c.log.WithField("useSSL", c.server.UseSSL()).
|
||||
WithField("address", c.server.Address())
|
||||
|
||||
var listener net.Listener
|
||||
var err error
|
||||
|
||||
if c.server.UseSSL() {
|
||||
listener, err = tls.Listen("tcp", c.server.Address(), c.server.TLSConfig())
|
||||
} else {
|
||||
listener, err = net.Listen("tcp", c.server.Address())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
l.WithError(err).Error("Cannot start listner.")
|
||||
c.signals.Emit(events.ErrorEvent, string(c.server.Protocol())+" failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// When starting the Bridge, we don't want to retry to notify user
|
||||
// quickly about the issue. Very probably retry will not help anyway.
|
||||
l.Info("Starting server")
|
||||
err = c.server.Serve(&connListener{listener, c.server})
|
||||
l.WithError(err).Debug("GoSMTP not serving")
|
||||
}
|
||||
|
||||
func monitorDisconnectedUsers(s Server, l listener.Listener, done <-chan void) {
|
||||
ch := make(chan string)
|
||||
l.Add(events.CloseConnectionEvent, ch)
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
case address := <-ch:
|
||||
s.DisconnectUser(address)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,29 +15,25 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package smtp
|
||||
package serverutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/serverutil/mocks"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func TestSMTPServerTurnOffAndOnAgain(t *testing.T) {
|
||||
r := require.New(t)
|
||||
ts := mocks.NewTestServer(12342)
|
||||
|
||||
s := &Server{
|
||||
panicHandler: ts.PanicHandler,
|
||||
port: ts.WantPort,
|
||||
eventListener: ts.EventListener,
|
||||
}
|
||||
s.isRunning.Store(false)
|
||||
|
||||
r.True(ts.IsPortFree())
|
||||
|
||||
go s.ListenAndServe()
|
||||
ts.RunServerTests(r)
|
||||
// ServerErrorLogger implements go-imap/logger interface.
|
||||
type ServerErrorLogger struct {
|
||||
l *logrus.Entry
|
||||
}
|
||||
|
||||
func NewServerErrorLogger(protocol Protocol) *ServerErrorLogger {
|
||||
return &ServerErrorLogger{l: logrus.WithField("protocol", protocol)}
|
||||
}
|
||||
|
||||
func (s *ServerErrorLogger) Printf(format string, args ...interface{}) {
|
||||
s.l.Errorf(format, args...)
|
||||
}
|
||||
|
||||
func (s *ServerErrorLogger) Println(args ...interface{}) {
|
||||
s.l.Errorln(args...)
|
||||
}
|
||||
59
internal/serverutil/listener.go
Normal file
59
internal/serverutil/listener.go
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package serverutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// connListener sets debug loggers on server containing fields with local
|
||||
// and remote addresses right after new connection is accepted.
|
||||
type connListener struct {
|
||||
net.Listener
|
||||
|
||||
server Server
|
||||
}
|
||||
|
||||
func (l *connListener) Accept() (net.Conn, error) {
|
||||
conn, err := l.Listener.Accept()
|
||||
|
||||
if err == nil && (l.server.DebugServer() || l.server.DebugClient()) {
|
||||
debugLog := logrus.WithField("pkg", l.server.Protocol())
|
||||
if addr := conn.LocalAddr(); addr != nil {
|
||||
debugLog = debugLog.WithField("loc", addr.String())
|
||||
}
|
||||
if addr := conn.RemoteAddr(); addr != nil {
|
||||
debugLog = debugLog.WithField("rem", addr.String())
|
||||
}
|
||||
|
||||
var localDebug, remoteDebug io.Writer
|
||||
if l.server.DebugServer() {
|
||||
localDebug = debugLog.WithField("comm", "server").WriterLevel(logrus.DebugLevel)
|
||||
}
|
||||
if l.server.DebugClient() {
|
||||
remoteDebug = debugLog.WithField("comm", "client").WriterLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
l.server.SetLoggers(localDebug, remoteDebug)
|
||||
}
|
||||
|
||||
return conn, err
|
||||
}
|
||||
@ -1,150 +0,0 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/ports"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type DummyPanicHandler struct{}
|
||||
|
||||
func (ph *DummyPanicHandler) HandlePanic() {}
|
||||
|
||||
type TestServer struct {
|
||||
PanicHandler *DummyPanicHandler
|
||||
WantPort int
|
||||
EventListener listener.Listener
|
||||
|
||||
isRunning atomic.Value
|
||||
srv *http.Server
|
||||
}
|
||||
|
||||
func NewTestServer(port int) *TestServer {
|
||||
s := &TestServer{
|
||||
PanicHandler: &DummyPanicHandler{},
|
||||
EventListener: listener.New(),
|
||||
WantPort: ports.FindFreePortFrom(port),
|
||||
}
|
||||
s.isRunning.Store(false)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *TestServer) IsPortFree() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *TestServer) IsPortOccupied() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *TestServer) Emit(event string, try, iEvt int) int {
|
||||
// Emit has separate go routine so it is needed to wait here to
|
||||
// prevent event race condition.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
iEvt++
|
||||
s.EventListener.Emit(event, fmt.Sprintf("%d:%d", try, iEvt))
|
||||
return iEvt
|
||||
}
|
||||
|
||||
func (s *TestServer) HandlePanic() {}
|
||||
func (s *TestServer) DisconnectUser(string) {}
|
||||
func (s *TestServer) Port() int { return s.WantPort }
|
||||
func (s *TestServer) IsRunning() bool { return s.isRunning.Load().(bool) }
|
||||
|
||||
func (s *TestServer) ListenRetryAndServe(retries int, retryAfter time.Duration) {
|
||||
if s.isRunning.Load().(bool) {
|
||||
return
|
||||
}
|
||||
s.isRunning.Store(true)
|
||||
|
||||
// There can be delay when starting server
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
||||
s.srv = &http.Server{
|
||||
Addr: fmt.Sprintf("127.0.0.1:%d", s.WantPort),
|
||||
}
|
||||
|
||||
err := s.srv.ListenAndServe()
|
||||
if err != nil {
|
||||
s.isRunning.Store(false)
|
||||
if retries > 0 {
|
||||
time.Sleep(retryAfter)
|
||||
s.ListenRetryAndServe(retries-1, retryAfter)
|
||||
}
|
||||
}
|
||||
|
||||
if s.IsRunning() {
|
||||
logrus.Error("Not serving but isRunning is true")
|
||||
s.isRunning.Store(false)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *TestServer) Close() {
|
||||
if !s.isRunning.Load().(bool) {
|
||||
return
|
||||
}
|
||||
s.isRunning.Store(false)
|
||||
|
||||
// There can be delay when stopping server
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
if err := s.srv.Close(); err != nil {
|
||||
logrus.WithError(err).Error("Closing dummy server")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *TestServer) RunServerTests(r *require.Assertions) {
|
||||
// NOTE About choosing tick durations:
|
||||
// In order to avoid ticks to synchronise and cause occasional race
|
||||
// condition we choose the tick duration around 100ms but not exactly
|
||||
// to have large common multiple.
|
||||
r.Eventually(s.IsPortOccupied, 5*time.Second, 97*time.Millisecond)
|
||||
|
||||
// There was an issue where second time we were not able to restore server.
|
||||
for try := 0; try < 3; try++ {
|
||||
i := s.Emit(events.InternetOffEvent, try, 0)
|
||||
r.Eventually(s.IsPortFree, 10*time.Second, 99*time.Millisecond, "signal off try %d : %d", try, i)
|
||||
|
||||
i = s.Emit(events.InternetOnEvent, try, i)
|
||||
i = s.Emit(events.InternetOffEvent, try, i)
|
||||
i = s.Emit(events.InternetOffEvent, try, i)
|
||||
i = s.Emit(events.InternetOffEvent, try, i)
|
||||
i = s.Emit(events.InternetOffEvent, try, i)
|
||||
i = s.Emit(events.InternetOnEvent, try, i)
|
||||
i = s.Emit(events.InternetOnEvent, try, i)
|
||||
i = s.Emit(events.InternetOffEvent, try, i)
|
||||
// Wait a bit longer if needed to process all events
|
||||
r.Eventually(s.IsPortFree, 20*time.Second, 101*time.Millisecond, "again signal off number %d : %d", try, i)
|
||||
|
||||
i = s.Emit(events.InternetOnEvent, try, i)
|
||||
r.Eventually(s.IsPortOccupied, 10*time.Second, 103*time.Millisecond, "signal on number %d : %d", try, i)
|
||||
|
||||
i = s.Emit(events.InternetOffEvent, try, i)
|
||||
i = s.Emit(events.InternetOnEvent, try, i)
|
||||
i = s.Emit(events.InternetOnEvent, try, i)
|
||||
r.Eventually(s.IsPortOccupied, 10*time.Second, 107*time.Millisecond, "again signal on number %d : %d", try, i)
|
||||
}
|
||||
}
|
||||
@ -17,19 +17,10 @@
|
||||
|
||||
package serverutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
type Protocol string
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/serverutil/mocks"
|
||||
"github.com/stretchr/testify/require"
|
||||
const (
|
||||
HTTP = Protocol("HTTP")
|
||||
IMAP = Protocol("IMAP")
|
||||
SMTP = Protocol("SMTP")
|
||||
)
|
||||
|
||||
func TestServerTurnOffAndOnAgain(t *testing.T) {
|
||||
r := require.New(t)
|
||||
s := mocks.NewTestServer(12321)
|
||||
|
||||
r.True(s.IsPortFree())
|
||||
|
||||
go ListenAndServe(s, s.EventListener)
|
||||
s.RunServerTests(r)
|
||||
}
|
||||
@ -18,115 +18,24 @@
|
||||
package serverutil
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/ports"
|
||||
"github.com/sirupsen/logrus"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Server which can handle disconnected users and lost internet connection.
|
||||
// Server can handle disconnected users.
|
||||
type Server interface {
|
||||
Protocol() Protocol
|
||||
UseSSL() bool
|
||||
Address() string
|
||||
TLSConfig() *tls.Config
|
||||
|
||||
DebugServer() bool
|
||||
DebugClient() bool
|
||||
SetLoggers(localDebug, remoteDebug io.Writer)
|
||||
|
||||
HandlePanic()
|
||||
DisconnectUser(string)
|
||||
ListenRetryAndServe(int, time.Duration)
|
||||
Close()
|
||||
Port() int
|
||||
IsRunning() bool
|
||||
}
|
||||
|
||||
func monitorDisconnectedUsers(s Server, l listener.Listener) {
|
||||
ch := make(chan string)
|
||||
l.Add(events.CloseConnectionEvent, ch)
|
||||
for address := range ch {
|
||||
s.DisconnectUser(address)
|
||||
}
|
||||
}
|
||||
|
||||
func redirectInternetEventsToOneChannel(l listener.Listener) (isInternetOn chan bool) {
|
||||
on := make(chan string)
|
||||
l.Add(events.InternetOnEvent, on)
|
||||
off := make(chan string)
|
||||
l.Add(events.InternetOffEvent, off)
|
||||
|
||||
// Redirect two channels into one. When select was used the algorithm
|
||||
// first read all on channels and then read all off channels.
|
||||
isInternetOn = make(chan bool, 20)
|
||||
go func() {
|
||||
for {
|
||||
logrus.WithField("try", <-on).Trace("Internet ON")
|
||||
isInternetOn <- true
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
logrus.WithField("try", <-off).Trace("Internet OFF")
|
||||
isInternetOn <- false
|
||||
}
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
const (
|
||||
recheckPortAfter = 50 * time.Millisecond
|
||||
stopPortChecksAfter = 15 * time.Second
|
||||
retryListenerAfter = 5 * time.Second
|
||||
)
|
||||
|
||||
func monitorInternetConnection(s Server, l listener.Listener) {
|
||||
isInternetOn := redirectInternetEventsToOneChannel(l)
|
||||
for {
|
||||
var expectedIsPortFree bool
|
||||
if <-isInternetOn {
|
||||
if s.IsRunning() {
|
||||
continue
|
||||
}
|
||||
go func() {
|
||||
defer s.HandlePanic()
|
||||
// We had issues on Mac that from time to time something
|
||||
// blocked our port for a bit after we closed IMAP server
|
||||
// due to connection issues.
|
||||
// Restart always helped, so we do retry to not bother user.
|
||||
s.ListenRetryAndServe(10, retryListenerAfter)
|
||||
}()
|
||||
expectedIsPortFree = false
|
||||
} else {
|
||||
if !s.IsRunning() {
|
||||
continue
|
||||
}
|
||||
s.Close()
|
||||
expectedIsPortFree = true
|
||||
}
|
||||
start := time.Now()
|
||||
for {
|
||||
isPortFree := ports.IsPortFree(s.Port())
|
||||
logrus.
|
||||
WithField("port", s.Port()).
|
||||
WithField("isFree", isPortFree).
|
||||
WithField("wantToBeFree", expectedIsPortFree).
|
||||
Trace("Check port")
|
||||
if isPortFree == expectedIsPortFree {
|
||||
break
|
||||
}
|
||||
// Safety stop if something went wrong.
|
||||
if time.Since(start) > stopPortChecksAfter {
|
||||
logrus.WithField("expectedIsPortFree", expectedIsPortFree).Warn("Server start/stop check timeouted")
|
||||
break
|
||||
}
|
||||
time.Sleep(recheckPortAfter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ListenAndServe starts the server and keeps it on based on internet
|
||||
// availability. It also monitors and disconnect users if requested.
|
||||
func ListenAndServe(s Server, l listener.Listener) {
|
||||
go monitorDisconnectedUsers(s, l)
|
||||
go monitorInternetConnection(s, l)
|
||||
|
||||
// When starting the Bridge, we don't want to retry to notify user
|
||||
// quickly about the issue. Very probably retry will not help anyway.
|
||||
s.ListenRetryAndServe(0, 0)
|
||||
Serve(net.Listener) error
|
||||
StopServe() error
|
||||
}
|
||||
|
||||
153
internal/serverutil/test/controller_test.go
Normal file
153
internal/serverutil/test/controller_test.go
Normal file
@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/internal/serverutil"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func setup(t *testing.T) (*require.Assertions, *testServer, listener.Listener, serverutil.Controller) {
|
||||
r := require.New(t)
|
||||
s := newTestServer()
|
||||
l := listener.New()
|
||||
c := serverutil.NewController(s, l)
|
||||
|
||||
return r, s, l, c
|
||||
}
|
||||
|
||||
func TestControllerListernServeClose(t *testing.T) {
|
||||
r, s, l, c := setup(t)
|
||||
|
||||
errorCh := l.ProvideChannel(events.ErrorEvent)
|
||||
|
||||
r.True(s.portIsFree())
|
||||
go c.ListenAndServe()
|
||||
r.Eventually(s.portIsOccupied, time.Second, 50*time.Millisecond)
|
||||
|
||||
r.NoError(s.ping())
|
||||
|
||||
r.Nil(s.localDebug)
|
||||
r.Nil(s.remoteDebug)
|
||||
|
||||
c.Close()
|
||||
r.Eventually(s.portIsFree, time.Second, 50*time.Millisecond)
|
||||
|
||||
select {
|
||||
case msg := <-errorCh:
|
||||
r.Fail("Expected no error but have %q", msg)
|
||||
case <-time.Tick(100 * time.Millisecond):
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func TestControllerFailOnBusyPort(t *testing.T) {
|
||||
r, s, l, c := setup(t)
|
||||
|
||||
ocupator := http.Server{Addr: s.Address()}
|
||||
defer ocupator.Close() //nolint[errcheck]
|
||||
|
||||
go ocupator.ListenAndServe() //nolint[errcheck]
|
||||
r.Eventually(s.portIsOccupied, time.Second, 50*time.Millisecond)
|
||||
|
||||
errorCh := l.ProvideChannel(events.ErrorEvent)
|
||||
go c.ListenAndServe()
|
||||
|
||||
r.Eventually(s.portIsOccupied, time.Second, 50*time.Millisecond)
|
||||
|
||||
select {
|
||||
case <-errorCh:
|
||||
break
|
||||
case <-time.Tick(time.Second):
|
||||
r.Fail("Expected error but have none.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestControllerCallDisconnectUser(t *testing.T) {
|
||||
r, s, l, c := setup(t)
|
||||
|
||||
go c.ListenAndServe()
|
||||
r.Eventually(s.portIsOccupied, time.Second, 50*time.Millisecond)
|
||||
r.NoError(s.ping())
|
||||
|
||||
l.Emit(events.CloseConnectionEvent, "")
|
||||
r.Eventually(func() bool { return s.calledDisconnected == 1 }, time.Second, 50*time.Millisecond)
|
||||
|
||||
c.Close()
|
||||
r.Eventually(s.portIsFree, time.Second, 50*time.Millisecond)
|
||||
|
||||
l.Emit(events.CloseConnectionEvent, "")
|
||||
r.Equal(1, s.calledDisconnected)
|
||||
}
|
||||
|
||||
func TestDebugClient(t *testing.T) {
|
||||
r, s, _, c := setup(t)
|
||||
|
||||
s.debugServer = false
|
||||
s.debugClient = true
|
||||
|
||||
go c.ListenAndServe()
|
||||
r.Eventually(s.portIsOccupied, time.Second, 50*time.Millisecond)
|
||||
r.NoError(s.ping())
|
||||
|
||||
r.Nil(s.localDebug)
|
||||
r.NotNil(s.remoteDebug)
|
||||
|
||||
c.Close()
|
||||
r.Eventually(s.portIsFree, time.Second, 50*time.Millisecond)
|
||||
}
|
||||
|
||||
func TestDebugServer(t *testing.T) {
|
||||
r, s, _, c := setup(t)
|
||||
|
||||
s.debugServer = true
|
||||
s.debugClient = false
|
||||
|
||||
go c.ListenAndServe()
|
||||
r.Eventually(s.portIsOccupied, time.Second, 50*time.Millisecond)
|
||||
r.NoError(s.ping())
|
||||
|
||||
r.NotNil(s.localDebug)
|
||||
r.Nil(s.remoteDebug)
|
||||
|
||||
c.Close()
|
||||
r.Eventually(s.portIsFree, time.Second, 50*time.Millisecond)
|
||||
}
|
||||
|
||||
func TestDebugBoth(t *testing.T) {
|
||||
r, s, _, c := setup(t)
|
||||
|
||||
s.debugServer = true
|
||||
s.debugClient = true
|
||||
|
||||
go c.ListenAndServe()
|
||||
r.Eventually(s.portIsOccupied, time.Second, 50*time.Millisecond)
|
||||
r.NoError(s.ping())
|
||||
|
||||
r.NotNil(s.localDebug)
|
||||
r.NotNil(s.remoteDebug)
|
||||
|
||||
c.Close()
|
||||
r.Eventually(s.portIsFree, time.Second, 50*time.Millisecond)
|
||||
}
|
||||
88
internal/serverutil/test/server.go
Normal file
88
internal/serverutil/test/server.go
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/serverutil"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/ports"
|
||||
)
|
||||
|
||||
func newTestServer() *testServer {
|
||||
return &testServer{port: 11188}
|
||||
}
|
||||
|
||||
type testServer struct {
|
||||
http http.Server
|
||||
|
||||
useSSL,
|
||||
debugServer,
|
||||
debugClient bool
|
||||
calledDisconnected int
|
||||
|
||||
port int
|
||||
tls *tls.Config
|
||||
|
||||
localDebug, remoteDebug io.Writer
|
||||
}
|
||||
|
||||
func (*testServer) Protocol() serverutil.Protocol { return serverutil.HTTP }
|
||||
func (s *testServer) UseSSL() bool { return s.useSSL }
|
||||
func (s *testServer) Address() string { return fmt.Sprintf("127.0.0.1:%d", s.port) }
|
||||
func (s *testServer) TLSConfig() *tls.Config { return s.tls }
|
||||
func (s *testServer) HandlePanic() {}
|
||||
|
||||
func (s *testServer) DebugServer() bool { return s.debugServer }
|
||||
func (s *testServer) DebugClient() bool { return s.debugClient }
|
||||
func (s *testServer) SetLoggers(localDebug, remoteDebug io.Writer) {
|
||||
s.localDebug = localDebug
|
||||
s.remoteDebug = remoteDebug
|
||||
}
|
||||
|
||||
func (s *testServer) DisconnectUser(string) {
|
||||
s.calledDisconnected++
|
||||
}
|
||||
|
||||
func (s *testServer) Serve(l net.Listener) error {
|
||||
return s.http.Serve(l)
|
||||
}
|
||||
|
||||
func (s *testServer) StopServe() error { return s.http.Close() }
|
||||
|
||||
func (s *testServer) portIsFree() bool {
|
||||
return ports.IsPortFree(s.port)
|
||||
}
|
||||
|
||||
func (s *testServer) portIsOccupied() bool {
|
||||
return !ports.IsPortFree(s.port)
|
||||
}
|
||||
|
||||
func (s *testServer) ping() error {
|
||||
client := &http.Client{}
|
||||
resp, err := client.Get("http://" + s.Address() + "/ping")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resp.Body.Close()
|
||||
}
|
||||
@ -20,72 +20,60 @@ package smtp
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/internal/serverutil"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/emersion/go-sasl"
|
||||
goSMTP "github.com/emersion/go-smtp"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Server is Bridge SMTP server implementation.
|
||||
type Server struct {
|
||||
panicHandler panicHandler
|
||||
backend goSMTP.Backend
|
||||
server *goSMTP.Server
|
||||
eventListener listener.Listener
|
||||
debug bool
|
||||
useSSL bool
|
||||
port int
|
||||
tls *tls.Config
|
||||
isRunning atomic.Value
|
||||
panicHandler panicHandler
|
||||
backend goSMTP.Backend
|
||||
debug bool
|
||||
useSSL bool
|
||||
port int
|
||||
tls *tls.Config
|
||||
|
||||
server *goSMTP.Server
|
||||
controller serverutil.Controller
|
||||
}
|
||||
|
||||
// NewSMTPServer returns an SMTP server configured with the given options.
|
||||
func NewSMTPServer(panicHandler panicHandler, debug bool, port int, useSSL bool, tls *tls.Config, smtpBackend goSMTP.Backend, eventListener listener.Listener) *Server {
|
||||
if debug {
|
||||
fmt.Println("THE LOG WILL CONTAIN **DECRYPTED** MESSAGE DATA")
|
||||
log.Warning("================================================")
|
||||
log.Warning("THIS LOG WILL CONTAIN **DECRYPTED** MESSAGE DATA")
|
||||
log.Warning("================================================")
|
||||
func NewSMTPServer(
|
||||
panicHandler panicHandler,
|
||||
debug bool, port int, useSSL bool,
|
||||
tls *tls.Config,
|
||||
smtpBackend goSMTP.Backend,
|
||||
eventListener listener.Listener,
|
||||
) *Server {
|
||||
server := &Server{
|
||||
panicHandler: panicHandler,
|
||||
backend: smtpBackend,
|
||||
debug: debug,
|
||||
useSSL: useSSL,
|
||||
port: port,
|
||||
tls: tls,
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
panicHandler: panicHandler,
|
||||
backend: smtpBackend,
|
||||
eventListener: eventListener,
|
||||
debug: debug,
|
||||
useSSL: useSSL,
|
||||
port: port,
|
||||
tls: tls,
|
||||
}
|
||||
server.isRunning.Store(false)
|
||||
server.server = newGoSMTPServer(server)
|
||||
server.controller = serverutil.NewController(server, eventListener)
|
||||
return server
|
||||
}
|
||||
|
||||
func (s *Server) HandlePanic() { s.panicHandler.HandlePanic() }
|
||||
func (s *Server) IsRunning() bool { return s.isRunning.Load().(bool) }
|
||||
func (s *Server) Port() int { return s.port }
|
||||
|
||||
func newGoSMTPServer(debug bool, smtpBackend goSMTP.Backend, port int, tls *tls.Config) *goSMTP.Server {
|
||||
newSMTP := goSMTP.NewServer(smtpBackend)
|
||||
newSMTP.Addr = fmt.Sprintf("%v:%v", bridge.Host, port)
|
||||
newSMTP.TLSConfig = tls
|
||||
func newGoSMTPServer(s *Server) *goSMTP.Server {
|
||||
newSMTP := goSMTP.NewServer(s.backend)
|
||||
newSMTP.Addr = s.Address()
|
||||
newSMTP.TLSConfig = s.tls
|
||||
newSMTP.Domain = bridge.Host
|
||||
newSMTP.ErrorLog = serverutil.NewServerErrorLogger(serverutil.SMTP)
|
||||
newSMTP.AllowInsecureAuth = true
|
||||
newSMTP.MaxLineLength = 1 << 16
|
||||
|
||||
if debug {
|
||||
newSMTP.Debug = logrus.
|
||||
WithField("pkg", "smtp/server").
|
||||
WriterLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
newSMTP.EnableAuth(sasl.Login, func(conn *goSMTP.Conn) sasl.Server {
|
||||
return sasl.NewLoginServer(func(address, password string) error {
|
||||
user, err := conn.Server().Backend.Login(nil, address, password)
|
||||
@ -100,80 +88,24 @@ func newGoSMTPServer(debug bool, smtpBackend goSMTP.Backend, port int, tls *tls.
|
||||
return newSMTP
|
||||
}
|
||||
|
||||
// ListenAndServe starts the server and keeps it on based on internet
|
||||
// availability.
|
||||
func (s *Server) ListenAndServe() {
|
||||
serverutil.ListenAndServe(s, s.eventListener)
|
||||
}
|
||||
// ListenAndServe will run server and all monitors.
|
||||
func (s *Server) ListenAndServe() { s.controller.ListenAndServe() }
|
||||
|
||||
func (s *Server) ListenRetryAndServe(retries int, retryAfter time.Duration) {
|
||||
if s.IsRunning() {
|
||||
return
|
||||
}
|
||||
s.isRunning.Store(true)
|
||||
// Close turns off server and monitors.
|
||||
func (s *Server) Close() { s.controller.Close() }
|
||||
|
||||
s.server = newGoSMTPServer(s.debug, s.backend, s.port, s.tls)
|
||||
// Implements servertutil.Server interface.
|
||||
|
||||
l := log.WithField("useSSL", s.useSSL).WithField("address", s.server.Addr)
|
||||
l.Info("SMTP server is starting")
|
||||
func (Server) Protocol() serverutil.Protocol { return serverutil.SMTP }
|
||||
func (s *Server) UseSSL() bool { return s.useSSL }
|
||||
func (s *Server) Address() string { return fmt.Sprintf("%s:%d", bridge.Host, s.port) }
|
||||
func (s *Server) TLSConfig() *tls.Config { return s.tls }
|
||||
func (s *Server) HandlePanic() { s.panicHandler.HandlePanic() }
|
||||
|
||||
var listener net.Listener
|
||||
var err error
|
||||
if s.useSSL {
|
||||
listener, err = tls.Listen("tcp", s.server.Addr, s.server.TLSConfig)
|
||||
} else {
|
||||
listener, err = net.Listen("tcp", s.server.Addr)
|
||||
}
|
||||
l.WithError(err).Debug("Listener for SMTP created")
|
||||
if err != nil {
|
||||
s.isRunning.Store(false)
|
||||
if retries > 0 {
|
||||
l.WithError(err).WithField("retries", retries).Warn("SMTP listener failed")
|
||||
time.Sleep(retryAfter)
|
||||
s.ListenRetryAndServe(retries-1, retryAfter)
|
||||
return
|
||||
}
|
||||
func (s *Server) DebugServer() bool { return s.debug }
|
||||
func (s *Server) DebugClient() bool { return s.debug }
|
||||
|
||||
l.WithError(err).Error("SMTP listener failed")
|
||||
s.eventListener.Emit(events.ErrorEvent, "SMTP failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = s.server.Serve(listener)
|
||||
l.WithError(err).Debug("GoSMTP not serving")
|
||||
// Serve returns error every time, even after closing the server.
|
||||
// User shouldn't be notified about error if server shouldn't be running,
|
||||
// but it should in case it was not closed by `s.Close()`.
|
||||
if err != nil && s.IsRunning() {
|
||||
s.isRunning.Store(false)
|
||||
l.WithError(err).Error("SMTP server failed")
|
||||
s.eventListener.Emit(events.ErrorEvent, "SMTP failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
// Go SMTP server instance can be closed only once. Otherwise
|
||||
// it returns an error. The error is not export therefore we
|
||||
// will check the string value.
|
||||
err := s.server.Close()
|
||||
if err == nil || err.Error() != "smtp: server already closed" {
|
||||
l.WithError(err).Warn("Server was not closed")
|
||||
}
|
||||
}()
|
||||
|
||||
l.Info("SMTP server closed")
|
||||
}
|
||||
|
||||
// Close stops the server.
|
||||
func (s *Server) Close() {
|
||||
if !s.IsRunning() {
|
||||
return
|
||||
}
|
||||
s.isRunning.Store(false)
|
||||
|
||||
if err := s.server.Close(); err != nil {
|
||||
log.WithError(err).Error("Cannot close the server")
|
||||
}
|
||||
}
|
||||
func (s *Server) SetLoggers(localDebug, remoteDebug io.Writer) { s.server.Debug = localDebug }
|
||||
|
||||
func (s *Server) DisconnectUser(address string) {
|
||||
log.Info("Disconnecting all open SMTP connections for ", address)
|
||||
@ -186,3 +118,6 @@ func (s *Server) DisconnectUser(address string) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) Serve(l net.Listener) error { return s.server.Serve(l) }
|
||||
func (s *Server) StopServe() error { return s.server.Close() }
|
||||
|
||||
@ -12,89 +12,89 @@ import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockPanicHandler is a mock of PanicHandler interface
|
||||
// MockPanicHandler is a mock of PanicHandler interface.
|
||||
type MockPanicHandler struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockPanicHandlerMockRecorder
|
||||
}
|
||||
|
||||
// MockPanicHandlerMockRecorder is the mock recorder for MockPanicHandler
|
||||
// MockPanicHandlerMockRecorder is the mock recorder for MockPanicHandler.
|
||||
type MockPanicHandlerMockRecorder struct {
|
||||
mock *MockPanicHandler
|
||||
}
|
||||
|
||||
// NewMockPanicHandler creates a new mock instance
|
||||
// NewMockPanicHandler creates a new mock instance.
|
||||
func NewMockPanicHandler(ctrl *gomock.Controller) *MockPanicHandler {
|
||||
mock := &MockPanicHandler{ctrl: ctrl}
|
||||
mock.recorder = &MockPanicHandlerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockPanicHandler) EXPECT() *MockPanicHandlerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// HandlePanic mocks base method
|
||||
// HandlePanic mocks base method.
|
||||
func (m *MockPanicHandler) HandlePanic() {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "HandlePanic")
|
||||
}
|
||||
|
||||
// HandlePanic indicates an expected call of HandlePanic
|
||||
// HandlePanic indicates an expected call of HandlePanic.
|
||||
func (mr *MockPanicHandlerMockRecorder) HandlePanic() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandlePanic", reflect.TypeOf((*MockPanicHandler)(nil).HandlePanic))
|
||||
}
|
||||
|
||||
// MockBridgeUser is a mock of BridgeUser interface
|
||||
// MockBridgeUser is a mock of BridgeUser interface.
|
||||
type MockBridgeUser struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockBridgeUserMockRecorder
|
||||
}
|
||||
|
||||
// MockBridgeUserMockRecorder is the mock recorder for MockBridgeUser
|
||||
// MockBridgeUserMockRecorder is the mock recorder for MockBridgeUser.
|
||||
type MockBridgeUserMockRecorder struct {
|
||||
mock *MockBridgeUser
|
||||
}
|
||||
|
||||
// NewMockBridgeUser creates a new mock instance
|
||||
// NewMockBridgeUser creates a new mock instance.
|
||||
func NewMockBridgeUser(ctrl *gomock.Controller) *MockBridgeUser {
|
||||
mock := &MockBridgeUser{ctrl: ctrl}
|
||||
mock.recorder = &MockBridgeUserMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockBridgeUser) EXPECT() *MockBridgeUserMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// CloseAllConnections mocks base method
|
||||
// CloseAllConnections mocks base method.
|
||||
func (m *MockBridgeUser) CloseAllConnections() {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "CloseAllConnections")
|
||||
}
|
||||
|
||||
// CloseAllConnections indicates an expected call of CloseAllConnections
|
||||
// CloseAllConnections indicates an expected call of CloseAllConnections.
|
||||
func (mr *MockBridgeUserMockRecorder) CloseAllConnections() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseAllConnections", reflect.TypeOf((*MockBridgeUser)(nil).CloseAllConnections))
|
||||
}
|
||||
|
||||
// CloseConnection mocks base method
|
||||
// CloseConnection mocks base method.
|
||||
func (m *MockBridgeUser) CloseConnection(arg0 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "CloseConnection", arg0)
|
||||
}
|
||||
|
||||
// CloseConnection indicates an expected call of CloseConnection
|
||||
// CloseConnection indicates an expected call of CloseConnection.
|
||||
func (mr *MockBridgeUserMockRecorder) CloseConnection(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseConnection", reflect.TypeOf((*MockBridgeUser)(nil).CloseConnection), arg0)
|
||||
}
|
||||
|
||||
// GetAddressID mocks base method
|
||||
// GetAddressID mocks base method.
|
||||
func (m *MockBridgeUser) GetAddressID(arg0 string) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAddressID", arg0)
|
||||
@ -103,13 +103,13 @@ func (m *MockBridgeUser) GetAddressID(arg0 string) (string, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetAddressID indicates an expected call of GetAddressID
|
||||
// GetAddressID indicates an expected call of GetAddressID.
|
||||
func (mr *MockBridgeUserMockRecorder) GetAddressID(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAddressID", reflect.TypeOf((*MockBridgeUser)(nil).GetAddressID), arg0)
|
||||
}
|
||||
|
||||
// GetClient mocks base method
|
||||
// GetClient mocks base method.
|
||||
func (m *MockBridgeUser) GetClient() pmapi.Client {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetClient")
|
||||
@ -117,13 +117,13 @@ func (m *MockBridgeUser) GetClient() pmapi.Client {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetClient indicates an expected call of GetClient
|
||||
// GetClient indicates an expected call of GetClient.
|
||||
func (mr *MockBridgeUserMockRecorder) GetClient() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClient", reflect.TypeOf((*MockBridgeUser)(nil).GetClient))
|
||||
}
|
||||
|
||||
// GetPrimaryAddress mocks base method
|
||||
// GetPrimaryAddress mocks base method.
|
||||
func (m *MockBridgeUser) GetPrimaryAddress() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetPrimaryAddress")
|
||||
@ -131,13 +131,13 @@ func (m *MockBridgeUser) GetPrimaryAddress() string {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetPrimaryAddress indicates an expected call of GetPrimaryAddress
|
||||
// GetPrimaryAddress indicates an expected call of GetPrimaryAddress.
|
||||
func (mr *MockBridgeUserMockRecorder) GetPrimaryAddress() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPrimaryAddress", reflect.TypeOf((*MockBridgeUser)(nil).GetPrimaryAddress))
|
||||
}
|
||||
|
||||
// GetStoreAddresses mocks base method
|
||||
// GetStoreAddresses mocks base method.
|
||||
func (m *MockBridgeUser) GetStoreAddresses() []string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetStoreAddresses")
|
||||
@ -145,13 +145,13 @@ func (m *MockBridgeUser) GetStoreAddresses() []string {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetStoreAddresses indicates an expected call of GetStoreAddresses
|
||||
// GetStoreAddresses indicates an expected call of GetStoreAddresses.
|
||||
func (mr *MockBridgeUserMockRecorder) GetStoreAddresses() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStoreAddresses", reflect.TypeOf((*MockBridgeUser)(nil).GetStoreAddresses))
|
||||
}
|
||||
|
||||
// ID mocks base method
|
||||
// ID mocks base method.
|
||||
func (m *MockBridgeUser) ID() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ID")
|
||||
@ -159,13 +159,13 @@ func (m *MockBridgeUser) ID() string {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ID indicates an expected call of ID
|
||||
// ID indicates an expected call of ID.
|
||||
func (mr *MockBridgeUserMockRecorder) ID() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockBridgeUser)(nil).ID))
|
||||
}
|
||||
|
||||
// IsCombinedAddressMode mocks base method
|
||||
// IsCombinedAddressMode mocks base method.
|
||||
func (m *MockBridgeUser) IsCombinedAddressMode() bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsCombinedAddressMode")
|
||||
@ -173,13 +173,13 @@ func (m *MockBridgeUser) IsCombinedAddressMode() bool {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IsCombinedAddressMode indicates an expected call of IsCombinedAddressMode
|
||||
// IsCombinedAddressMode indicates an expected call of IsCombinedAddressMode.
|
||||
func (mr *MockBridgeUserMockRecorder) IsCombinedAddressMode() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsCombinedAddressMode", reflect.TypeOf((*MockBridgeUser)(nil).IsCombinedAddressMode))
|
||||
}
|
||||
|
||||
// IsConnected mocks base method
|
||||
// IsConnected mocks base method.
|
||||
func (m *MockBridgeUser) IsConnected() bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsConnected")
|
||||
@ -187,13 +187,13 @@ func (m *MockBridgeUser) IsConnected() bool {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IsConnected indicates an expected call of IsConnected
|
||||
// IsConnected indicates an expected call of IsConnected.
|
||||
func (mr *MockBridgeUserMockRecorder) IsConnected() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsConnected", reflect.TypeOf((*MockBridgeUser)(nil).IsConnected))
|
||||
}
|
||||
|
||||
// Logout mocks base method
|
||||
// Logout mocks base method.
|
||||
func (m *MockBridgeUser) Logout() error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Logout")
|
||||
@ -201,13 +201,13 @@ func (m *MockBridgeUser) Logout() error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Logout indicates an expected call of Logout
|
||||
// Logout indicates an expected call of Logout.
|
||||
func (mr *MockBridgeUserMockRecorder) Logout() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Logout", reflect.TypeOf((*MockBridgeUser)(nil).Logout))
|
||||
}
|
||||
|
||||
// UpdateUser mocks base method
|
||||
// UpdateUser mocks base method.
|
||||
func (m *MockBridgeUser) UpdateUser(arg0 context.Context) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateUser", arg0)
|
||||
@ -215,36 +215,36 @@ func (m *MockBridgeUser) UpdateUser(arg0 context.Context) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdateUser indicates an expected call of UpdateUser
|
||||
// UpdateUser indicates an expected call of UpdateUser.
|
||||
func (mr *MockBridgeUserMockRecorder) UpdateUser(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUser", reflect.TypeOf((*MockBridgeUser)(nil).UpdateUser), arg0)
|
||||
}
|
||||
|
||||
// MockChangeNotifier is a mock of ChangeNotifier interface
|
||||
// MockChangeNotifier is a mock of ChangeNotifier interface.
|
||||
type MockChangeNotifier struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockChangeNotifierMockRecorder
|
||||
}
|
||||
|
||||
// MockChangeNotifierMockRecorder is the mock recorder for MockChangeNotifier
|
||||
// MockChangeNotifierMockRecorder is the mock recorder for MockChangeNotifier.
|
||||
type MockChangeNotifierMockRecorder struct {
|
||||
mock *MockChangeNotifier
|
||||
}
|
||||
|
||||
// NewMockChangeNotifier creates a new mock instance
|
||||
// NewMockChangeNotifier creates a new mock instance.
|
||||
func NewMockChangeNotifier(ctrl *gomock.Controller) *MockChangeNotifier {
|
||||
mock := &MockChangeNotifier{ctrl: ctrl}
|
||||
mock.recorder = &MockChangeNotifierMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockChangeNotifier) EXPECT() *MockChangeNotifierMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// CanDelete mocks base method
|
||||
// CanDelete mocks base method.
|
||||
func (m *MockChangeNotifier) CanDelete(arg0 string) (bool, func()) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CanDelete", arg0)
|
||||
@ -253,67 +253,67 @@ func (m *MockChangeNotifier) CanDelete(arg0 string) (bool, func()) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CanDelete indicates an expected call of CanDelete
|
||||
// CanDelete indicates an expected call of CanDelete.
|
||||
func (mr *MockChangeNotifierMockRecorder) CanDelete(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CanDelete", reflect.TypeOf((*MockChangeNotifier)(nil).CanDelete), arg0)
|
||||
}
|
||||
|
||||
// DeleteMessage mocks base method
|
||||
// DeleteMessage mocks base method.
|
||||
func (m *MockChangeNotifier) DeleteMessage(arg0, arg1 string, arg2 uint32) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "DeleteMessage", arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// DeleteMessage indicates an expected call of DeleteMessage
|
||||
// DeleteMessage indicates an expected call of DeleteMessage.
|
||||
func (mr *MockChangeNotifierMockRecorder) DeleteMessage(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteMessage", reflect.TypeOf((*MockChangeNotifier)(nil).DeleteMessage), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// MailboxCreated mocks base method
|
||||
// MailboxCreated mocks base method.
|
||||
func (m *MockChangeNotifier) MailboxCreated(arg0, arg1 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "MailboxCreated", arg0, arg1)
|
||||
}
|
||||
|
||||
// MailboxCreated indicates an expected call of MailboxCreated
|
||||
// MailboxCreated indicates an expected call of MailboxCreated.
|
||||
func (mr *MockChangeNotifierMockRecorder) MailboxCreated(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MailboxCreated", reflect.TypeOf((*MockChangeNotifier)(nil).MailboxCreated), arg0, arg1)
|
||||
}
|
||||
|
||||
// MailboxStatus mocks base method
|
||||
// MailboxStatus mocks base method.
|
||||
func (m *MockChangeNotifier) MailboxStatus(arg0, arg1 string, arg2, arg3, arg4 uint32) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "MailboxStatus", arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
// MailboxStatus indicates an expected call of MailboxStatus
|
||||
// MailboxStatus indicates an expected call of MailboxStatus.
|
||||
func (mr *MockChangeNotifierMockRecorder) MailboxStatus(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MailboxStatus", reflect.TypeOf((*MockChangeNotifier)(nil).MailboxStatus), arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
// Notice mocks base method
|
||||
// Notice mocks base method.
|
||||
func (m *MockChangeNotifier) Notice(arg0, arg1 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Notice", arg0, arg1)
|
||||
}
|
||||
|
||||
// Notice indicates an expected call of Notice
|
||||
// Notice indicates an expected call of Notice.
|
||||
func (mr *MockChangeNotifierMockRecorder) Notice(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Notice", reflect.TypeOf((*MockChangeNotifier)(nil).Notice), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdateMessage mocks base method
|
||||
// UpdateMessage mocks base method.
|
||||
func (m *MockChangeNotifier) UpdateMessage(arg0, arg1 string, arg2, arg3 uint32, arg4 *pmapi.Message, arg5 bool) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "UpdateMessage", arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
// UpdateMessage indicates an expected call of UpdateMessage
|
||||
// UpdateMessage indicates an expected call of UpdateMessage.
|
||||
func (mr *MockChangeNotifierMockRecorder) UpdateMessage(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateMessage", reflect.TypeOf((*MockChangeNotifier)(nil).UpdateMessage), arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
|
||||
@ -11,54 +11,54 @@ import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockListener is a mock of Listener interface
|
||||
// MockListener is a mock of Listener interface.
|
||||
type MockListener struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockListenerMockRecorder
|
||||
}
|
||||
|
||||
// MockListenerMockRecorder is the mock recorder for MockListener
|
||||
// MockListenerMockRecorder is the mock recorder for MockListener.
|
||||
type MockListenerMockRecorder struct {
|
||||
mock *MockListener
|
||||
}
|
||||
|
||||
// NewMockListener creates a new mock instance
|
||||
// NewMockListener creates a new mock instance.
|
||||
func NewMockListener(ctrl *gomock.Controller) *MockListener {
|
||||
mock := &MockListener{ctrl: ctrl}
|
||||
mock.recorder = &MockListenerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockListener) EXPECT() *MockListenerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Add mocks base method
|
||||
// Add mocks base method.
|
||||
func (m *MockListener) Add(arg0 string, arg1 chan<- string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Add", arg0, arg1)
|
||||
}
|
||||
|
||||
// Add indicates an expected call of Add
|
||||
// Add indicates an expected call of Add.
|
||||
func (mr *MockListenerMockRecorder) Add(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockListener)(nil).Add), arg0, arg1)
|
||||
}
|
||||
|
||||
// Emit mocks base method
|
||||
// Emit mocks base method.
|
||||
func (m *MockListener) Emit(arg0, arg1 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Emit", arg0, arg1)
|
||||
}
|
||||
|
||||
// Emit indicates an expected call of Emit
|
||||
// Emit indicates an expected call of Emit.
|
||||
func (mr *MockListenerMockRecorder) Emit(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Emit", reflect.TypeOf((*MockListener)(nil).Emit), arg0, arg1)
|
||||
}
|
||||
|
||||
// ProvideChannel mocks base method
|
||||
// ProvideChannel mocks base method.
|
||||
func (m *MockListener) ProvideChannel(arg0 string) <-chan string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProvideChannel", arg0)
|
||||
@ -66,55 +66,55 @@ func (m *MockListener) ProvideChannel(arg0 string) <-chan string {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ProvideChannel indicates an expected call of ProvideChannel
|
||||
// ProvideChannel indicates an expected call of ProvideChannel.
|
||||
func (mr *MockListenerMockRecorder) ProvideChannel(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvideChannel", reflect.TypeOf((*MockListener)(nil).ProvideChannel), arg0)
|
||||
}
|
||||
|
||||
// Remove mocks base method
|
||||
// Remove mocks base method.
|
||||
func (m *MockListener) Remove(arg0 string, arg1 chan<- string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Remove", arg0, arg1)
|
||||
}
|
||||
|
||||
// Remove indicates an expected call of Remove
|
||||
// Remove indicates an expected call of Remove.
|
||||
func (mr *MockListenerMockRecorder) Remove(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remove", reflect.TypeOf((*MockListener)(nil).Remove), arg0, arg1)
|
||||
}
|
||||
|
||||
// RetryEmit mocks base method
|
||||
// RetryEmit mocks base method.
|
||||
func (m *MockListener) RetryEmit(arg0 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "RetryEmit", arg0)
|
||||
}
|
||||
|
||||
// RetryEmit indicates an expected call of RetryEmit
|
||||
// RetryEmit indicates an expected call of RetryEmit.
|
||||
func (mr *MockListenerMockRecorder) RetryEmit(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetryEmit", reflect.TypeOf((*MockListener)(nil).RetryEmit), arg0)
|
||||
}
|
||||
|
||||
// SetBuffer mocks base method
|
||||
// SetBuffer mocks base method.
|
||||
func (m *MockListener) SetBuffer(arg0 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetBuffer", arg0)
|
||||
}
|
||||
|
||||
// SetBuffer indicates an expected call of SetBuffer
|
||||
// SetBuffer indicates an expected call of SetBuffer.
|
||||
func (mr *MockListenerMockRecorder) SetBuffer(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBuffer", reflect.TypeOf((*MockListener)(nil).SetBuffer), arg0)
|
||||
}
|
||||
|
||||
// SetLimit mocks base method
|
||||
// SetLimit mocks base method.
|
||||
func (m *MockListener) SetLimit(arg0 string, arg1 time.Duration) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetLimit", arg0, arg1)
|
||||
}
|
||||
|
||||
// SetLimit indicates an expected call of SetLimit
|
||||
// SetLimit indicates an expected call of SetLimit.
|
||||
func (mr *MockListenerMockRecorder) SetLimit(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLimit", reflect.TypeOf((*MockListener)(nil).SetLimit), arg0, arg1)
|
||||
|
||||
@ -12,65 +12,65 @@ import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockPanicHandler is a mock of PanicHandler interface
|
||||
// MockPanicHandler is a mock of PanicHandler interface.
|
||||
type MockPanicHandler struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockPanicHandlerMockRecorder
|
||||
}
|
||||
|
||||
// MockPanicHandlerMockRecorder is the mock recorder for MockPanicHandler
|
||||
// MockPanicHandlerMockRecorder is the mock recorder for MockPanicHandler.
|
||||
type MockPanicHandlerMockRecorder struct {
|
||||
mock *MockPanicHandler
|
||||
}
|
||||
|
||||
// NewMockPanicHandler creates a new mock instance
|
||||
// NewMockPanicHandler creates a new mock instance.
|
||||
func NewMockPanicHandler(ctrl *gomock.Controller) *MockPanicHandler {
|
||||
mock := &MockPanicHandler{ctrl: ctrl}
|
||||
mock.recorder = &MockPanicHandlerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockPanicHandler) EXPECT() *MockPanicHandlerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// HandlePanic mocks base method
|
||||
// HandlePanic mocks base method.
|
||||
func (m *MockPanicHandler) HandlePanic() {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "HandlePanic")
|
||||
}
|
||||
|
||||
// HandlePanic indicates an expected call of HandlePanic
|
||||
// HandlePanic indicates an expected call of HandlePanic.
|
||||
func (mr *MockPanicHandlerMockRecorder) HandlePanic() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandlePanic", reflect.TypeOf((*MockPanicHandler)(nil).HandlePanic))
|
||||
}
|
||||
|
||||
// MockIMAPClientProvider is a mock of IMAPClientProvider interface
|
||||
// MockIMAPClientProvider is a mock of IMAPClientProvider interface.
|
||||
type MockIMAPClientProvider struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockIMAPClientProviderMockRecorder
|
||||
}
|
||||
|
||||
// MockIMAPClientProviderMockRecorder is the mock recorder for MockIMAPClientProvider
|
||||
// MockIMAPClientProviderMockRecorder is the mock recorder for MockIMAPClientProvider.
|
||||
type MockIMAPClientProviderMockRecorder struct {
|
||||
mock *MockIMAPClientProvider
|
||||
}
|
||||
|
||||
// NewMockIMAPClientProvider creates a new mock instance
|
||||
// NewMockIMAPClientProvider creates a new mock instance.
|
||||
func NewMockIMAPClientProvider(ctrl *gomock.Controller) *MockIMAPClientProvider {
|
||||
mock := &MockIMAPClientProvider{ctrl: ctrl}
|
||||
mock.recorder = &MockIMAPClientProviderMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockIMAPClientProvider) EXPECT() *MockIMAPClientProviderMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Authenticate mocks base method
|
||||
// Authenticate mocks base method.
|
||||
func (m *MockIMAPClientProvider) Authenticate(arg0 sasl.Client) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Authenticate", arg0)
|
||||
@ -78,13 +78,13 @@ func (m *MockIMAPClientProvider) Authenticate(arg0 sasl.Client) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Authenticate indicates an expected call of Authenticate
|
||||
// Authenticate indicates an expected call of Authenticate.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) Authenticate(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Authenticate", reflect.TypeOf((*MockIMAPClientProvider)(nil).Authenticate), arg0)
|
||||
}
|
||||
|
||||
// Capability mocks base method
|
||||
// Capability mocks base method.
|
||||
func (m *MockIMAPClientProvider) Capability() (map[string]bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Capability")
|
||||
@ -93,13 +93,13 @@ func (m *MockIMAPClientProvider) Capability() (map[string]bool, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Capability indicates an expected call of Capability
|
||||
// Capability indicates an expected call of Capability.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) Capability() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Capability", reflect.TypeOf((*MockIMAPClientProvider)(nil).Capability))
|
||||
}
|
||||
|
||||
// Fetch mocks base method
|
||||
// Fetch mocks base method.
|
||||
func (m *MockIMAPClientProvider) Fetch(arg0 *imap.SeqSet, arg1 []imap.FetchItem, arg2 chan *imap.Message) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Fetch", arg0, arg1, arg2)
|
||||
@ -107,13 +107,13 @@ func (m *MockIMAPClientProvider) Fetch(arg0 *imap.SeqSet, arg1 []imap.FetchItem,
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Fetch indicates an expected call of Fetch
|
||||
// Fetch indicates an expected call of Fetch.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) Fetch(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fetch", reflect.TypeOf((*MockIMAPClientProvider)(nil).Fetch), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// List mocks base method
|
||||
// List mocks base method.
|
||||
func (m *MockIMAPClientProvider) List(arg0, arg1 string, arg2 chan *imap.MailboxInfo) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "List", arg0, arg1, arg2)
|
||||
@ -121,13 +121,13 @@ func (m *MockIMAPClientProvider) List(arg0, arg1 string, arg2 chan *imap.Mailbox
|
||||
return ret0
|
||||
}
|
||||
|
||||
// List indicates an expected call of List
|
||||
// List indicates an expected call of List.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) List(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockIMAPClientProvider)(nil).List), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// Login mocks base method
|
||||
// Login mocks base method.
|
||||
func (m *MockIMAPClientProvider) Login(arg0, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Login", arg0, arg1)
|
||||
@ -135,13 +135,13 @@ func (m *MockIMAPClientProvider) Login(arg0, arg1 string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Login indicates an expected call of Login
|
||||
// Login indicates an expected call of Login.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) Login(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Login", reflect.TypeOf((*MockIMAPClientProvider)(nil).Login), arg0, arg1)
|
||||
}
|
||||
|
||||
// Select mocks base method
|
||||
// Select mocks base method.
|
||||
func (m *MockIMAPClientProvider) Select(arg0 string, arg1 bool) (*imap.MailboxStatus, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Select", arg0, arg1)
|
||||
@ -150,13 +150,13 @@ func (m *MockIMAPClientProvider) Select(arg0 string, arg1 bool) (*imap.MailboxSt
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Select indicates an expected call of Select
|
||||
// Select indicates an expected call of Select.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) Select(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Select", reflect.TypeOf((*MockIMAPClientProvider)(nil).Select), arg0, arg1)
|
||||
}
|
||||
|
||||
// State mocks base method
|
||||
// State mocks base method.
|
||||
func (m *MockIMAPClientProvider) State() imap.ConnState {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "State")
|
||||
@ -164,13 +164,13 @@ func (m *MockIMAPClientProvider) State() imap.ConnState {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// State indicates an expected call of State
|
||||
// State indicates an expected call of State.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) State() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "State", reflect.TypeOf((*MockIMAPClientProvider)(nil).State))
|
||||
}
|
||||
|
||||
// Support mocks base method
|
||||
// Support mocks base method.
|
||||
func (m *MockIMAPClientProvider) Support(arg0 string) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Support", arg0)
|
||||
@ -179,13 +179,13 @@ func (m *MockIMAPClientProvider) Support(arg0 string) (bool, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Support indicates an expected call of Support
|
||||
// Support indicates an expected call of Support.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) Support(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Support", reflect.TypeOf((*MockIMAPClientProvider)(nil).Support), arg0)
|
||||
}
|
||||
|
||||
// SupportAuth mocks base method
|
||||
// SupportAuth mocks base method.
|
||||
func (m *MockIMAPClientProvider) SupportAuth(arg0 string) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SupportAuth", arg0)
|
||||
@ -194,13 +194,13 @@ func (m *MockIMAPClientProvider) SupportAuth(arg0 string) (bool, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SupportAuth indicates an expected call of SupportAuth
|
||||
// SupportAuth indicates an expected call of SupportAuth.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) SupportAuth(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SupportAuth", reflect.TypeOf((*MockIMAPClientProvider)(nil).SupportAuth), arg0)
|
||||
}
|
||||
|
||||
// UidFetch mocks base method
|
||||
// UidFetch mocks base method.
|
||||
func (m *MockIMAPClientProvider) UidFetch(arg0 *imap.SeqSet, arg1 []imap.FetchItem, arg2 chan *imap.Message) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UidFetch", arg0, arg1, arg2)
|
||||
@ -208,7 +208,7 @@ func (m *MockIMAPClientProvider) UidFetch(arg0 *imap.SeqSet, arg1 []imap.FetchIt
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UidFetch indicates an expected call of UidFetch
|
||||
// UidFetch indicates an expected call of UidFetch.
|
||||
func (mr *MockIMAPClientProviderMockRecorder) UidFetch(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UidFetch", reflect.TypeOf((*MockIMAPClientProvider)(nil).UidFetch), arg0, arg1, arg2)
|
||||
|
||||
@ -11,54 +11,54 @@ import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockListener is a mock of Listener interface
|
||||
// MockListener is a mock of Listener interface.
|
||||
type MockListener struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockListenerMockRecorder
|
||||
}
|
||||
|
||||
// MockListenerMockRecorder is the mock recorder for MockListener
|
||||
// MockListenerMockRecorder is the mock recorder for MockListener.
|
||||
type MockListenerMockRecorder struct {
|
||||
mock *MockListener
|
||||
}
|
||||
|
||||
// NewMockListener creates a new mock instance
|
||||
// NewMockListener creates a new mock instance.
|
||||
func NewMockListener(ctrl *gomock.Controller) *MockListener {
|
||||
mock := &MockListener{ctrl: ctrl}
|
||||
mock.recorder = &MockListenerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockListener) EXPECT() *MockListenerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Add mocks base method
|
||||
// Add mocks base method.
|
||||
func (m *MockListener) Add(arg0 string, arg1 chan<- string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Add", arg0, arg1)
|
||||
}
|
||||
|
||||
// Add indicates an expected call of Add
|
||||
// Add indicates an expected call of Add.
|
||||
func (mr *MockListenerMockRecorder) Add(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockListener)(nil).Add), arg0, arg1)
|
||||
}
|
||||
|
||||
// Emit mocks base method
|
||||
// Emit mocks base method.
|
||||
func (m *MockListener) Emit(arg0, arg1 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Emit", arg0, arg1)
|
||||
}
|
||||
|
||||
// Emit indicates an expected call of Emit
|
||||
// Emit indicates an expected call of Emit.
|
||||
func (mr *MockListenerMockRecorder) Emit(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Emit", reflect.TypeOf((*MockListener)(nil).Emit), arg0, arg1)
|
||||
}
|
||||
|
||||
// ProvideChannel mocks base method
|
||||
// ProvideChannel mocks base method.
|
||||
func (m *MockListener) ProvideChannel(arg0 string) <-chan string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProvideChannel", arg0)
|
||||
@ -66,55 +66,55 @@ func (m *MockListener) ProvideChannel(arg0 string) <-chan string {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ProvideChannel indicates an expected call of ProvideChannel
|
||||
// ProvideChannel indicates an expected call of ProvideChannel.
|
||||
func (mr *MockListenerMockRecorder) ProvideChannel(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvideChannel", reflect.TypeOf((*MockListener)(nil).ProvideChannel), arg0)
|
||||
}
|
||||
|
||||
// Remove mocks base method
|
||||
// Remove mocks base method.
|
||||
func (m *MockListener) Remove(arg0 string, arg1 chan<- string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Remove", arg0, arg1)
|
||||
}
|
||||
|
||||
// Remove indicates an expected call of Remove
|
||||
// Remove indicates an expected call of Remove.
|
||||
func (mr *MockListenerMockRecorder) Remove(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remove", reflect.TypeOf((*MockListener)(nil).Remove), arg0, arg1)
|
||||
}
|
||||
|
||||
// RetryEmit mocks base method
|
||||
// RetryEmit mocks base method.
|
||||
func (m *MockListener) RetryEmit(arg0 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "RetryEmit", arg0)
|
||||
}
|
||||
|
||||
// RetryEmit indicates an expected call of RetryEmit
|
||||
// RetryEmit indicates an expected call of RetryEmit.
|
||||
func (mr *MockListenerMockRecorder) RetryEmit(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetryEmit", reflect.TypeOf((*MockListener)(nil).RetryEmit), arg0)
|
||||
}
|
||||
|
||||
// SetBuffer mocks base method
|
||||
// SetBuffer mocks base method.
|
||||
func (m *MockListener) SetBuffer(arg0 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetBuffer", arg0)
|
||||
}
|
||||
|
||||
// SetBuffer indicates an expected call of SetBuffer
|
||||
// SetBuffer indicates an expected call of SetBuffer.
|
||||
func (mr *MockListenerMockRecorder) SetBuffer(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBuffer", reflect.TypeOf((*MockListener)(nil).SetBuffer), arg0)
|
||||
}
|
||||
|
||||
// SetLimit mocks base method
|
||||
// SetLimit mocks base method.
|
||||
func (m *MockListener) SetLimit(arg0 string, arg1 time.Duration) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetLimit", arg0, arg1)
|
||||
}
|
||||
|
||||
// SetLimit indicates an expected call of SetLimit
|
||||
// SetLimit indicates an expected call of SetLimit.
|
||||
func (mr *MockListenerMockRecorder) SetLimit(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLimit", reflect.TypeOf((*MockListener)(nil).SetLimit), arg0, arg1)
|
||||
|
||||
@ -12,30 +12,30 @@ import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockLocator is a mock of Locator interface
|
||||
// MockLocator is a mock of Locator interface.
|
||||
type MockLocator struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockLocatorMockRecorder
|
||||
}
|
||||
|
||||
// MockLocatorMockRecorder is the mock recorder for MockLocator
|
||||
// MockLocatorMockRecorder is the mock recorder for MockLocator.
|
||||
type MockLocatorMockRecorder struct {
|
||||
mock *MockLocator
|
||||
}
|
||||
|
||||
// NewMockLocator creates a new mock instance
|
||||
// NewMockLocator creates a new mock instance.
|
||||
func NewMockLocator(ctrl *gomock.Controller) *MockLocator {
|
||||
mock := &MockLocator{ctrl: ctrl}
|
||||
mock.recorder = &MockLocatorMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockLocator) EXPECT() *MockLocatorMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Clear mocks base method
|
||||
// Clear mocks base method.
|
||||
func (m *MockLocator) Clear() error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Clear")
|
||||
@ -43,71 +43,71 @@ func (m *MockLocator) Clear() error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Clear indicates an expected call of Clear
|
||||
// Clear indicates an expected call of Clear.
|
||||
func (mr *MockLocatorMockRecorder) Clear() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Clear", reflect.TypeOf((*MockLocator)(nil).Clear))
|
||||
}
|
||||
|
||||
// MockPanicHandler is a mock of PanicHandler interface
|
||||
// MockPanicHandler is a mock of PanicHandler interface.
|
||||
type MockPanicHandler struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockPanicHandlerMockRecorder
|
||||
}
|
||||
|
||||
// MockPanicHandlerMockRecorder is the mock recorder for MockPanicHandler
|
||||
// MockPanicHandlerMockRecorder is the mock recorder for MockPanicHandler.
|
||||
type MockPanicHandlerMockRecorder struct {
|
||||
mock *MockPanicHandler
|
||||
}
|
||||
|
||||
// NewMockPanicHandler creates a new mock instance
|
||||
// NewMockPanicHandler creates a new mock instance.
|
||||
func NewMockPanicHandler(ctrl *gomock.Controller) *MockPanicHandler {
|
||||
mock := &MockPanicHandler{ctrl: ctrl}
|
||||
mock.recorder = &MockPanicHandlerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockPanicHandler) EXPECT() *MockPanicHandlerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// HandlePanic mocks base method
|
||||
// HandlePanic mocks base method.
|
||||
func (m *MockPanicHandler) HandlePanic() {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "HandlePanic")
|
||||
}
|
||||
|
||||
// HandlePanic indicates an expected call of HandlePanic
|
||||
// HandlePanic indicates an expected call of HandlePanic.
|
||||
func (mr *MockPanicHandlerMockRecorder) HandlePanic() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandlePanic", reflect.TypeOf((*MockPanicHandler)(nil).HandlePanic))
|
||||
}
|
||||
|
||||
// MockCredentialsStorer is a mock of CredentialsStorer interface
|
||||
// MockCredentialsStorer is a mock of CredentialsStorer interface.
|
||||
type MockCredentialsStorer struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockCredentialsStorerMockRecorder
|
||||
}
|
||||
|
||||
// MockCredentialsStorerMockRecorder is the mock recorder for MockCredentialsStorer
|
||||
// MockCredentialsStorerMockRecorder is the mock recorder for MockCredentialsStorer.
|
||||
type MockCredentialsStorerMockRecorder struct {
|
||||
mock *MockCredentialsStorer
|
||||
}
|
||||
|
||||
// NewMockCredentialsStorer creates a new mock instance
|
||||
// NewMockCredentialsStorer creates a new mock instance.
|
||||
func NewMockCredentialsStorer(ctrl *gomock.Controller) *MockCredentialsStorer {
|
||||
mock := &MockCredentialsStorer{ctrl: ctrl}
|
||||
mock.recorder = &MockCredentialsStorerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockCredentialsStorer) EXPECT() *MockCredentialsStorerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Add mocks base method
|
||||
// Add mocks base method.
|
||||
func (m *MockCredentialsStorer) Add(arg0, arg1, arg2, arg3 string, arg4 []byte, arg5 []string) (*credentials.Credentials, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Add", arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
@ -116,13 +116,13 @@ func (m *MockCredentialsStorer) Add(arg0, arg1, arg2, arg3 string, arg4 []byte,
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Add indicates an expected call of Add
|
||||
// Add indicates an expected call of Add.
|
||||
func (mr *MockCredentialsStorerMockRecorder) Add(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockCredentialsStorer)(nil).Add), arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
// Delete mocks base method
|
||||
// Delete mocks base method.
|
||||
func (m *MockCredentialsStorer) Delete(arg0 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Delete", arg0)
|
||||
@ -130,13 +130,13 @@ func (m *MockCredentialsStorer) Delete(arg0 string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Delete indicates an expected call of Delete
|
||||
// Delete indicates an expected call of Delete.
|
||||
func (mr *MockCredentialsStorerMockRecorder) Delete(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockCredentialsStorer)(nil).Delete), arg0)
|
||||
}
|
||||
|
||||
// Get mocks base method
|
||||
// Get mocks base method.
|
||||
func (m *MockCredentialsStorer) Get(arg0 string) (*credentials.Credentials, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", arg0)
|
||||
@ -145,13 +145,13 @@ func (m *MockCredentialsStorer) Get(arg0 string) (*credentials.Credentials, erro
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockCredentialsStorerMockRecorder) Get(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCredentialsStorer)(nil).Get), arg0)
|
||||
}
|
||||
|
||||
// List mocks base method
|
||||
// List mocks base method.
|
||||
func (m *MockCredentialsStorer) List() ([]string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "List")
|
||||
@ -160,13 +160,13 @@ func (m *MockCredentialsStorer) List() ([]string, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// List indicates an expected call of List
|
||||
// List indicates an expected call of List.
|
||||
func (mr *MockCredentialsStorerMockRecorder) List() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockCredentialsStorer)(nil).List))
|
||||
}
|
||||
|
||||
// Logout mocks base method
|
||||
// Logout mocks base method.
|
||||
func (m *MockCredentialsStorer) Logout(arg0 string) (*credentials.Credentials, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Logout", arg0)
|
||||
@ -175,13 +175,13 @@ func (m *MockCredentialsStorer) Logout(arg0 string) (*credentials.Credentials, e
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Logout indicates an expected call of Logout
|
||||
// Logout indicates an expected call of Logout.
|
||||
func (mr *MockCredentialsStorerMockRecorder) Logout(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Logout", reflect.TypeOf((*MockCredentialsStorer)(nil).Logout), arg0)
|
||||
}
|
||||
|
||||
// SwitchAddressMode mocks base method
|
||||
// SwitchAddressMode mocks base method.
|
||||
func (m *MockCredentialsStorer) SwitchAddressMode(arg0 string) (*credentials.Credentials, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SwitchAddressMode", arg0)
|
||||
@ -190,13 +190,13 @@ func (m *MockCredentialsStorer) SwitchAddressMode(arg0 string) (*credentials.Cre
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SwitchAddressMode indicates an expected call of SwitchAddressMode
|
||||
// SwitchAddressMode indicates an expected call of SwitchAddressMode.
|
||||
func (mr *MockCredentialsStorerMockRecorder) SwitchAddressMode(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SwitchAddressMode", reflect.TypeOf((*MockCredentialsStorer)(nil).SwitchAddressMode), arg0)
|
||||
}
|
||||
|
||||
// UpdateEmails mocks base method
|
||||
// UpdateEmails mocks base method.
|
||||
func (m *MockCredentialsStorer) UpdateEmails(arg0 string, arg1 []string) (*credentials.Credentials, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateEmails", arg0, arg1)
|
||||
@ -205,13 +205,13 @@ func (m *MockCredentialsStorer) UpdateEmails(arg0 string, arg1 []string) (*crede
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateEmails indicates an expected call of UpdateEmails
|
||||
// UpdateEmails indicates an expected call of UpdateEmails.
|
||||
func (mr *MockCredentialsStorerMockRecorder) UpdateEmails(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateEmails", reflect.TypeOf((*MockCredentialsStorer)(nil).UpdateEmails), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdatePassword mocks base method
|
||||
// UpdatePassword mocks base method.
|
||||
func (m *MockCredentialsStorer) UpdatePassword(arg0 string, arg1 []byte) (*credentials.Credentials, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdatePassword", arg0, arg1)
|
||||
@ -220,13 +220,13 @@ func (m *MockCredentialsStorer) UpdatePassword(arg0 string, arg1 []byte) (*crede
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdatePassword indicates an expected call of UpdatePassword
|
||||
// UpdatePassword indicates an expected call of UpdatePassword.
|
||||
func (mr *MockCredentialsStorerMockRecorder) UpdatePassword(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatePassword", reflect.TypeOf((*MockCredentialsStorer)(nil).UpdatePassword), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdateToken mocks base method
|
||||
// UpdateToken mocks base method.
|
||||
func (m *MockCredentialsStorer) UpdateToken(arg0, arg1, arg2 string) (*credentials.Credentials, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateToken", arg0, arg1, arg2)
|
||||
@ -235,36 +235,36 @@ func (m *MockCredentialsStorer) UpdateToken(arg0, arg1, arg2 string) (*credentia
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateToken indicates an expected call of UpdateToken
|
||||
// UpdateToken indicates an expected call of UpdateToken.
|
||||
func (mr *MockCredentialsStorerMockRecorder) UpdateToken(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateToken", reflect.TypeOf((*MockCredentialsStorer)(nil).UpdateToken), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// MockStoreMaker is a mock of StoreMaker interface
|
||||
// MockStoreMaker is a mock of StoreMaker interface.
|
||||
type MockStoreMaker struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockStoreMakerMockRecorder
|
||||
}
|
||||
|
||||
// MockStoreMakerMockRecorder is the mock recorder for MockStoreMaker
|
||||
// MockStoreMakerMockRecorder is the mock recorder for MockStoreMaker.
|
||||
type MockStoreMakerMockRecorder struct {
|
||||
mock *MockStoreMaker
|
||||
}
|
||||
|
||||
// NewMockStoreMaker creates a new mock instance
|
||||
// NewMockStoreMaker creates a new mock instance.
|
||||
func NewMockStoreMaker(ctrl *gomock.Controller) *MockStoreMaker {
|
||||
mock := &MockStoreMaker{ctrl: ctrl}
|
||||
mock.recorder = &MockStoreMakerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockStoreMaker) EXPECT() *MockStoreMakerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// New mocks base method
|
||||
// New mocks base method.
|
||||
func (m *MockStoreMaker) New(arg0 store.BridgeUser) (*store.Store, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "New", arg0)
|
||||
@ -273,13 +273,13 @@ func (m *MockStoreMaker) New(arg0 store.BridgeUser) (*store.Store, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// New indicates an expected call of New
|
||||
// New indicates an expected call of New.
|
||||
func (mr *MockStoreMakerMockRecorder) New(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "New", reflect.TypeOf((*MockStoreMaker)(nil).New), arg0)
|
||||
}
|
||||
|
||||
// Remove mocks base method
|
||||
// Remove mocks base method.
|
||||
func (m *MockStoreMaker) Remove(arg0 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Remove", arg0)
|
||||
@ -287,7 +287,7 @@ func (m *MockStoreMaker) Remove(arg0 string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Remove indicates an expected call of Remove
|
||||
// Remove indicates an expected call of Remove.
|
||||
func (mr *MockStoreMakerMockRecorder) Remove(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remove", reflect.TypeOf((*MockStoreMaker)(nil).Remove), arg0)
|
||||
|
||||
@ -33,6 +33,7 @@ import (
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/text/encoding/htmlindex"
|
||||
)
|
||||
|
||||
func newTestFetcher(
|
||||
@ -66,6 +67,10 @@ func newTestMessage(
|
||||
arm, err := enc.GetArmored()
|
||||
require.NoError(t, err)
|
||||
|
||||
return newRawTestMessage(messageID, addressID, mimeType, arm, date)
|
||||
}
|
||||
|
||||
func newRawTestMessage(messageID, addressID, mimeType, body string, date time.Time) *pmapi.Message {
|
||||
return &pmapi.Message{
|
||||
ID: messageID,
|
||||
AddressID: addressID,
|
||||
@ -74,7 +79,7 @@ func newTestMessage(
|
||||
"Content-Type": {mimeType},
|
||||
"Date": {date.In(time.UTC).Format(time.RFC1123Z)},
|
||||
},
|
||||
Body: arm,
|
||||
Body: body,
|
||||
Time: date.Unix(),
|
||||
}
|
||||
}
|
||||
@ -298,6 +303,25 @@ func decryptsTo(kr *crypto.KeyRing, want string) decryptsToMatcher {
|
||||
return decryptsToMatcher{kr: kr, want: want}
|
||||
}
|
||||
|
||||
type decodesToMatcher struct {
|
||||
charset string
|
||||
want string
|
||||
}
|
||||
|
||||
func (matcher decodesToMatcher) match(t *testing.T, have string) {
|
||||
enc, err := htmlindex.Get(matcher.charset)
|
||||
require.NoError(t, err)
|
||||
|
||||
dec, err := enc.NewDecoder().String(have)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, matcher.want, dec)
|
||||
}
|
||||
|
||||
func decodesTo(charset string, want string) decodesToMatcher {
|
||||
return decodesToMatcher{charset: charset, want: want}
|
||||
}
|
||||
|
||||
type verifiesAgainstMatcher struct {
|
||||
kr *crypto.KeyRing
|
||||
sig *crypto.PGPSignature
|
||||
|
||||
@ -20,7 +20,6 @@ package message
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"net/mail"
|
||||
"strings"
|
||||
@ -31,6 +30,7 @@ import (
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
"github.com/emersion/go-message"
|
||||
"github.com/emersion/go-message/textproto"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -280,27 +280,30 @@ func buildPGPMIMEFallbackRFC822(msg *pmapi.Message, opts JobOptions) ([]byte, er
|
||||
func writeMultipartSignedRFC822(header message.Header, body []byte, sig pmapi.Signature) ([]byte, error) { //nolint[funlen]
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
boundary := newBoundary("").gen()
|
||||
|
||||
header.SetContentType("multipart/signed", map[string]string{
|
||||
"micalg": sig.Hash,
|
||||
"protocol": "application/pgp-signature",
|
||||
"boundary": boundary,
|
||||
})
|
||||
|
||||
w, err := message.CreateWriter(buf, header)
|
||||
if err := textproto.WriteHeader(buf, header.Header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mw := textproto.NewMultipartWriter(buf)
|
||||
|
||||
if err := mw.SetBoundary(boundary); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bodyHeader, bodyData, err := readHeaderBody(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ent, err := message.Read(bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bodyPart, err := w.CreatePart(ent.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bodyData, err := ioutil.ReadAll(ent.Body)
|
||||
bodyPart, err := mw.CreatePart(*bodyHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -309,17 +312,13 @@ func writeMultipartSignedRFC822(header message.Header, body []byte, sig pmapi.Si
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := bodyPart.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sigHeader message.Header
|
||||
|
||||
sigHeader.SetContentType("application/pgp-signature", map[string]string{"name": "OpenPGP_signature.asc"})
|
||||
sigHeader.SetContentDisposition("attachment", map[string]string{"filename": "OpenPGP_signature"})
|
||||
sigHeader.Set("Content-Description", "OpenPGP digital signature")
|
||||
|
||||
sigPart, err := w.CreatePart(sigHeader)
|
||||
sigPart, err := mw.CreatePart(sigHeader.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -333,11 +332,7 @@ func writeMultipartSignedRFC822(header message.Header, body []byte, sig pmapi.Si
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := sigPart.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := w.Close(); err != nil {
|
||||
if err := mw.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -347,32 +342,22 @@ func writeMultipartSignedRFC822(header message.Header, body []byte, sig pmapi.Si
|
||||
func writeMultipartEncryptedRFC822(header message.Header, body []byte) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
ent, err := message.Read(bytes.NewReader(body))
|
||||
bodyHeader, bodyData, err := readHeaderBody(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entFields := ent.Header.Fields()
|
||||
entFields := bodyHeader.Fields()
|
||||
|
||||
for entFields.Next() {
|
||||
header.Set(entFields.Key(), entFields.Value())
|
||||
}
|
||||
|
||||
w, err := message.CreateWriter(buf, header)
|
||||
if err != nil {
|
||||
if err := textproto.WriteHeader(buf, header.Header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bodyData, err := ioutil.ReadAll(ent.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := w.Write(bodyData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := w.Close(); err != nil {
|
||||
if _, err := buf.Write(bodyData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/message/mocks"
|
||||
tests "github.com/ProtonMail/proton-bridge/test"
|
||||
"github.com/golang/mock/gomock"
|
||||
@ -98,6 +99,31 @@ func TestBuildPlainEncryptedMessage(t *testing.T) {
|
||||
expectBody(contains(`Where do fruits go on vacation? Pear-is!`))
|
||||
}
|
||||
|
||||
func TestBuildPlainEncryptedLatin2Message(t *testing.T) {
|
||||
m := gomock.NewController(t)
|
||||
defer m.Finish()
|
||||
|
||||
b := NewBuilder(1, 1, 1)
|
||||
defer b.Done()
|
||||
|
||||
body := readerToString(getFileReader("pgp-mime-body-plaintext-latin2.eml"))
|
||||
|
||||
kr := tests.MakeKeyRing(t)
|
||||
msg := newTestMessage(t, kr, "messageID", "addressID", "multipart/mixed", body, time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
res, err := b.NewJob(context.Background(), newTestFetcher(m, kr, msg), msg.ID).GetResult()
|
||||
require.NoError(t, err)
|
||||
|
||||
section(t, res).
|
||||
expectContentType(is(`text/plain`)).
|
||||
expectContentTypeParam("charset", is(`iso-8859-2`)).
|
||||
expectDate(is(`Wed, 01 Jan 2020 00:00:00 +0000`)).
|
||||
expectHeader(`Subject`, is(`plain no pubkey no sign`)).
|
||||
expectHeader(`From`, is(`"pm.bridge.qa" <pm.bridge.qa@gmail.com>`)).
|
||||
expectHeader(`To`, is(`schizofrenic@pm.me`)).
|
||||
expectBody(decodesTo("iso-8859-2", "řšřšřš\r\n"))
|
||||
}
|
||||
|
||||
func TestBuildHTMLEncryptedMessage(t *testing.T) {
|
||||
m := gomock.NewController(t)
|
||||
defer m.Finish()
|
||||
@ -127,6 +153,89 @@ func TestBuildHTMLEncryptedMessage(t *testing.T) {
|
||||
expectBody(contains(`Where do boats go when they're sick`))
|
||||
}
|
||||
|
||||
func TestBuildPlainSignedMessage(t *testing.T) {
|
||||
m := gomock.NewController(t)
|
||||
defer m.Finish()
|
||||
|
||||
b := NewBuilder(1, 1, 1)
|
||||
defer b.Done()
|
||||
|
||||
body := readerToString(getFileReader("text_plain.eml"))
|
||||
|
||||
kr := tests.MakeKeyRing(t)
|
||||
sig := tests.MakeKeyRing(t)
|
||||
|
||||
enc, err := kr.Encrypt(crypto.NewPlainMessageFromString(body), sig)
|
||||
require.NoError(t, err)
|
||||
|
||||
arm, err := enc.GetArmored()
|
||||
require.NoError(t, err)
|
||||
|
||||
msg := newRawTestMessage("messageID", "addressID", "multipart/mixed", arm, time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
res, err := b.NewJob(context.Background(), newTestFetcher(m, kr, msg), msg.ID).GetResult()
|
||||
require.NoError(t, err)
|
||||
|
||||
section(t, res).
|
||||
expectContentType(is(`multipart/signed`)).
|
||||
expectContentTypeParam(`micalg`, is(`SHA-256`)). // NOTE: Maybe this is bad... should probably be pgp-sha256
|
||||
expectContentTypeParam(`protocol`, is(`application/pgp-signature`)).
|
||||
expectDate(is(`Wed, 01 Jan 2020 00:00:00 +0000`))
|
||||
|
||||
section(t, res, 1).
|
||||
expectContentType(is(`text/plain`)).
|
||||
expectBody(is(`body`)).
|
||||
expectSection(verifiesAgainst(sig, section(t, res, 2).signature()))
|
||||
|
||||
section(t, res, 2).
|
||||
expectContentType(is(`application/pgp-signature`)).
|
||||
expectContentTypeParam(`name`, is(`OpenPGP_signature.asc`)).
|
||||
expectContentDisposition(is(`attachment`)).
|
||||
expectContentDispositionParam(`filename`, is(`OpenPGP_signature`))
|
||||
}
|
||||
|
||||
func TestBuildPlainSignedBase64Message(t *testing.T) {
|
||||
m := gomock.NewController(t)
|
||||
defer m.Finish()
|
||||
|
||||
b := NewBuilder(1, 1, 1)
|
||||
defer b.Done()
|
||||
|
||||
body := readerToString(getFileReader("text_plain_base64.eml"))
|
||||
|
||||
kr := tests.MakeKeyRing(t)
|
||||
sig := tests.MakeKeyRing(t)
|
||||
|
||||
enc, err := kr.Encrypt(crypto.NewPlainMessageFromString(body), sig)
|
||||
require.NoError(t, err)
|
||||
|
||||
arm, err := enc.GetArmored()
|
||||
require.NoError(t, err)
|
||||
|
||||
msg := newRawTestMessage("messageID", "addressID", "multipart/mixed", arm, time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
res, err := b.NewJob(context.Background(), newTestFetcher(m, kr, msg), msg.ID).GetResult()
|
||||
require.NoError(t, err)
|
||||
|
||||
section(t, res).
|
||||
expectContentType(is(`multipart/signed`)).
|
||||
expectContentTypeParam(`micalg`, is(`SHA-256`)). // NOTE: Maybe this is bad... should probably be pgp-sha256
|
||||
expectContentTypeParam(`protocol`, is(`application/pgp-signature`)).
|
||||
expectDate(is(`Wed, 01 Jan 2020 00:00:00 +0000`))
|
||||
|
||||
section(t, res, 1).
|
||||
expectContentType(is(`text/plain`)).
|
||||
expectTransferEncoding(is(`base64`)).
|
||||
expectBody(is(`body`)).
|
||||
expectSection(verifiesAgainst(sig, section(t, res, 2).signature()))
|
||||
|
||||
section(t, res, 2).
|
||||
expectContentType(is(`application/pgp-signature`)).
|
||||
expectContentTypeParam(`name`, is(`OpenPGP_signature.asc`)).
|
||||
expectContentDisposition(is(`attachment`)).
|
||||
expectContentDispositionParam(`filename`, is(`OpenPGP_signature`))
|
||||
}
|
||||
|
||||
func TestBuildSignedPlainEncryptedMessage(t *testing.T) {
|
||||
m := gomock.NewController(t)
|
||||
defer m.Finish()
|
||||
|
||||
@ -85,11 +85,14 @@ func readHeaderBody(b []byte) (*textproto.Header, []byte, error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
lines := HeaderLines(rawHeader)
|
||||
|
||||
var header textproto.Header
|
||||
|
||||
for _, line := range HeaderLines(rawHeader) {
|
||||
if len(bytes.TrimSpace(line)) > 0 {
|
||||
header.AddRaw(line)
|
||||
// We add lines in reverse so that calling textproto.WriteHeader later writes with the correct order.
|
||||
for i := len(lines) - 1; i >= 0; i-- {
|
||||
if len(bytes.TrimSpace(lines[i])) > 0 {
|
||||
header.AddRaw(lines[i])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,30 +14,30 @@ import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockFetcher is a mock of Fetcher interface
|
||||
// MockFetcher is a mock of Fetcher interface.
|
||||
type MockFetcher struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockFetcherMockRecorder
|
||||
}
|
||||
|
||||
// MockFetcherMockRecorder is the mock recorder for MockFetcher
|
||||
// MockFetcherMockRecorder is the mock recorder for MockFetcher.
|
||||
type MockFetcherMockRecorder struct {
|
||||
mock *MockFetcher
|
||||
}
|
||||
|
||||
// NewMockFetcher creates a new mock instance
|
||||
// NewMockFetcher creates a new mock instance.
|
||||
func NewMockFetcher(ctrl *gomock.Controller) *MockFetcher {
|
||||
mock := &MockFetcher{ctrl: ctrl}
|
||||
mock.recorder = &MockFetcherMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockFetcher) EXPECT() *MockFetcherMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetAttachment mocks base method
|
||||
// GetAttachment mocks base method.
|
||||
func (m *MockFetcher) GetAttachment(arg0 context.Context, arg1 string) (io.ReadCloser, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAttachment", arg0, arg1)
|
||||
@ -46,13 +46,13 @@ func (m *MockFetcher) GetAttachment(arg0 context.Context, arg1 string) (io.ReadC
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetAttachment indicates an expected call of GetAttachment
|
||||
// GetAttachment indicates an expected call of GetAttachment.
|
||||
func (mr *MockFetcherMockRecorder) GetAttachment(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAttachment", reflect.TypeOf((*MockFetcher)(nil).GetAttachment), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetMessage mocks base method
|
||||
// GetMessage mocks base method.
|
||||
func (m *MockFetcher) GetMessage(arg0 context.Context, arg1 string) (*pmapi.Message, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetMessage", arg0, arg1)
|
||||
@ -61,13 +61,13 @@ func (m *MockFetcher) GetMessage(arg0 context.Context, arg1 string) (*pmapi.Mess
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMessage indicates an expected call of GetMessage
|
||||
// GetMessage indicates an expected call of GetMessage.
|
||||
func (mr *MockFetcherMockRecorder) GetMessage(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessage", reflect.TypeOf((*MockFetcher)(nil).GetMessage), arg0, arg1)
|
||||
}
|
||||
|
||||
// KeyRingForAddressID mocks base method
|
||||
// KeyRingForAddressID mocks base method.
|
||||
func (m *MockFetcher) KeyRingForAddressID(arg0 string) (*crypto.KeyRing, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "KeyRingForAddressID", arg0)
|
||||
@ -76,7 +76,7 @@ func (m *MockFetcher) KeyRingForAddressID(arg0 string) (*crypto.KeyRing, error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// KeyRingForAddressID indicates an expected call of KeyRingForAddressID
|
||||
// KeyRingForAddressID indicates an expected call of KeyRingForAddressID.
|
||||
func (mr *MockFetcherMockRecorder) KeyRingForAddressID(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KeyRingForAddressID", reflect.TypeOf((*MockFetcher)(nil).KeyRingForAddressID), arg0)
|
||||
|
||||
8
pkg/message/testdata/pgp-mime-body-plaintext-latin2.eml
vendored
Normal file
8
pkg/message/testdata/pgp-mime-body-plaintext-latin2.eml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
Subject: plain no pubkey no sign
|
||||
From: "pm.bridge.qa" <pm.bridge.qa@gmail.com>
|
||||
To: schizofrenic@pm.me
|
||||
Message-ID: <564b9c7c-91eb-6508-107a-35108f383a44@gmail.com>
|
||||
Content-Type: text/plain; charset=iso-8859-2; format=flowed
|
||||
Content-Language: en-US
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
5
pkg/message/testdata/text_plain_base64.eml
vendored
Normal file
5
pkg/message/testdata/text_plain_base64.eml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
From: Sender <sender@pm.me>
|
||||
To: Receiver <receiver@pm.me>
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
Ym9keQ==
|
||||
@ -217,3 +217,13 @@ func randomString(length int) string {
|
||||
|
||||
return base64.StdEncoding.EncodeToString(noise)[:length]
|
||||
}
|
||||
|
||||
func (c *client) GetCurrentAuth() *Auth {
|
||||
return &Auth{
|
||||
UserID: c.user.ID,
|
||||
AuthRefresh: AuthRefresh{
|
||||
UID: c.uid,
|
||||
RefreshToken: c.ref,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,6 +59,7 @@ func newManager(cfg Config) *manager {
|
||||
// wrapped in JSON. If error is returned, `handleRequestFailure` is called,
|
||||
// otherwise `handleRequestSuccess` is called.
|
||||
m.rc.SetError(&Error{})
|
||||
m.rc.OnAfterResponse(updateTime)
|
||||
m.rc.OnAfterResponse(m.catchAPIError)
|
||||
m.rc.OnAfterResponse(m.handleRequestSuccess)
|
||||
m.rc.OnError(m.handleRequestFailure)
|
||||
|
||||
@ -17,42 +17,42 @@ import (
|
||||
logrus "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// MockClient is a mock of Client interface
|
||||
// MockClient is a mock of Client interface.
|
||||
type MockClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockClientMockRecorder
|
||||
}
|
||||
|
||||
// MockClientMockRecorder is the mock recorder for MockClient
|
||||
// MockClientMockRecorder is the mock recorder for MockClient.
|
||||
type MockClientMockRecorder struct {
|
||||
mock *MockClient
|
||||
}
|
||||
|
||||
// NewMockClient creates a new mock instance
|
||||
// NewMockClient creates a new mock instance.
|
||||
func NewMockClient(ctrl *gomock.Controller) *MockClient {
|
||||
mock := &MockClient{ctrl: ctrl}
|
||||
mock.recorder = &MockClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockClient) EXPECT() *MockClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AddAuthRefreshHandler mocks base method
|
||||
// AddAuthRefreshHandler mocks base method.
|
||||
func (m *MockClient) AddAuthRefreshHandler(arg0 pmapi.AuthRefreshHandler) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "AddAuthRefreshHandler", arg0)
|
||||
}
|
||||
|
||||
// AddAuthRefreshHandler indicates an expected call of AddAuthRefreshHandler
|
||||
// AddAuthRefreshHandler indicates an expected call of AddAuthRefreshHandler.
|
||||
func (mr *MockClientMockRecorder) AddAuthRefreshHandler(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAuthRefreshHandler", reflect.TypeOf((*MockClient)(nil).AddAuthRefreshHandler), arg0)
|
||||
}
|
||||
|
||||
// Addresses mocks base method
|
||||
// Addresses mocks base method.
|
||||
func (m *MockClient) Addresses() pmapi.AddressList {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Addresses")
|
||||
@ -60,13 +60,13 @@ func (m *MockClient) Addresses() pmapi.AddressList {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Addresses indicates an expected call of Addresses
|
||||
// Addresses indicates an expected call of Addresses.
|
||||
func (mr *MockClientMockRecorder) Addresses() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Addresses", reflect.TypeOf((*MockClient)(nil).Addresses))
|
||||
}
|
||||
|
||||
// Auth2FA mocks base method
|
||||
// Auth2FA mocks base method.
|
||||
func (m *MockClient) Auth2FA(arg0 context.Context, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Auth2FA", arg0, arg1)
|
||||
@ -74,13 +74,13 @@ func (m *MockClient) Auth2FA(arg0 context.Context, arg1 string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Auth2FA indicates an expected call of Auth2FA
|
||||
// Auth2FA indicates an expected call of Auth2FA.
|
||||
func (mr *MockClientMockRecorder) Auth2FA(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Auth2FA", reflect.TypeOf((*MockClient)(nil).Auth2FA), arg0, arg1)
|
||||
}
|
||||
|
||||
// AuthDelete mocks base method
|
||||
// AuthDelete mocks base method.
|
||||
func (m *MockClient) AuthDelete(arg0 context.Context) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AuthDelete", arg0)
|
||||
@ -88,13 +88,13 @@ func (m *MockClient) AuthDelete(arg0 context.Context) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AuthDelete indicates an expected call of AuthDelete
|
||||
// AuthDelete indicates an expected call of AuthDelete.
|
||||
func (mr *MockClientMockRecorder) AuthDelete(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthDelete", reflect.TypeOf((*MockClient)(nil).AuthDelete), arg0)
|
||||
}
|
||||
|
||||
// AuthSalt mocks base method
|
||||
// AuthSalt mocks base method.
|
||||
func (m *MockClient) AuthSalt(arg0 context.Context) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AuthSalt", arg0)
|
||||
@ -103,13 +103,13 @@ func (m *MockClient) AuthSalt(arg0 context.Context) (string, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AuthSalt indicates an expected call of AuthSalt
|
||||
// AuthSalt indicates an expected call of AuthSalt.
|
||||
func (mr *MockClientMockRecorder) AuthSalt(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthSalt", reflect.TypeOf((*MockClient)(nil).AuthSalt), arg0)
|
||||
}
|
||||
|
||||
// CountMessages mocks base method
|
||||
// CountMessages mocks base method.
|
||||
func (m *MockClient) CountMessages(arg0 context.Context, arg1 string) ([]*pmapi.MessagesCount, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CountMessages", arg0, arg1)
|
||||
@ -118,13 +118,13 @@ func (m *MockClient) CountMessages(arg0 context.Context, arg1 string) ([]*pmapi.
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CountMessages indicates an expected call of CountMessages
|
||||
// CountMessages indicates an expected call of CountMessages.
|
||||
func (mr *MockClientMockRecorder) CountMessages(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CountMessages", reflect.TypeOf((*MockClient)(nil).CountMessages), arg0, arg1)
|
||||
}
|
||||
|
||||
// CreateAttachment mocks base method
|
||||
// CreateAttachment mocks base method.
|
||||
func (m *MockClient) CreateAttachment(arg0 context.Context, arg1 *pmapi.Attachment, arg2, arg3 io.Reader) (*pmapi.Attachment, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateAttachment", arg0, arg1, arg2, arg3)
|
||||
@ -133,13 +133,13 @@ func (m *MockClient) CreateAttachment(arg0 context.Context, arg1 *pmapi.Attachme
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateAttachment indicates an expected call of CreateAttachment
|
||||
// CreateAttachment indicates an expected call of CreateAttachment.
|
||||
func (mr *MockClientMockRecorder) CreateAttachment(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAttachment", reflect.TypeOf((*MockClient)(nil).CreateAttachment), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// CreateDraft mocks base method
|
||||
// CreateDraft mocks base method.
|
||||
func (m *MockClient) CreateDraft(arg0 context.Context, arg1 *pmapi.Message, arg2 string, arg3 int) (*pmapi.Message, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateDraft", arg0, arg1, arg2, arg3)
|
||||
@ -148,13 +148,13 @@ func (m *MockClient) CreateDraft(arg0 context.Context, arg1 *pmapi.Message, arg2
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateDraft indicates an expected call of CreateDraft
|
||||
// CreateDraft indicates an expected call of CreateDraft.
|
||||
func (mr *MockClientMockRecorder) CreateDraft(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateDraft", reflect.TypeOf((*MockClient)(nil).CreateDraft), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// CreateLabel mocks base method
|
||||
// CreateLabel mocks base method.
|
||||
func (m *MockClient) CreateLabel(arg0 context.Context, arg1 *pmapi.Label) (*pmapi.Label, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateLabel", arg0, arg1)
|
||||
@ -163,13 +163,13 @@ func (m *MockClient) CreateLabel(arg0 context.Context, arg1 *pmapi.Label) (*pmap
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateLabel indicates an expected call of CreateLabel
|
||||
// CreateLabel indicates an expected call of CreateLabel.
|
||||
func (mr *MockClientMockRecorder) CreateLabel(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateLabel", reflect.TypeOf((*MockClient)(nil).CreateLabel), arg0, arg1)
|
||||
}
|
||||
|
||||
// CurrentUser mocks base method
|
||||
// CurrentUser mocks base method.
|
||||
func (m *MockClient) CurrentUser(arg0 context.Context) (*pmapi.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CurrentUser", arg0)
|
||||
@ -178,13 +178,13 @@ func (m *MockClient) CurrentUser(arg0 context.Context) (*pmapi.User, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CurrentUser indicates an expected call of CurrentUser
|
||||
// CurrentUser indicates an expected call of CurrentUser.
|
||||
func (mr *MockClientMockRecorder) CurrentUser(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentUser", reflect.TypeOf((*MockClient)(nil).CurrentUser), arg0)
|
||||
}
|
||||
|
||||
// DecryptAndVerifyCards mocks base method
|
||||
// DecryptAndVerifyCards mocks base method.
|
||||
func (m *MockClient) DecryptAndVerifyCards(arg0 []pmapi.Card) ([]pmapi.Card, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DecryptAndVerifyCards", arg0)
|
||||
@ -193,13 +193,13 @@ func (m *MockClient) DecryptAndVerifyCards(arg0 []pmapi.Card) ([]pmapi.Card, err
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// DecryptAndVerifyCards indicates an expected call of DecryptAndVerifyCards
|
||||
// DecryptAndVerifyCards indicates an expected call of DecryptAndVerifyCards.
|
||||
func (mr *MockClientMockRecorder) DecryptAndVerifyCards(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecryptAndVerifyCards", reflect.TypeOf((*MockClient)(nil).DecryptAndVerifyCards), arg0)
|
||||
}
|
||||
|
||||
// DeleteLabel mocks base method
|
||||
// DeleteLabel mocks base method.
|
||||
func (m *MockClient) DeleteLabel(arg0 context.Context, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteLabel", arg0, arg1)
|
||||
@ -207,13 +207,13 @@ func (m *MockClient) DeleteLabel(arg0 context.Context, arg1 string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteLabel indicates an expected call of DeleteLabel
|
||||
// DeleteLabel indicates an expected call of DeleteLabel.
|
||||
func (mr *MockClientMockRecorder) DeleteLabel(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteLabel", reflect.TypeOf((*MockClient)(nil).DeleteLabel), arg0, arg1)
|
||||
}
|
||||
|
||||
// DeleteMessages mocks base method
|
||||
// DeleteMessages mocks base method.
|
||||
func (m *MockClient) DeleteMessages(arg0 context.Context, arg1 []string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteMessages", arg0, arg1)
|
||||
@ -221,13 +221,13 @@ func (m *MockClient) DeleteMessages(arg0 context.Context, arg1 []string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteMessages indicates an expected call of DeleteMessages
|
||||
// DeleteMessages indicates an expected call of DeleteMessages.
|
||||
func (mr *MockClientMockRecorder) DeleteMessages(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteMessages", reflect.TypeOf((*MockClient)(nil).DeleteMessages), arg0, arg1)
|
||||
}
|
||||
|
||||
// EmptyFolder mocks base method
|
||||
// EmptyFolder mocks base method.
|
||||
func (m *MockClient) EmptyFolder(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EmptyFolder", arg0, arg1, arg2)
|
||||
@ -235,13 +235,13 @@ func (m *MockClient) EmptyFolder(arg0 context.Context, arg1, arg2 string) error
|
||||
return ret0
|
||||
}
|
||||
|
||||
// EmptyFolder indicates an expected call of EmptyFolder
|
||||
// EmptyFolder indicates an expected call of EmptyFolder.
|
||||
func (mr *MockClientMockRecorder) EmptyFolder(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EmptyFolder", reflect.TypeOf((*MockClient)(nil).EmptyFolder), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// GetAddresses mocks base method
|
||||
// GetAddresses mocks base method.
|
||||
func (m *MockClient) GetAddresses(arg0 context.Context) (pmapi.AddressList, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAddresses", arg0)
|
||||
@ -250,13 +250,13 @@ func (m *MockClient) GetAddresses(arg0 context.Context) (pmapi.AddressList, erro
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetAddresses indicates an expected call of GetAddresses
|
||||
// GetAddresses indicates an expected call of GetAddresses.
|
||||
func (mr *MockClientMockRecorder) GetAddresses(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAddresses", reflect.TypeOf((*MockClient)(nil).GetAddresses), arg0)
|
||||
}
|
||||
|
||||
// GetAttachment mocks base method
|
||||
// GetAttachment mocks base method.
|
||||
func (m *MockClient) GetAttachment(arg0 context.Context, arg1 string) (io.ReadCloser, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAttachment", arg0, arg1)
|
||||
@ -265,13 +265,13 @@ func (m *MockClient) GetAttachment(arg0 context.Context, arg1 string) (io.ReadCl
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetAttachment indicates an expected call of GetAttachment
|
||||
// GetAttachment indicates an expected call of GetAttachment.
|
||||
func (mr *MockClientMockRecorder) GetAttachment(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAttachment", reflect.TypeOf((*MockClient)(nil).GetAttachment), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetContactByID mocks base method
|
||||
// GetContactByID mocks base method.
|
||||
func (m *MockClient) GetContactByID(arg0 context.Context, arg1 string) (pmapi.Contact, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetContactByID", arg0, arg1)
|
||||
@ -280,13 +280,13 @@ func (m *MockClient) GetContactByID(arg0 context.Context, arg1 string) (pmapi.Co
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetContactByID indicates an expected call of GetContactByID
|
||||
// GetContactByID indicates an expected call of GetContactByID.
|
||||
func (mr *MockClientMockRecorder) GetContactByID(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetContactByID", reflect.TypeOf((*MockClient)(nil).GetContactByID), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetContactEmailByEmail mocks base method
|
||||
// GetContactEmailByEmail mocks base method.
|
||||
func (m *MockClient) GetContactEmailByEmail(arg0 context.Context, arg1 string, arg2, arg3 int) ([]pmapi.ContactEmail, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetContactEmailByEmail", arg0, arg1, arg2, arg3)
|
||||
@ -295,13 +295,13 @@ func (m *MockClient) GetContactEmailByEmail(arg0 context.Context, arg1 string, a
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetContactEmailByEmail indicates an expected call of GetContactEmailByEmail
|
||||
// GetContactEmailByEmail indicates an expected call of GetContactEmailByEmail.
|
||||
func (mr *MockClientMockRecorder) GetContactEmailByEmail(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetContactEmailByEmail", reflect.TypeOf((*MockClient)(nil).GetContactEmailByEmail), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// GetEvent mocks base method
|
||||
// GetEvent mocks base method.
|
||||
func (m *MockClient) GetEvent(arg0 context.Context, arg1 string) (*pmapi.Event, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetEvent", arg0, arg1)
|
||||
@ -310,13 +310,13 @@ func (m *MockClient) GetEvent(arg0 context.Context, arg1 string) (*pmapi.Event,
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetEvent indicates an expected call of GetEvent
|
||||
// GetEvent indicates an expected call of GetEvent.
|
||||
func (mr *MockClientMockRecorder) GetEvent(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEvent", reflect.TypeOf((*MockClient)(nil).GetEvent), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetMailSettings mocks base method
|
||||
// GetMailSettings mocks base method.
|
||||
func (m *MockClient) GetMailSettings(arg0 context.Context) (pmapi.MailSettings, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetMailSettings", arg0)
|
||||
@ -325,13 +325,13 @@ func (m *MockClient) GetMailSettings(arg0 context.Context) (pmapi.MailSettings,
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMailSettings indicates an expected call of GetMailSettings
|
||||
// GetMailSettings indicates an expected call of GetMailSettings.
|
||||
func (mr *MockClientMockRecorder) GetMailSettings(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMailSettings", reflect.TypeOf((*MockClient)(nil).GetMailSettings), arg0)
|
||||
}
|
||||
|
||||
// GetMessage mocks base method
|
||||
// GetMessage mocks base method.
|
||||
func (m *MockClient) GetMessage(arg0 context.Context, arg1 string) (*pmapi.Message, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetMessage", arg0, arg1)
|
||||
@ -340,13 +340,13 @@ func (m *MockClient) GetMessage(arg0 context.Context, arg1 string) (*pmapi.Messa
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMessage indicates an expected call of GetMessage
|
||||
// GetMessage indicates an expected call of GetMessage.
|
||||
func (mr *MockClientMockRecorder) GetMessage(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessage", reflect.TypeOf((*MockClient)(nil).GetMessage), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetPublicKeysForEmail mocks base method
|
||||
// GetPublicKeysForEmail mocks base method.
|
||||
func (m *MockClient) GetPublicKeysForEmail(arg0 context.Context, arg1 string) ([]pmapi.PublicKey, bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetPublicKeysForEmail", arg0, arg1)
|
||||
@ -356,13 +356,13 @@ func (m *MockClient) GetPublicKeysForEmail(arg0 context.Context, arg1 string) ([
|
||||
return ret0, ret1, ret2
|
||||
}
|
||||
|
||||
// GetPublicKeysForEmail indicates an expected call of GetPublicKeysForEmail
|
||||
// GetPublicKeysForEmail indicates an expected call of GetPublicKeysForEmail.
|
||||
func (mr *MockClientMockRecorder) GetPublicKeysForEmail(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPublicKeysForEmail", reflect.TypeOf((*MockClient)(nil).GetPublicKeysForEmail), arg0, arg1)
|
||||
}
|
||||
|
||||
// Import mocks base method
|
||||
// Import mocks base method.
|
||||
func (m *MockClient) Import(arg0 context.Context, arg1 pmapi.ImportMsgReqs) ([]*pmapi.ImportMsgRes, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Import", arg0, arg1)
|
||||
@ -371,13 +371,13 @@ func (m *MockClient) Import(arg0 context.Context, arg1 pmapi.ImportMsgReqs) ([]*
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Import indicates an expected call of Import
|
||||
// Import indicates an expected call of Import.
|
||||
func (mr *MockClientMockRecorder) Import(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Import", reflect.TypeOf((*MockClient)(nil).Import), arg0, arg1)
|
||||
}
|
||||
|
||||
// IsUnlocked mocks base method
|
||||
// IsUnlocked mocks base method.
|
||||
func (m *MockClient) IsUnlocked() bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsUnlocked")
|
||||
@ -385,13 +385,13 @@ func (m *MockClient) IsUnlocked() bool {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IsUnlocked indicates an expected call of IsUnlocked
|
||||
// IsUnlocked indicates an expected call of IsUnlocked.
|
||||
func (mr *MockClientMockRecorder) IsUnlocked() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsUnlocked", reflect.TypeOf((*MockClient)(nil).IsUnlocked))
|
||||
}
|
||||
|
||||
// KeyRingForAddressID mocks base method
|
||||
// KeyRingForAddressID mocks base method.
|
||||
func (m *MockClient) KeyRingForAddressID(arg0 string) (*crypto.KeyRing, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "KeyRingForAddressID", arg0)
|
||||
@ -400,13 +400,13 @@ func (m *MockClient) KeyRingForAddressID(arg0 string) (*crypto.KeyRing, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// KeyRingForAddressID indicates an expected call of KeyRingForAddressID
|
||||
// KeyRingForAddressID indicates an expected call of KeyRingForAddressID.
|
||||
func (mr *MockClientMockRecorder) KeyRingForAddressID(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KeyRingForAddressID", reflect.TypeOf((*MockClient)(nil).KeyRingForAddressID), arg0)
|
||||
}
|
||||
|
||||
// LabelMessages mocks base method
|
||||
// LabelMessages mocks base method.
|
||||
func (m *MockClient) LabelMessages(arg0 context.Context, arg1 []string, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LabelMessages", arg0, arg1, arg2)
|
||||
@ -414,13 +414,13 @@ func (m *MockClient) LabelMessages(arg0 context.Context, arg1 []string, arg2 str
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LabelMessages indicates an expected call of LabelMessages
|
||||
// LabelMessages indicates an expected call of LabelMessages.
|
||||
func (mr *MockClientMockRecorder) LabelMessages(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LabelMessages", reflect.TypeOf((*MockClient)(nil).LabelMessages), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// ListLabels mocks base method
|
||||
// ListLabels mocks base method.
|
||||
func (m *MockClient) ListLabels(arg0 context.Context) ([]*pmapi.Label, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ListLabels", arg0)
|
||||
@ -429,13 +429,13 @@ func (m *MockClient) ListLabels(arg0 context.Context) ([]*pmapi.Label, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ListLabels indicates an expected call of ListLabels
|
||||
// ListLabels indicates an expected call of ListLabels.
|
||||
func (mr *MockClientMockRecorder) ListLabels(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListLabels", reflect.TypeOf((*MockClient)(nil).ListLabels), arg0)
|
||||
}
|
||||
|
||||
// ListMessages mocks base method
|
||||
// ListMessages mocks base method.
|
||||
func (m *MockClient) ListMessages(arg0 context.Context, arg1 *pmapi.MessagesFilter) ([]*pmapi.Message, int, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ListMessages", arg0, arg1)
|
||||
@ -445,13 +445,13 @@ func (m *MockClient) ListMessages(arg0 context.Context, arg1 *pmapi.MessagesFilt
|
||||
return ret0, ret1, ret2
|
||||
}
|
||||
|
||||
// ListMessages indicates an expected call of ListMessages
|
||||
// ListMessages indicates an expected call of ListMessages.
|
||||
func (mr *MockClientMockRecorder) ListMessages(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListMessages", reflect.TypeOf((*MockClient)(nil).ListMessages), arg0, arg1)
|
||||
}
|
||||
|
||||
// MarkMessagesRead mocks base method
|
||||
// MarkMessagesRead mocks base method.
|
||||
func (m *MockClient) MarkMessagesRead(arg0 context.Context, arg1 []string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MarkMessagesRead", arg0, arg1)
|
||||
@ -459,13 +459,13 @@ func (m *MockClient) MarkMessagesRead(arg0 context.Context, arg1 []string) error
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MarkMessagesRead indicates an expected call of MarkMessagesRead
|
||||
// MarkMessagesRead indicates an expected call of MarkMessagesRead.
|
||||
func (mr *MockClientMockRecorder) MarkMessagesRead(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MarkMessagesRead", reflect.TypeOf((*MockClient)(nil).MarkMessagesRead), arg0, arg1)
|
||||
}
|
||||
|
||||
// MarkMessagesUnread mocks base method
|
||||
// MarkMessagesUnread mocks base method.
|
||||
func (m *MockClient) MarkMessagesUnread(arg0 context.Context, arg1 []string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MarkMessagesUnread", arg0, arg1)
|
||||
@ -473,13 +473,13 @@ func (m *MockClient) MarkMessagesUnread(arg0 context.Context, arg1 []string) err
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MarkMessagesUnread indicates an expected call of MarkMessagesUnread
|
||||
// MarkMessagesUnread indicates an expected call of MarkMessagesUnread.
|
||||
func (mr *MockClientMockRecorder) MarkMessagesUnread(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MarkMessagesUnread", reflect.TypeOf((*MockClient)(nil).MarkMessagesUnread), arg0, arg1)
|
||||
}
|
||||
|
||||
// ReloadKeys mocks base method
|
||||
// ReloadKeys mocks base method.
|
||||
func (m *MockClient) ReloadKeys(arg0 context.Context, arg1 []byte) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ReloadKeys", arg0, arg1)
|
||||
@ -487,13 +487,13 @@ func (m *MockClient) ReloadKeys(arg0 context.Context, arg1 []byte) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ReloadKeys indicates an expected call of ReloadKeys
|
||||
// ReloadKeys indicates an expected call of ReloadKeys.
|
||||
func (mr *MockClientMockRecorder) ReloadKeys(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReloadKeys", reflect.TypeOf((*MockClient)(nil).ReloadKeys), arg0, arg1)
|
||||
}
|
||||
|
||||
// ReorderAddresses mocks base method
|
||||
// ReorderAddresses mocks base method.
|
||||
func (m *MockClient) ReorderAddresses(arg0 context.Context, arg1 []string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ReorderAddresses", arg0, arg1)
|
||||
@ -501,13 +501,13 @@ func (m *MockClient) ReorderAddresses(arg0 context.Context, arg1 []string) error
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ReorderAddresses indicates an expected call of ReorderAddresses
|
||||
// ReorderAddresses indicates an expected call of ReorderAddresses.
|
||||
func (mr *MockClientMockRecorder) ReorderAddresses(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReorderAddresses", reflect.TypeOf((*MockClient)(nil).ReorderAddresses), arg0, arg1)
|
||||
}
|
||||
|
||||
// SendMessage mocks base method
|
||||
// SendMessage mocks base method.
|
||||
func (m *MockClient) SendMessage(arg0 context.Context, arg1 string, arg2 *pmapi.SendMessageReq) (*pmapi.Message, *pmapi.Message, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SendMessage", arg0, arg1, arg2)
|
||||
@ -517,13 +517,13 @@ func (m *MockClient) SendMessage(arg0 context.Context, arg1 string, arg2 *pmapi.
|
||||
return ret0, ret1, ret2
|
||||
}
|
||||
|
||||
// SendMessage indicates an expected call of SendMessage
|
||||
// SendMessage indicates an expected call of SendMessage.
|
||||
func (mr *MockClientMockRecorder) SendMessage(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMessage", reflect.TypeOf((*MockClient)(nil).SendMessage), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// UnlabelMessages mocks base method
|
||||
// UnlabelMessages mocks base method.
|
||||
func (m *MockClient) UnlabelMessages(arg0 context.Context, arg1 []string, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UnlabelMessages", arg0, arg1, arg2)
|
||||
@ -531,13 +531,13 @@ func (m *MockClient) UnlabelMessages(arg0 context.Context, arg1 []string, arg2 s
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UnlabelMessages indicates an expected call of UnlabelMessages
|
||||
// UnlabelMessages indicates an expected call of UnlabelMessages.
|
||||
func (mr *MockClientMockRecorder) UnlabelMessages(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnlabelMessages", reflect.TypeOf((*MockClient)(nil).UnlabelMessages), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// Unlock mocks base method
|
||||
// Unlock mocks base method.
|
||||
func (m *MockClient) Unlock(arg0 context.Context, arg1 []byte) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Unlock", arg0, arg1)
|
||||
@ -545,13 +545,13 @@ func (m *MockClient) Unlock(arg0 context.Context, arg1 []byte) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Unlock indicates an expected call of Unlock
|
||||
// Unlock indicates an expected call of Unlock.
|
||||
func (mr *MockClientMockRecorder) Unlock(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unlock", reflect.TypeOf((*MockClient)(nil).Unlock), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdateLabel mocks base method
|
||||
// UpdateLabel mocks base method.
|
||||
func (m *MockClient) UpdateLabel(arg0 context.Context, arg1 *pmapi.Label) (*pmapi.Label, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateLabel", arg0, arg1)
|
||||
@ -560,13 +560,13 @@ func (m *MockClient) UpdateLabel(arg0 context.Context, arg1 *pmapi.Label) (*pmap
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateLabel indicates an expected call of UpdateLabel
|
||||
// UpdateLabel indicates an expected call of UpdateLabel.
|
||||
func (mr *MockClientMockRecorder) UpdateLabel(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateLabel", reflect.TypeOf((*MockClient)(nil).UpdateLabel), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdateUser mocks base method
|
||||
// UpdateUser mocks base method.
|
||||
func (m *MockClient) UpdateUser(arg0 context.Context) (*pmapi.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateUser", arg0)
|
||||
@ -575,72 +575,72 @@ func (m *MockClient) UpdateUser(arg0 context.Context) (*pmapi.User, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateUser indicates an expected call of UpdateUser
|
||||
// UpdateUser indicates an expected call of UpdateUser.
|
||||
func (mr *MockClientMockRecorder) UpdateUser(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUser", reflect.TypeOf((*MockClient)(nil).UpdateUser), arg0)
|
||||
}
|
||||
|
||||
// MockManager is a mock of Manager interface
|
||||
// MockManager is a mock of Manager interface.
|
||||
type MockManager struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockManagerMockRecorder
|
||||
}
|
||||
|
||||
// MockManagerMockRecorder is the mock recorder for MockManager
|
||||
// MockManagerMockRecorder is the mock recorder for MockManager.
|
||||
type MockManagerMockRecorder struct {
|
||||
mock *MockManager
|
||||
}
|
||||
|
||||
// NewMockManager creates a new mock instance
|
||||
// NewMockManager creates a new mock instance.
|
||||
func NewMockManager(ctrl *gomock.Controller) *MockManager {
|
||||
mock := &MockManager{ctrl: ctrl}
|
||||
mock.recorder = &MockManagerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockManager) EXPECT() *MockManagerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AddConnectionObserver mocks base method
|
||||
// AddConnectionObserver mocks base method.
|
||||
func (m *MockManager) AddConnectionObserver(arg0 pmapi.ConnectionObserver) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "AddConnectionObserver", arg0)
|
||||
}
|
||||
|
||||
// AddConnectionObserver indicates an expected call of AddConnectionObserver
|
||||
// AddConnectionObserver indicates an expected call of AddConnectionObserver.
|
||||
func (mr *MockManagerMockRecorder) AddConnectionObserver(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddConnectionObserver", reflect.TypeOf((*MockManager)(nil).AddConnectionObserver), arg0)
|
||||
}
|
||||
|
||||
// AllowProxy mocks base method
|
||||
// AllowProxy mocks base method.
|
||||
func (m *MockManager) AllowProxy() {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "AllowProxy")
|
||||
}
|
||||
|
||||
// AllowProxy indicates an expected call of AllowProxy
|
||||
// AllowProxy indicates an expected call of AllowProxy.
|
||||
func (mr *MockManagerMockRecorder) AllowProxy() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllowProxy", reflect.TypeOf((*MockManager)(nil).AllowProxy))
|
||||
}
|
||||
|
||||
// DisallowProxy mocks base method
|
||||
// DisallowProxy mocks base method.
|
||||
func (m *MockManager) DisallowProxy() {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "DisallowProxy")
|
||||
}
|
||||
|
||||
// DisallowProxy indicates an expected call of DisallowProxy
|
||||
// DisallowProxy indicates an expected call of DisallowProxy.
|
||||
func (mr *MockManagerMockRecorder) DisallowProxy() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DisallowProxy", reflect.TypeOf((*MockManager)(nil).DisallowProxy))
|
||||
}
|
||||
|
||||
// DownloadAndVerify mocks base method
|
||||
// DownloadAndVerify mocks base method.
|
||||
func (m *MockManager) DownloadAndVerify(arg0 *crypto.KeyRing, arg1, arg2 string) ([]byte, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DownloadAndVerify", arg0, arg1, arg2)
|
||||
@ -649,13 +649,13 @@ func (m *MockManager) DownloadAndVerify(arg0 *crypto.KeyRing, arg1, arg2 string)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// DownloadAndVerify indicates an expected call of DownloadAndVerify
|
||||
// DownloadAndVerify indicates an expected call of DownloadAndVerify.
|
||||
func (mr *MockManagerMockRecorder) DownloadAndVerify(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DownloadAndVerify", reflect.TypeOf((*MockManager)(nil).DownloadAndVerify), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// NewClient mocks base method
|
||||
// NewClient mocks base method.
|
||||
func (m *MockManager) NewClient(arg0, arg1, arg2 string, arg3 time.Time) pmapi.Client {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NewClient", arg0, arg1, arg2, arg3)
|
||||
@ -663,13 +663,13 @@ func (m *MockManager) NewClient(arg0, arg1, arg2 string, arg3 time.Time) pmapi.C
|
||||
return ret0
|
||||
}
|
||||
|
||||
// NewClient indicates an expected call of NewClient
|
||||
// NewClient indicates an expected call of NewClient.
|
||||
func (mr *MockManagerMockRecorder) NewClient(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewClient", reflect.TypeOf((*MockManager)(nil).NewClient), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// NewClientWithLogin mocks base method
|
||||
// NewClientWithLogin mocks base method.
|
||||
func (m *MockManager) NewClientWithLogin(arg0 context.Context, arg1 string, arg2 []byte) (pmapi.Client, *pmapi.Auth, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NewClientWithLogin", arg0, arg1, arg2)
|
||||
@ -679,13 +679,13 @@ func (m *MockManager) NewClientWithLogin(arg0 context.Context, arg1 string, arg2
|
||||
return ret0, ret1, ret2
|
||||
}
|
||||
|
||||
// NewClientWithLogin indicates an expected call of NewClientWithLogin
|
||||
// NewClientWithLogin indicates an expected call of NewClientWithLogin.
|
||||
func (mr *MockManagerMockRecorder) NewClientWithLogin(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewClientWithLogin", reflect.TypeOf((*MockManager)(nil).NewClientWithLogin), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// NewClientWithRefresh mocks base method
|
||||
// NewClientWithRefresh mocks base method.
|
||||
func (m *MockManager) NewClientWithRefresh(arg0 context.Context, arg1, arg2 string) (pmapi.Client, *pmapi.AuthRefresh, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NewClientWithRefresh", arg0, arg1, arg2)
|
||||
@ -695,13 +695,13 @@ func (m *MockManager) NewClientWithRefresh(arg0 context.Context, arg1, arg2 stri
|
||||
return ret0, ret1, ret2
|
||||
}
|
||||
|
||||
// NewClientWithRefresh indicates an expected call of NewClientWithRefresh
|
||||
// NewClientWithRefresh indicates an expected call of NewClientWithRefresh.
|
||||
func (mr *MockManagerMockRecorder) NewClientWithRefresh(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewClientWithRefresh", reflect.TypeOf((*MockManager)(nil).NewClientWithRefresh), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// ReportBug mocks base method
|
||||
// ReportBug mocks base method.
|
||||
func (m *MockManager) ReportBug(arg0 context.Context, arg1 pmapi.ReportBugReq) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ReportBug", arg0, arg1)
|
||||
@ -709,13 +709,13 @@ func (m *MockManager) ReportBug(arg0 context.Context, arg1 pmapi.ReportBugReq) e
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ReportBug indicates an expected call of ReportBug
|
||||
// ReportBug indicates an expected call of ReportBug.
|
||||
func (mr *MockManagerMockRecorder) ReportBug(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportBug", reflect.TypeOf((*MockManager)(nil).ReportBug), arg0, arg1)
|
||||
}
|
||||
|
||||
// SendSimpleMetric mocks base method
|
||||
// SendSimpleMetric mocks base method.
|
||||
func (m *MockManager) SendSimpleMetric(arg0 context.Context, arg1, arg2, arg3 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SendSimpleMetric", arg0, arg1, arg2, arg3)
|
||||
@ -723,55 +723,55 @@ func (m *MockManager) SendSimpleMetric(arg0 context.Context, arg1, arg2, arg3 st
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SendSimpleMetric indicates an expected call of SendSimpleMetric
|
||||
// SendSimpleMetric indicates an expected call of SendSimpleMetric.
|
||||
func (mr *MockManagerMockRecorder) SendSimpleMetric(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendSimpleMetric", reflect.TypeOf((*MockManager)(nil).SendSimpleMetric), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// SetCookieJar mocks base method
|
||||
// SetCookieJar mocks base method.
|
||||
func (m *MockManager) SetCookieJar(arg0 http.CookieJar) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetCookieJar", arg0)
|
||||
}
|
||||
|
||||
// SetCookieJar indicates an expected call of SetCookieJar
|
||||
// SetCookieJar indicates an expected call of SetCookieJar.
|
||||
func (mr *MockManagerMockRecorder) SetCookieJar(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCookieJar", reflect.TypeOf((*MockManager)(nil).SetCookieJar), arg0)
|
||||
}
|
||||
|
||||
// SetLogging mocks base method
|
||||
// SetLogging mocks base method.
|
||||
func (m *MockManager) SetLogging(arg0 *logrus.Entry, arg1 bool) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetLogging", arg0, arg1)
|
||||
}
|
||||
|
||||
// SetLogging indicates an expected call of SetLogging
|
||||
// SetLogging indicates an expected call of SetLogging.
|
||||
func (mr *MockManagerMockRecorder) SetLogging(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogging", reflect.TypeOf((*MockManager)(nil).SetLogging), arg0, arg1)
|
||||
}
|
||||
|
||||
// SetRetryCount mocks base method
|
||||
// SetRetryCount mocks base method.
|
||||
func (m *MockManager) SetRetryCount(arg0 int) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetRetryCount", arg0)
|
||||
}
|
||||
|
||||
// SetRetryCount indicates an expected call of SetRetryCount
|
||||
// SetRetryCount indicates an expected call of SetRetryCount.
|
||||
func (mr *MockManagerMockRecorder) SetRetryCount(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetRetryCount", reflect.TypeOf((*MockManager)(nil).SetRetryCount), arg0)
|
||||
}
|
||||
|
||||
// SetTransport mocks base method
|
||||
// SetTransport mocks base method.
|
||||
func (m *MockManager) SetTransport(arg0 http.RoundTripper) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetTransport", arg0)
|
||||
}
|
||||
|
||||
// SetTransport indicates an expected call of SetTransport
|
||||
// SetTransport indicates an expected call of SetTransport.
|
||||
func (mr *MockManagerMockRecorder) SetTransport(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTransport", reflect.TypeOf((*MockManager)(nil).SetTransport), arg0)
|
||||
|
||||
@ -23,6 +23,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -71,6 +72,16 @@ func (m *manager) catchAPIError(_ *resty.Client, res *resty.Response) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func updateTime(_ *resty.Client, res *resty.Response) error {
|
||||
if date, err := time.Parse(time.RFC1123, res.Header().Get("Date")); err != nil {
|
||||
log.WithError(err).Warning("Cannot parse header date")
|
||||
} else {
|
||||
crypto.UpdateTime(date.Unix())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func catchRetryAfter(_ *resty.Client, res *resty.Response) (time.Duration, error) {
|
||||
if res.StatusCode() == http.StatusTooManyRequests {
|
||||
if after := res.Header().Get("Retry-After"); after != "" {
|
||||
|
||||
@ -1,15 +1,27 @@
|
||||
## v1.8.3
|
||||
- 2021-05-31
|
||||
## v1.8.5
|
||||
- 2021-06-11
|
||||
|
||||
### New
|
||||
|
||||
- Improved moving messages from other accounts to ProtonMail - implemented new parser for processing such messages
|
||||
- Performance improvements
|
||||
- Implemented golang Secure Remote Password Protocol
|
||||
- Updated crypto-libraries to gopenpgp/v2 v2.1.9
|
||||
- Implemented new message parser (for imports from external accounts)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Sync issue with Microsoft Outlook (changed the order of processing requests)
|
||||
- Fetching the bodies of non-multipart messages
|
||||
- Bridge not to strip PGP signatures of incoming clear text messages
|
||||
- Import of messages with malformed MIME header
|
||||
- Improved parsing of message headers
|
||||
- Fetching bodies of non-multipart messages
|
||||
- Sync and performance improvements
|
||||
|
||||
|
||||
## v1.8.3
|
||||
- 2021-05-27
|
||||
|
||||
### Fixed
|
||||
|
||||
- A bug with sending encrypted emails to external contacts
|
||||
|
||||
|
||||
## v1.8.2
|
||||
|
||||
@ -1,3 +1,11 @@
|
||||
## v1.8.3
|
||||
- 2021-05-27
|
||||
|
||||
### Fixed
|
||||
|
||||
- A bug with sending encrypted emails to external contacts
|
||||
|
||||
|
||||
## v1.8.2
|
||||
- 2021-05-21
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.PHONY: check-go check-godog install-godog test test-bridge test-ie test-live test-live-bridge test-live-ie test-stage test-debug test-live-debug bench
|
||||
|
||||
export GO111MODULE=on
|
||||
export BRIDGE_VERSION:=1.5.5+integrationtests
|
||||
export BRIDGE_VERSION:=1.8.7+integrationtests
|
||||
export VERBOSITY?=fatal
|
||||
export TEST_DATA=testdata
|
||||
export TEST_APP?=bridge
|
||||
|
||||
@ -29,6 +29,9 @@ const (
|
||||
)
|
||||
|
||||
func FeatureContext(s *godog.Suite) {
|
||||
s.BeforeSuite(context.BeforeRun)
|
||||
s.AfterSuite(context.AfterRun)
|
||||
|
||||
s.BeforeScenario(beforeScenario)
|
||||
s.AfterScenario(afterScenario)
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ func benchTestContext() (*context.TestContext, *mocks.IMAPClient) {
|
||||
panic("account " + username + " does not exist")
|
||||
}
|
||||
|
||||
_ = ctx.GetPMAPIController().AddUser(account.User(), account.Addresses(), account.Password(), account.IsTwoFAEnabled())
|
||||
_ = ctx.GetPMAPIController().AddUser(account)
|
||||
if err := ctx.LoginUser(account.Username(), account.Password(), account.MailboxPassword()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@ -94,8 +94,6 @@ type TestContext struct {
|
||||
|
||||
// New returns a new test TestContext.
|
||||
func New(app string) *TestContext {
|
||||
setLogrusVerbosityFromEnv()
|
||||
|
||||
listener := listener.New()
|
||||
pmapiController, clientManager := newPMAPIController(app, listener)
|
||||
|
||||
|
||||
40
test/context/globals.go
Normal file
40
test/context/globals.go
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/test/liveapi"
|
||||
)
|
||||
|
||||
// BeforeRun does necessary setup.
|
||||
func BeforeRun() {
|
||||
setLogrusVerbosityFromEnv()
|
||||
|
||||
if os.Getenv(EnvName) == EnvLive {
|
||||
liveapi.SetupPersistentClients()
|
||||
}
|
||||
}
|
||||
|
||||
// AfterRun does necessary cleanup.
|
||||
func AfterRun() {
|
||||
if os.Getenv(EnvName) == EnvLive {
|
||||
liveapi.CleanupPersistentClients()
|
||||
}
|
||||
}
|
||||
@ -23,6 +23,7 @@ import (
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
"github.com/ProtonMail/proton-bridge/test/accounts"
|
||||
"github.com/ProtonMail/proton-bridge/test/fakeapi"
|
||||
"github.com/ProtonMail/proton-bridge/test/liveapi"
|
||||
)
|
||||
@ -30,7 +31,8 @@ import (
|
||||
type PMAPIController interface {
|
||||
TurnInternetConnectionOff()
|
||||
TurnInternetConnectionOn()
|
||||
AddUser(user *pmapi.User, addresses *pmapi.AddressList, password []byte, twoFAEnabled bool) error
|
||||
GetAuthClient(username string) pmapi.Client
|
||||
AddUser(account *accounts.TestAccount) error
|
||||
AddUserLabel(username string, label *pmapi.Label) error
|
||||
GetLabelIDs(username string, labelNames []string) ([]string, error)
|
||||
AddUserMessage(username string, message *pmapi.Message) (string, error)
|
||||
|
||||
@ -27,6 +27,7 @@ import (
|
||||
"github.com/ProtonMail/go-srp"
|
||||
"github.com/ProtonMail/proton-bridge/internal/store"
|
||||
"github.com/ProtonMail/proton-bridge/internal/users"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -61,6 +62,27 @@ func (ctx *TestContext) LoginUser(username string, password, mailboxPassword []b
|
||||
return nil
|
||||
}
|
||||
|
||||
// FinishLogin prevents authentication if not necessary.
|
||||
func (ctx *TestContext) FinishLogin(client pmapi.Client, mailboxPassword []byte) error {
|
||||
type currentAuthGetter interface {
|
||||
GetCurrentAuth() *pmapi.Auth
|
||||
}
|
||||
|
||||
c, ok := client.(currentAuthGetter)
|
||||
if c == nil || !ok {
|
||||
return errors.New("cannot get current auth tokens from client")
|
||||
}
|
||||
|
||||
user, err := ctx.users.FinishLogin(client, c.GetCurrentAuth(), mailboxPassword)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to finish login")
|
||||
}
|
||||
|
||||
ctx.addCleanupChecked(user.Logout, "Logging out user")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUser retrieves the bridge user matching the given query string.
|
||||
func (ctx *TestContext) GetUser(username string) (*users.User, error) {
|
||||
return ctx.users.GetUser(username)
|
||||
|
||||
@ -63,3 +63,13 @@ func (api *FakePMAPI) AuthDelete(_ context.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (api *FakePMAPI) GetCurrentAuth() *pmapi.Auth {
|
||||
return &pmapi.Auth{
|
||||
UserID: api.userID,
|
||||
AuthRefresh: pmapi.AuthRefresh{
|
||||
UID: api.uid,
|
||||
RefreshToken: api.ref,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Controller implements dummy PMAPIController interface without actual
|
||||
// endpoint.
|
||||
type Controller struct {
|
||||
// Internal states.
|
||||
lock *sync.RWMutex
|
||||
|
||||
@ -22,8 +22,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
"github.com/ProtonMail/proton-bridge/test/accounts"
|
||||
)
|
||||
|
||||
var systemLabelNameToID = map[string]string{ //nolint[gochecknoglobals]
|
||||
@ -61,13 +63,15 @@ func (ctl *Controller) ReorderAddresses(user *pmapi.User, addressIDs []string) e
|
||||
return api.ReorderAddresses(context.Background(), addressIDs)
|
||||
}
|
||||
|
||||
func (ctl *Controller) AddUser(user *pmapi.User, addresses *pmapi.AddressList, password []byte, twoFAEnabled bool) error {
|
||||
ctl.usersByUsername[user.Name] = &fakeUser{
|
||||
user: user,
|
||||
password: password,
|
||||
has2FA: twoFAEnabled,
|
||||
func (ctl *Controller) AddUser(account *accounts.TestAccount) error {
|
||||
ctl.usersByUsername[account.User().Name] = &fakeUser{
|
||||
user: account.User(),
|
||||
password: account.Password(),
|
||||
has2FA: account.IsTwoFAEnabled(),
|
||||
}
|
||||
ctl.addressesByUsername[user.Name] = addresses
|
||||
ctl.addressesByUsername[account.User().Name] = account.Addresses()
|
||||
ctl.createSession(account.User().Name, true)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -181,3 +185,15 @@ func (ctl *Controller) GetMessages(username, labelID string) ([]*pmapi.Message,
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
func (ctl *Controller) GetAuthClient(username string) pmapi.Client {
|
||||
for uid, session := range ctl.sessionsByUID {
|
||||
if session.username == username {
|
||||
return ctl.clientManager.NewClient(uid, session.acc, session.ref, time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
ctl.log.WithField("username", username).Fatal("Cannot get authenticated client.")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -51,24 +51,25 @@ func (ctl *Controller) checkScope(uid string) bool {
|
||||
}
|
||||
|
||||
func (ctl *Controller) createSessionIfAuthorized(username string, password []byte) (*fakeSession, error) {
|
||||
// get user
|
||||
user, ok := ctl.usersByUsername[username]
|
||||
if !ok || !bytes.Equal(user.password, password) {
|
||||
return nil, errWrongNameOrPassword
|
||||
}
|
||||
|
||||
// create session
|
||||
return ctl.createSession(username, !user.has2FA), nil
|
||||
}
|
||||
|
||||
func (ctl *Controller) createSession(username string, hasFullScope bool) *fakeSession {
|
||||
session := &fakeSession{
|
||||
username: username,
|
||||
uid: ctl.tokenGenerator.next("uid"),
|
||||
acc: ctl.tokenGenerator.next("acc"),
|
||||
ref: ctl.tokenGenerator.next("ref"),
|
||||
hasFullScope: !user.has2FA,
|
||||
hasFullScope: hasFullScope,
|
||||
}
|
||||
|
||||
ctl.sessionsByUID[session.uid] = session
|
||||
|
||||
return session, nil
|
||||
return session
|
||||
}
|
||||
|
||||
func (ctl *Controller) refreshSessionIfAuthorized(uid, ref string) (*fakeSession, error) {
|
||||
|
||||
@ -15,7 +15,7 @@ Feature: IMAP auth
|
||||
Then IMAP response is "IMAP error: NO account is logged out, use the app to login again"
|
||||
|
||||
Scenario: Authenticates with connected user that was loaded without internet
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
And there is no internet connection
|
||||
When bridge starts
|
||||
And the internet connection is restored
|
||||
@ -28,13 +28,13 @@ Feature: IMAP auth
|
||||
Then "user" is connected
|
||||
|
||||
Scenario: Authenticates with freshly logged-out user
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
When "user" logs out
|
||||
And IMAP client authenticates "user"
|
||||
Then IMAP response is "IMAP error: NO account is logged out, use the app to login again"
|
||||
|
||||
Scenario: Authenticates user which was re-logged in
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
When "user" logs out
|
||||
And IMAP client authenticates "user"
|
||||
Then IMAP response is "IMAP error: NO account is logged out, use the app to login again"
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
Feature: Servers are closed when no internet
|
||||
|
||||
Scenario: All connection are closed and then restored multiple times
|
||||
Given there is connected user "user"
|
||||
And there is IMAP client "i1" logged in as "user"
|
||||
And there is SMTP client "s1" logged in as "user"
|
||||
When there is no internet connection
|
||||
And 1 second pass
|
||||
Then IMAP client "i1" is logged out
|
||||
And SMTP client "s1" is logged out
|
||||
Given the internet connection is restored
|
||||
And 1 second pass
|
||||
And there is IMAP client "i2" logged in as "user"
|
||||
And there is SMTP client "s2" logged in as "user"
|
||||
When IMAP client "i2" gets info of "INBOX"
|
||||
When SMTP client "s2" sends "HELO example.com"
|
||||
Then IMAP response to "i2" is "OK"
|
||||
Then SMTP response to "s2" is "OK"
|
||||
When there is no internet connection
|
||||
And 1 second pass
|
||||
Then IMAP client "i2" is logged out
|
||||
And SMTP client "s2" is logged out
|
||||
Given the internet connection is restored
|
||||
And 1 second pass
|
||||
And there is IMAP client "i3" logged in as "user"
|
||||
And there is SMTP client "s3" logged in as "user"
|
||||
When IMAP client "i3" gets info of "INBOX"
|
||||
When SMTP client "s3" sends "HELO example.com"
|
||||
Then IMAP response to "i3" is "OK"
|
||||
Then SMTP response to "s3" is "OK"
|
||||
@ -1,6 +1,6 @@
|
||||
Feature: Start bridge
|
||||
Scenario: Start with connected user, database file and internet connection
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
And there is database file for "user"
|
||||
When bridge starts
|
||||
Then "user" is connected
|
||||
@ -8,7 +8,7 @@ Feature: Start bridge
|
||||
And "user" has running event loop
|
||||
|
||||
Scenario: Start with connected user, database file and no internet connection
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
And there is database file for "user"
|
||||
And there is no internet connection
|
||||
When bridge starts
|
||||
@ -17,7 +17,7 @@ Feature: Start bridge
|
||||
And "user" has running event loop
|
||||
|
||||
Scenario: Start with connected user, no database file and internet connection
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
And there is no database file for "user"
|
||||
When bridge starts
|
||||
Then "user" is connected
|
||||
@ -25,7 +25,7 @@ Feature: Start bridge
|
||||
And "user" has running event loop
|
||||
|
||||
Scenario: Start with connected user, no database file and no internet connection
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
And there is no database file for "user"
|
||||
And there is no internet connection
|
||||
When bridge starts
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
Feature: Delete user
|
||||
Scenario: Deleting connected user
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
When user deletes "user"
|
||||
Then last response is "OK"
|
||||
And "user" has database file
|
||||
|
||||
Scenario: Deleting connected user with cache
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
When user deletes "user" with cache
|
||||
Then last response is "OK"
|
||||
And "user" does not have database file
|
||||
|
||||
Scenario: Deleting connected user without database file
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
And there is no database file for "user"
|
||||
When user deletes "user" with cache
|
||||
Then last response is "OK"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Feature: Re-login
|
||||
Scenario: Re-login with connected user and database file
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
And there is database file for "user"
|
||||
When "user" logs in
|
||||
Then last response is "failed to finish login: user is already connected"
|
||||
@ -9,7 +9,7 @@ Feature: Re-login
|
||||
|
||||
@ignore
|
||||
Scenario: Re-login with connected user and no database file
|
||||
Given there is connected user "user"
|
||||
Given there is user "user" which just logged in
|
||||
And there is no database file for "user"
|
||||
When "user" logs in
|
||||
Then last response is "failed to finish login: user is already connected"
|
||||
|
||||
@ -21,45 +21,36 @@ import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/constants"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Controller implements PMAPIController interface for specified endpoint.
|
||||
type Controller struct {
|
||||
log *logrus.Entry
|
||||
// Internal states.
|
||||
lock *sync.RWMutex
|
||||
calls []*fakeCall
|
||||
pmapiByUsername map[string]pmapi.Client
|
||||
messageIDsByUsername map[string][]string
|
||||
clientManager pmapi.Manager
|
||||
|
||||
// State controlled by test.
|
||||
noInternetConnection bool
|
||||
}
|
||||
|
||||
func NewController(app string) (*Controller, pmapi.Manager) {
|
||||
cm := pmapi.New(pmapi.NewConfig(getAppVersionName(app), constants.Version))
|
||||
func NewController(_ string) (*Controller, pmapi.Manager) {
|
||||
controller := &Controller{
|
||||
log: logrus.WithField("pkg", "live-controller"),
|
||||
lock: &sync.RWMutex{},
|
||||
calls: []*fakeCall{},
|
||||
pmapiByUsername: map[string]pmapi.Client{},
|
||||
messageIDsByUsername: map[string][]string{},
|
||||
clientManager: cm,
|
||||
|
||||
noInternetConnection: false,
|
||||
}
|
||||
|
||||
cm.SetTransport(&fakeTransport{
|
||||
persistentClients.manager.SetTransport(&fakeTransport{
|
||||
ctl: controller,
|
||||
transport: http.DefaultTransport,
|
||||
})
|
||||
|
||||
return controller, cm
|
||||
}
|
||||
|
||||
func getAppVersionName(app string) string {
|
||||
if app == "ie" {
|
||||
return "importExport"
|
||||
}
|
||||
return app
|
||||
return controller, persistentClients.manager
|
||||
}
|
||||
|
||||
@ -37,9 +37,9 @@ var systemLabelNameToID = map[string]string{ //nolint[gochecknoglobals]
|
||||
}
|
||||
|
||||
func (ctl *Controller) AddUserLabel(username string, label *pmapi.Label) error {
|
||||
client, ok := ctl.pmapiByUsername[username]
|
||||
if !ok {
|
||||
return fmt.Errorf("user %s does not exist", username)
|
||||
client, err := getPersistentClient(username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
label.Exclusive = getLabelExclusive(label.Name)
|
||||
@ -68,9 +68,9 @@ func (ctl *Controller) getLabelID(username, labelName string) (string, error) {
|
||||
return labelID, nil
|
||||
}
|
||||
|
||||
client, ok := ctl.pmapiByUsername[username]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("user %s does not exist", username)
|
||||
client, err := getPersistentClient(username)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
labels, err := client.ListLabels(context.Background())
|
||||
|
||||
@ -19,7 +19,6 @@ package liveapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
messageUtils "github.com/ProtonMail/proton-bridge/pkg/message"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
@ -31,9 +30,9 @@ func (ctl *Controller) AddUserMessage(username string, message *pmapi.Message) (
|
||||
return "", errors.New("add user messages with attachments is not implemented for live")
|
||||
}
|
||||
|
||||
client, ok := ctl.pmapiByUsername[username]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("user %s does not exist", username)
|
||||
client, err := getPersistentClient(username)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if message.Flags == 0 {
|
||||
@ -75,9 +74,9 @@ func (ctl *Controller) AddUserMessage(username string, message *pmapi.Message) (
|
||||
}
|
||||
|
||||
func (ctl *Controller) GetMessages(username, labelID string) ([]*pmapi.Message, error) {
|
||||
client, ok := ctl.pmapiByUsername[username]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("user %s does not exist", username)
|
||||
client, err := getPersistentClient(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
page := 0
|
||||
|
||||
141
test/liveapi/persistent_clients.go
Normal file
141
test/liveapi/persistent_clients.go
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package liveapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
|
||||
"github.com/ProtonMail/go-srp"
|
||||
"github.com/ProtonMail/proton-bridge/internal/constants"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type clientAuthGetter interface {
|
||||
pmapi.Client
|
||||
GetCurrentAuth() *pmapi.Auth
|
||||
}
|
||||
|
||||
// persistentClients keeps authenticated clients for tests.
|
||||
//
|
||||
// We need to reduce the number of authentication done by live tests.
|
||||
// Before every *scenario* we are creating and authenticating new client.
|
||||
// This is not necessary for controller purposes. We can reuse the same clients
|
||||
// for all tests.
|
||||
//
|
||||
//nolint:gochecknoglobals // This is necessary for testing
|
||||
var persistentClients = struct {
|
||||
manager pmapi.Manager
|
||||
byName map[string]clientAuthGetter
|
||||
saltByName map[string]string
|
||||
}{}
|
||||
|
||||
type persistentClient struct {
|
||||
clientAuthGetter
|
||||
username string
|
||||
}
|
||||
|
||||
// AuthDelete is noop. All sessions will be closed in CleanupPersistentClients.
|
||||
func (pc *persistentClient) AuthDelete(_ context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthSalt returns cached string. Otherwise after some time there is an error:
|
||||
//
|
||||
// Access token does not have sufficient scope
|
||||
//
|
||||
// while all other routes works normally. Need to confirm with Aron that this
|
||||
// is expected behaviour.
|
||||
func (pc *persistentClient) AuthSalt(_ context.Context) (string, error) {
|
||||
return persistentClients.saltByName[pc.username], nil
|
||||
}
|
||||
|
||||
func SetupPersistentClients() {
|
||||
app := os.Getenv("TEST_APP")
|
||||
|
||||
persistentClients.manager = pmapi.New(pmapi.NewConfig(getAppVersionName(app), constants.Version))
|
||||
persistentClients.manager.SetLogging(logrus.WithField("pkg", "liveapi"), logrus.GetLevel() == logrus.TraceLevel)
|
||||
|
||||
persistentClients.byName = map[string]clientAuthGetter{}
|
||||
persistentClients.saltByName = map[string]string{}
|
||||
}
|
||||
|
||||
func getAppVersionName(app string) string {
|
||||
if app == "ie" {
|
||||
return "importExport"
|
||||
}
|
||||
return app
|
||||
}
|
||||
|
||||
func CleanupPersistentClients() {
|
||||
for username, client := range persistentClients.byName {
|
||||
if err := client.AuthDelete(context.Background()); err != nil {
|
||||
logrus.WithError(err).
|
||||
WithField("username", username).
|
||||
Error("Failed to logout persistent client")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addPersistentClient(username string, password, mailboxPassword []byte) (pmapi.Client, error) {
|
||||
if cl, ok := persistentClients.byName[username]; ok {
|
||||
return cl, nil
|
||||
}
|
||||
|
||||
srp.RandReader = rand.New(rand.NewSource(42)) //nolint:gosec // It is OK to use weaker random number generator here
|
||||
|
||||
normalClient, _, err := persistentClients.manager.NewClientWithLogin(context.Background(), username, password)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create new persistent client")
|
||||
}
|
||||
|
||||
client, ok := normalClient.(clientAuthGetter)
|
||||
if !ok {
|
||||
return nil, errors.New("cannot make clientAuthGetter")
|
||||
}
|
||||
|
||||
salt, err := client.AuthSalt(context.Background())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "persistent client: failed to get salt")
|
||||
}
|
||||
|
||||
hashedMboxPass, err := pmapi.HashMailboxPassword(mailboxPassword, salt)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "persistent client: failed to hash mailbox password")
|
||||
}
|
||||
|
||||
if err := client.Unlock(context.Background(), hashedMboxPass); err != nil {
|
||||
return nil, errors.Wrap(err, "persistent client: failed to unlock user")
|
||||
}
|
||||
|
||||
persistentClients.byName[username] = client
|
||||
persistentClients.saltByName[username] = salt
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func getPersistentClient(username string) (pmapi.Client, error) {
|
||||
v, ok := persistentClients.byName[username]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("user %s does not exist", username)
|
||||
}
|
||||
return &persistentClient{v, username}, nil
|
||||
}
|
||||
@ -21,43 +21,42 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
"github.com/ProtonMail/proton-bridge/test/accounts"
|
||||
"github.com/cucumber/godog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (ctl *Controller) AddUser(user *pmapi.User, addresses *pmapi.AddressList, password []byte, twoFAEnabled bool) error {
|
||||
if twoFAEnabled {
|
||||
func (ctl *Controller) AddUser(account *accounts.TestAccount) error {
|
||||
if account.IsTwoFAEnabled() {
|
||||
return godog.ErrPending
|
||||
}
|
||||
|
||||
client, _, err := ctl.clientManager.NewClientWithLogin(context.Background(), user.Name, password)
|
||||
client, err := addPersistentClient(account.User().Name, account.Password(), account.MailboxPassword())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create new client")
|
||||
return errors.Wrap(err, "failed to add persistent client")
|
||||
}
|
||||
|
||||
salt, err := client.AuthSalt(context.Background())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get salt")
|
||||
}
|
||||
|
||||
mailboxPassword, err := pmapi.HashMailboxPassword(password, salt)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to hash mailbox password")
|
||||
}
|
||||
|
||||
if err := client.Unlock(context.Background(), mailboxPassword); err != nil {
|
||||
return errors.Wrap(err, "failed to unlock user")
|
||||
}
|
||||
|
||||
if err := cleanup(client, addresses); err != nil {
|
||||
if err := cleanup(client, account.Addresses()); err != nil {
|
||||
return errors.Wrap(err, "failed to clean user")
|
||||
}
|
||||
|
||||
ctl.pmapiByUsername[user.Name] = client
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctl *Controller) ReorderAddresses(user *pmapi.User, addressIDs []string) error {
|
||||
return ctl.pmapiByUsername[user.Name].ReorderAddresses(context.Background(), addressIDs)
|
||||
client, err := getPersistentClient(user.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.ReorderAddresses(context.Background(), addressIDs)
|
||||
}
|
||||
|
||||
func (ctl *Controller) GetAuthClient(username string) pmapi.Client {
|
||||
client, err := getPersistentClient(username)
|
||||
if err != nil {
|
||||
ctl.log.WithError(err).
|
||||
WithField("username", username).
|
||||
Fatal("Cannot get authenticated client")
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ import (
|
||||
func UsersSetupFeatureContext(s *godog.Suite) {
|
||||
s.Step(`^there is user "([^"]*)"$`, thereIsUser)
|
||||
s.Step(`^there is connected user "([^"]*)"$`, thereIsConnectedUser)
|
||||
s.Step(`^there is user "([^"]*)" which just logged in$`, thereIsUserWhichJustLoggedIn)
|
||||
s.Step(`^there is disconnected user "([^"]*)"$`, thereIsDisconnectedUser)
|
||||
s.Step(`^there is database file for "([^"]*)"$`, thereIsDatabaseFileForUser)
|
||||
s.Step(`^there is no database file for "([^"]*)"$`, thereIsNoDatabaseFileForUser)
|
||||
@ -39,7 +40,7 @@ func thereIsUser(bddUserID string) error {
|
||||
if account == nil {
|
||||
return godog.ErrPending
|
||||
}
|
||||
err := ctx.GetPMAPIController().AddUser(account.User(), account.Addresses(), account.Password(), account.IsTwoFAEnabled())
|
||||
err := ctx.GetPMAPIController().AddUser(account)
|
||||
return internalError(err, "adding user %s", account.Username())
|
||||
}
|
||||
|
||||
@ -48,7 +49,21 @@ func thereIsConnectedUser(bddUserID string) error {
|
||||
if account == nil {
|
||||
return godog.ErrPending
|
||||
}
|
||||
err := ctx.GetPMAPIController().AddUser(account.User(), account.Addresses(), account.Password(), account.IsTwoFAEnabled())
|
||||
username := account.Username()
|
||||
ctl := ctx.GetPMAPIController()
|
||||
err := ctl.AddUser(account)
|
||||
if err != nil {
|
||||
return internalError(err, "adding user %s", username)
|
||||
}
|
||||
return ctx.FinishLogin(ctx.GetPMAPIController().GetAuthClient(username), account.MailboxPassword())
|
||||
}
|
||||
|
||||
func thereIsUserWhichJustLoggedIn(bddUserID string) error {
|
||||
account := ctx.GetTestAccount(bddUserID)
|
||||
if account == nil {
|
||||
return godog.ErrPending
|
||||
}
|
||||
err := ctx.GetPMAPIController().AddUser(account)
|
||||
if err != nil {
|
||||
return internalError(err, "adding user %s", account.Username())
|
||||
}
|
||||
@ -60,7 +75,7 @@ func thereIsDisconnectedUser(bddUserID string) error {
|
||||
if account == nil {
|
||||
return godog.ErrPending
|
||||
}
|
||||
err := ctx.GetPMAPIController().AddUser(account.User(), account.Addresses(), account.Password(), account.IsTwoFAEnabled())
|
||||
err := ctx.GetPMAPIController().AddUser(account)
|
||||
if err != nil {
|
||||
return internalError(err, "adding user %s", account.Username())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user