diff --git a/Changelog.md b/Changelog.md
index 49143f7e..c6fa083b 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,18 @@
Changelog [format](http://keepachangelog.com/en/1.0.0/)
+## [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
diff --git a/Makefile b/Makefile
index a69a7b81..7fe0f7fd 100644
--- a/Makefile
+++ b/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.6+git
IE_APP_VERSION?=1.3.3+git
APP_VERSION:=${BRIDGE_APP_VERSION}
SRC_ICO:=logo.ico
diff --git a/go.mod b/go.mod
index f58d457e..a6383fe8 100644
--- a/go.mod
+++ b/go.mod
@@ -73,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
)
diff --git a/go.sum b/go.sum
index 17cf187b..3fc203fa 100644
--- a/go.sum
+++ b/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=
@@ -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=
diff --git a/internal/imap/server.go b/internal/imap/server.go
index 7dfb3caf..a6cecd3c 100644
--- a/internal/imap/server.go
+++ b/internal/imap/server.go
@@ -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() }
diff --git a/internal/imap/server_test.go b/internal/imap/server_test.go
deleted file mode 100644
index 1653cbd2..00000000
--- a/internal/imap/server_test.go
+++ /dev/null
@@ -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 .
-
-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)
-}
diff --git a/internal/serverutil/controller.go b/internal/serverutil/controller.go
new file mode 100644
index 00000000..c2ba1dca
--- /dev/null
+++ b/internal/serverutil/controller.go
@@ -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 .
+
+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)
+ }
+ }
+}
diff --git a/internal/smtp/server_test.go b/internal/serverutil/error_logger.go
similarity index 61%
rename from internal/smtp/server_test.go
rename to internal/serverutil/error_logger.go
index 3342d21c..576f2d84 100644
--- a/internal/smtp/server_test.go
+++ b/internal/serverutil/error_logger.go
@@ -15,29 +15,25 @@
// You should have received a copy of the GNU General Public License
// along with ProtonMail Bridge. If not, see .
-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...)
}
diff --git a/internal/serverutil/listener.go b/internal/serverutil/listener.go
new file mode 100644
index 00000000..53450205
--- /dev/null
+++ b/internal/serverutil/listener.go
@@ -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 .
+
+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
+}
diff --git a/internal/serverutil/mocks/server.go b/internal/serverutil/mocks/server.go
deleted file mode 100644
index 8e60c33c..00000000
--- a/internal/serverutil/mocks/server.go
+++ /dev/null
@@ -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 .
-
-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)
- }
-}
diff --git a/internal/serverutil/server_test.go b/internal/serverutil/protocol.go
similarity index 71%
rename from internal/serverutil/server_test.go
rename to internal/serverutil/protocol.go
index fa04a06f..c551359f 100644
--- a/internal/serverutil/server_test.go
+++ b/internal/serverutil/protocol.go
@@ -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)
-}
diff --git a/internal/serverutil/server.go b/internal/serverutil/server.go
index 6542194e..e081b032 100644
--- a/internal/serverutil/server.go
+++ b/internal/serverutil/server.go
@@ -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
}
diff --git a/internal/serverutil/test/controller_test.go b/internal/serverutil/test/controller_test.go
new file mode 100644
index 00000000..62cab2ec
--- /dev/null
+++ b/internal/serverutil/test/controller_test.go
@@ -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 .
+
+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)
+}
diff --git a/internal/serverutil/test/server.go b/internal/serverutil/test/server.go
new file mode 100644
index 00000000..f0615c5d
--- /dev/null
+++ b/internal/serverutil/test/server.go
@@ -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 .
+
+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()
+}
diff --git a/internal/smtp/server.go b/internal/smtp/server.go
index ecb9f2f6..3db68c69 100644
--- a/internal/smtp/server.go
+++ b/internal/smtp/server.go
@@ -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() }
diff --git a/internal/store/mocks/mocks.go b/internal/store/mocks/mocks.go
index acb846be..7adf0ed3 100644
--- a/internal/store/mocks/mocks.go
+++ b/internal/store/mocks/mocks.go
@@ -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)
diff --git a/internal/store/mocks/utils_mocks.go b/internal/store/mocks/utils_mocks.go
index 8a6c8677..ec99aa03 100644
--- a/internal/store/mocks/utils_mocks.go
+++ b/internal/store/mocks/utils_mocks.go
@@ -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)
diff --git a/internal/transfer/mocks/mocks.go b/internal/transfer/mocks/mocks.go
index 1c8040e0..3b57b51d 100644
--- a/internal/transfer/mocks/mocks.go
+++ b/internal/transfer/mocks/mocks.go
@@ -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)
diff --git a/internal/users/mocks/listener_mocks.go b/internal/users/mocks/listener_mocks.go
index 8a6c8677..ec99aa03 100644
--- a/internal/users/mocks/listener_mocks.go
+++ b/internal/users/mocks/listener_mocks.go
@@ -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)
diff --git a/internal/users/mocks/mocks.go b/internal/users/mocks/mocks.go
index 8293f297..83e327dd 100644
--- a/internal/users/mocks/mocks.go
+++ b/internal/users/mocks/mocks.go
@@ -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)
diff --git a/pkg/message/build_framework_test.go b/pkg/message/build_framework_test.go
index 4e00ce00..16ddfed6 100644
--- a/pkg/message/build_framework_test.go
+++ b/pkg/message/build_framework_test.go
@@ -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(
@@ -298,6 +299,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
diff --git a/pkg/message/build_rfc822.go b/pkg/message/build_rfc822.go
index 36366ca9..50471a3b 100644
--- a/pkg/message/build_rfc822.go
+++ b/pkg/message/build_rfc822.go
@@ -20,7 +20,6 @@ package message
import (
"bytes"
"encoding/base64"
- "io/ioutil"
"mime"
"net/mail"
"strings"
@@ -290,17 +289,12 @@ func writeMultipartSignedRFC822(header message.Header, body []byte, sig pmapi.Si
return nil, err
}
- ent, err := message.Read(bytes.NewReader(body))
+ bodyHeader, bodyData, err := readHeaderBody(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 := w.CreatePart(message.Header{Header: *bodyHeader})
if err != nil {
return nil, err
}
@@ -347,12 +341,12 @@ 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())
@@ -363,11 +357,6 @@ func writeMultipartEncryptedRFC822(header message.Header, body []byte) ([]byte,
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
}
diff --git a/pkg/message/build_test.go b/pkg/message/build_test.go
index c9f7fe70..f692a33c 100644
--- a/pkg/message/build_test.go
+++ b/pkg/message/build_test.go
@@ -98,6 +98,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" `)).
+ 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()
diff --git a/pkg/message/mocks/mocks.go b/pkg/message/mocks/mocks.go
index 0aa4b7ed..4c58525d 100644
--- a/pkg/message/mocks/mocks.go
+++ b/pkg/message/mocks/mocks.go
@@ -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)
diff --git a/pkg/message/testdata/pgp-mime-body-plaintext-latin2.eml b/pkg/message/testdata/pgp-mime-body-plaintext-latin2.eml
new file mode 100644
index 00000000..d971a446
--- /dev/null
+++ b/pkg/message/testdata/pgp-mime-body-plaintext-latin2.eml
@@ -0,0 +1,8 @@
+Subject: plain no pubkey no sign
+From: "pm.bridge.qa"
+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
+
+ø¹ø¹ø¹
diff --git a/pkg/pmapi/auth.go b/pkg/pmapi/auth.go
index 8773278d..d58b1060 100644
--- a/pkg/pmapi/auth.go
+++ b/pkg/pmapi/auth.go
@@ -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,
+ },
+ }
+}
diff --git a/pkg/pmapi/mocks/mocks.go b/pkg/pmapi/mocks/mocks.go
index 78492681..03085507 100644
--- a/pkg/pmapi/mocks/mocks.go
+++ b/pkg/pmapi/mocks/mocks.go
@@ -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)
diff --git a/release-notes/bridge_early.md b/release-notes/bridge_early.md
index 0d44e25a..47aaf860 100644
--- a/release-notes/bridge_early.md
+++ b/release-notes/bridge_early.md
@@ -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
diff --git a/release-notes/bridge_stable.md b/release-notes/bridge_stable.md
index e2328c9b..e2328088 100644
--- a/release-notes/bridge_stable.md
+++ b/release-notes/bridge_stable.md
@@ -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
diff --git a/test/Makefile b/test/Makefile
index 36197e27..61f43340 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -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.6+integrationtests
export VERBOSITY?=fatal
export TEST_DATA=testdata
export TEST_APP?=bridge
diff --git a/test/bdd_test.go b/test/bdd_test.go
index 0817b587..0b06c025 100644
--- a/test/bdd_test.go
+++ b/test/bdd_test.go
@@ -29,6 +29,9 @@ const (
)
func FeatureContext(s *godog.Suite) {
+ s.BeforeSuite(context.BeforeRun)
+ s.AfterSuite(context.AfterRun)
+
s.BeforeScenario(beforeScenario)
s.AfterScenario(afterScenario)
diff --git a/test/benchmarks/bench_test.go b/test/benchmarks/bench_test.go
index 4e01b6df..c7212914 100644
--- a/test/benchmarks/bench_test.go
+++ b/test/benchmarks/bench_test.go
@@ -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)
}
diff --git a/test/context/context.go b/test/context/context.go
index 4d2a1dc0..0778bebf 100644
--- a/test/context/context.go
+++ b/test/context/context.go
@@ -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)
diff --git a/test/context/globals.go b/test/context/globals.go
new file mode 100644
index 00000000..619cc5f5
--- /dev/null
+++ b/test/context/globals.go
@@ -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 .
+
+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()
+ }
+}
diff --git a/test/context/pmapi_controller.go b/test/context/pmapi_controller.go
index 17c5a1b9..7de8799d 100644
--- a/test/context/pmapi_controller.go
+++ b/test/context/pmapi_controller.go
@@ -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)
diff --git a/test/context/users.go b/test/context/users.go
index 9fa66ec0..1fb440b7 100644
--- a/test/context/users.go
+++ b/test/context/users.go
@@ -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)
diff --git a/test/fakeapi/auth.go b/test/fakeapi/auth.go
index 8f45a8df..b63fcc46 100644
--- a/test/fakeapi/auth.go
+++ b/test/fakeapi/auth.go
@@ -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,
+ },
+ }
+}
diff --git a/test/fakeapi/controller.go b/test/fakeapi/controller.go
index a01f0064..50a5d6d1 100644
--- a/test/fakeapi/controller.go
+++ b/test/fakeapi/controller.go
@@ -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
diff --git a/test/fakeapi/controller_control.go b/test/fakeapi/controller_control.go
index 35a9e184..8e853b65 100644
--- a/test/fakeapi/controller_control.go
+++ b/test/fakeapi/controller_control.go
@@ -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
+}
diff --git a/test/fakeapi/controller_session.go b/test/fakeapi/controller_session.go
index 87de705f..6fd81de5 100644
--- a/test/fakeapi/controller_session.go
+++ b/test/fakeapi/controller_session.go
@@ -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) {
diff --git a/test/features/bridge/imap/auth.feature b/test/features/bridge/imap/auth.feature
index 3191d1e3..a86e0897 100644
--- a/test/features/bridge/imap/auth.feature
+++ b/test/features/bridge/imap/auth.feature
@@ -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"
diff --git a/test/features/bridge/no_internet.feature b/test/features/bridge/no_internet.feature
deleted file mode 100644
index 5abb1841..00000000
--- a/test/features/bridge/no_internet.feature
+++ /dev/null
@@ -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"
diff --git a/test/features/bridge/start.feature b/test/features/bridge/start.feature
index 2d0b82e7..2b7c50c0 100644
--- a/test/features/bridge/start.feature
+++ b/test/features/bridge/start.feature
@@ -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
diff --git a/test/features/bridge/users/delete.feature b/test/features/bridge/users/delete.feature
index 770ddf6d..be7dc8d1 100644
--- a/test/features/bridge/users/delete.feature
+++ b/test/features/bridge/users/delete.feature
@@ -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"
diff --git a/test/features/bridge/users/relogin.feature b/test/features/bridge/users/relogin.feature
index e0b43d79..f1f8b9e0 100644
--- a/test/features/bridge/users/relogin.feature
+++ b/test/features/bridge/users/relogin.feature
@@ -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"
diff --git a/test/liveapi/controller.go b/test/liveapi/controller.go
index d4664007..9e28f512 100644
--- a/test/liveapi/controller.go
+++ b/test/liveapi/controller.go
@@ -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
}
diff --git a/test/liveapi/labels.go b/test/liveapi/labels.go
index 105b74e9..974ec085 100644
--- a/test/liveapi/labels.go
+++ b/test/liveapi/labels.go
@@ -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())
diff --git a/test/liveapi/messages.go b/test/liveapi/messages.go
index ed696f81..2487b568 100644
--- a/test/liveapi/messages.go
+++ b/test/liveapi/messages.go
@@ -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
diff --git a/test/liveapi/persistent_clients.go b/test/liveapi/persistent_clients.go
new file mode 100644
index 00000000..46538995
--- /dev/null
+++ b/test/liveapi/persistent_clients.go
@@ -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 .
+
+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
+}
diff --git a/test/liveapi/users.go b/test/liveapi/users.go
index eac77afa..b85aaa5b 100644
--- a/test/liveapi/users.go
+++ b/test/liveapi/users.go
@@ -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
}
diff --git a/test/users_setup_test.go b/test/users_setup_test.go
index 5ccfdc58..2c56fa0a 100644
--- a/test/users_setup_test.go
+++ b/test/users_setup_test.go
@@ -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())
}