Upgrade to latest go-smtp

This commit is contained in:
Michal Horejsek
2020-11-20 15:44:16 +01:00
parent ca962ce5ad
commit 635e51f32f
13 changed files with 192 additions and 31 deletions

3
go.mod
View File

@ -6,7 +6,6 @@ go 1.13
// They are in a separate require block to highlight this. // They are in a separate require block to highlight this.
require ( require (
github.com/docker/docker-credential-helpers v0.6.3 github.com/docker/docker-credential-helpers v0.6.3
github.com/emersion/go-smtp v0.0.0-20180712174835-db5eec195e67
github.com/jameskeane/bcrypt v0.0.0-20170924085257-7509ea014998 github.com/jameskeane/bcrypt v0.0.0-20170924085257-7509ea014998
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
) )
@ -38,6 +37,7 @@ require (
github.com/emersion/go-mbox v1.0.2 github.com/emersion/go-mbox v1.0.2
github.com/emersion/go-message v0.12.1-0.20200903165315-e1abe21f389a github.com/emersion/go-message v0.12.1-0.20200903165315-e1abe21f389a
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21
github.com/emersion/go-smtp v0.14.0
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe
github.com/emersion/go-vcard v0.0.0-20190105225839-8856043f13c5 // indirect github.com/emersion/go-vcard v0.0.0-20190105225839-8856043f13c5 // indirect
github.com/fatih/color v1.9.0 github.com/fatih/color v1.9.0
@ -75,7 +75,6 @@ require (
replace ( replace (
github.com/docker/docker-credential-helpers => github.com/ProtonMail/docker-credential-helpers v1.1.0 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-20201102134601-418cd74e9474 github.com/emersion/go-imap => github.com/ProtonMail/go-imap v0.0.0-20201102134601-418cd74e9474
github.com/emersion/go-smtp => github.com/ProtonMail/go-smtp v0.0.0-20181206232543-8261df20d309
github.com/jameskeane/bcrypt => github.com/ProtonMail/bcrypt v0.0.0-20170924085257-7509ea014998 github.com/jameskeane/bcrypt => github.com/ProtonMail/bcrypt v0.0.0-20170924085257-7509ea014998
golang.org/x/crypto => github.com/ProtonMail/crypto v0.0.0-20200818122824-ed5d25e28db8 golang.org/x/crypto => github.com/ProtonMail/crypto v0.0.0-20200818122824-ed5d25e28db8
) )

2
go.sum
View File

@ -94,6 +94,8 @@ github.com/emersion/go-message v0.12.1-0.20200903165315-e1abe21f389a/go.mod h1:k
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-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 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= 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 h1:40SWqY0zE3qCi6ZrtTf5OUdNm5lDnGnjRSq9GgmeTrg= github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe h1:40SWqY0zE3qCi6ZrtTf5OUdNm5lDnGnjRSq9GgmeTrg=
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U= github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/emersion/go-vcard v0.0.0-20190105225839-8856043f13c5 h1:n9qx98xiS5V4x2WIpPC2rr9mUM5ri9r/YhCEKbhCHro= github.com/emersion/go-vcard v0.0.0-20190105225839-8856043f13c5 h1:n9qx98xiS5V4x2WIpPC2rr9mUM5ri9r/YhCEKbhCHro=

View File

@ -15,8 +15,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>. // along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
// Code generated by ./credits.sh at Fri Nov 27 09:08:56 CET 2020. DO NOT EDIT. // Code generated by ./credits.sh at Fri Nov 27 09:23:06 CET 2020. DO NOT EDIT.
package bridge package bridge
const Credits = "github.com/0xAX/notificator;github.com/Masterminds/semver/v3;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/go-rfc5322;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/ProtonMail/gopenpgp/v2;github.com/PuerkitoBio/goquery;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-mbox;github.com/emersion/go-message;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/sentry-go;github.com/go-resty/resty/v2;github.com/golang/mock;github.com/google/go-cmp;github.com/google/uuid;github.com/gopherjs/gopherjs;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/mattn/go-runewidth;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/olekukonko/tablewriter;github.com/pkg/errors;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/ssor/bom;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;" const Credits = "github.com/0xAX/notificator;github.com/Masterminds/semver/v3;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/go-rfc5322;github.com/ProtonMail/go-vcard;github.com/ProtonMail/gopenpgp/v2;github.com/PuerkitoBio/goquery;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-mbox;github.com/emersion/go-message;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/sentry-go;github.com/go-resty/resty/v2;github.com/golang/mock;github.com/google/go-cmp;github.com/google/uuid;github.com/gopherjs/gopherjs;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/mattn/go-runewidth;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/olekukonko/tablewriter;github.com/pkg/errors;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/ssor/bom;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;"

View File

@ -126,7 +126,9 @@ func (s *imapServer) ListenAndServe() {
// Stops the server. // Stops the server.
func (s *imapServer) Close() { func (s *imapServer) Close() {
_ = s.server.Close() if err := s.server.Close(); err != nil {
log.WithError(err).Error("Failed to close the connection")
}
} }
func (s *imapServer) monitorDisconnectedUsers() { func (s *imapServer) monitorDisconnectedUsers() {
@ -139,7 +141,9 @@ func (s *imapServer) monitorDisconnectedUsers() {
disconnectUser := func(conn imapserver.Conn) { disconnectUser := func(conn imapserver.Conn) {
connUser := conn.Context().User connUser := conn.Context().User
if connUser != nil && strings.EqualFold(connUser.Username(), address) { if connUser != nil && strings.EqualFold(connUser.Username(), address) {
_ = conn.Close() if err := conn.Close(); err != nil {
log.WithError(err).Error("Failed to close the connection")
}
} }
} }
s.server.ForEachConn(disconnectUser) s.server.ForEachConn(disconnectUser)

View File

@ -15,8 +15,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>. // along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
// Code generated by ./credits.sh at Fri Nov 27 09:08:56 CET 2020. DO NOT EDIT. // Code generated by ./credits.sh at Fri Nov 27 09:23:06 CET 2020. DO NOT EDIT.
package importexport package importexport
const Credits = "github.com/0xAX/notificator;github.com/Masterminds/semver/v3;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/go-rfc5322;github.com/ProtonMail/go-smtp;github.com/ProtonMail/go-vcard;github.com/ProtonMail/gopenpgp/v2;github.com/PuerkitoBio/goquery;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-mbox;github.com/emersion/go-message;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/sentry-go;github.com/go-resty/resty/v2;github.com/golang/mock;github.com/google/go-cmp;github.com/google/uuid;github.com/gopherjs/gopherjs;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/mattn/go-runewidth;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/olekukonko/tablewriter;github.com/pkg/errors;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/ssor/bom;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;" const Credits = "github.com/0xAX/notificator;github.com/Masterminds/semver/v3;github.com/ProtonMail/bcrypt;github.com/ProtonMail/crypto;github.com/ProtonMail/docker-credential-helpers;github.com/ProtonMail/go-appdir;github.com/ProtonMail/go-apple-mobileconfig;github.com/ProtonMail/go-autostart;github.com/ProtonMail/go-imap;github.com/ProtonMail/go-imap-id;github.com/ProtonMail/go-rfc5322;github.com/ProtonMail/go-vcard;github.com/ProtonMail/gopenpgp/v2;github.com/PuerkitoBio/goquery;github.com/abiosoft/ishell;github.com/abiosoft/readline;github.com/allan-simon/go-singleinstance;github.com/chzyer/logex;github.com/chzyer/test;github.com/cucumber/godog;github.com/docker/docker-credential-helpers;github.com/emersion/go-imap;github.com/emersion/go-imap-appendlimit;github.com/emersion/go-imap-idle;github.com/emersion/go-imap-move;github.com/emersion/go-imap-quota;github.com/emersion/go-imap-specialuse;github.com/emersion/go-imap-unselect;github.com/emersion/go-mbox;github.com/emersion/go-message;github.com/emersion/go-sasl;github.com/emersion/go-smtp;github.com/emersion/go-textwrapper;github.com/emersion/go-vcard;github.com/fatih/color;github.com/flynn-archive/go-shlex;github.com/getsentry/sentry-go;github.com/go-resty/resty/v2;github.com/golang/mock;github.com/google/go-cmp;github.com/google/uuid;github.com/gopherjs/gopherjs;github.com/hashicorp/go-multierror;github.com/jameskeane/bcrypt;github.com/jaytaylor/html2text;github.com/kardianos/osext;github.com/keybase/go-keychain;github.com/logrusorgru/aurora;github.com/mattn/go-runewidth;github.com/miekg/dns;github.com/myesui/uuid;github.com/nsf/jsondiff;github.com/olekukonko/tablewriter;github.com/pkg/errors;github.com/sirupsen/logrus;github.com/skratchdot/open-golang;github.com/ssor/bom;github.com/stretchr/testify;github.com/therecipe/qt;github.com/twinj/uuid;github.com/urfave/cli;go.etcd.io/bbolt;golang.org/x/crypto;golang.org/x/net;golang.org/x/text;gopkg.in/stretchr/testify.v1;;Font Awesome 4.7.0;;Qt 5.13 by Qt group;"

View File

@ -27,6 +27,7 @@ import (
"github.com/ProtonMail/proton-bridge/pkg/confirmer" "github.com/ProtonMail/proton-bridge/pkg/confirmer"
"github.com/ProtonMail/proton-bridge/pkg/listener" "github.com/ProtonMail/proton-bridge/pkg/listener"
goSMTPBackend "github.com/emersion/go-smtp" goSMTPBackend "github.com/emersion/go-smtp"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -70,7 +71,7 @@ func newSMTPBackend(
} }
// Login authenticates a user. // Login authenticates a user.
func (sb *smtpBackend) Login(username, password string) (goSMTPBackend.User, error) { func (sb *smtpBackend) Login(_ *goSMTPBackend.ConnectionState, username, password string) (goSMTPBackend.Session, error) {
// Called from go-smtp in goroutines - we need to handle panics for each function. // Called from go-smtp in goroutines - we need to handle panics for each function.
defer sb.panicHandler.HandlePanic() defer sb.panicHandler.HandlePanic()
username = strings.ToLower(username) username = strings.ToLower(username)
@ -97,7 +98,14 @@ func (sb *smtpBackend) Login(username, password string) (goSMTPBackend.User, err
if user.IsCombinedAddressMode() { if user.IsCombinedAddressMode() {
addressID = "" addressID = ""
} }
return newSMTPUser(sb.panicHandler, sb.eventListener, sb, user, addressID) return newSMTPUser(sb.panicHandler, sb.eventListener, sb, user, username, addressID)
}
func (sb *smtpBackend) AnonymousLogin(_ *goSMTPBackend.ConnectionState) (goSMTPBackend.Session, error) {
// Called from go-smtp in goroutines - we need to handle panics for each function.
defer sb.panicHandler.HandlePanic()
return nil, errors.New("anonymous login not supported")
} }
func (sb *smtpBackend) shouldReportOutgoingNoEnc() bool { func (sb *smtpBackend) shouldReportOutgoingNoEnc() bool {

View File

@ -51,12 +51,12 @@ func NewSMTPServer(debug bool, port int, useSSL bool, tls *tls.Config, smtpBacke
s.EnableAuth(sasl.Login, func(conn *goSMTP.Conn) sasl.Server { s.EnableAuth(sasl.Login, func(conn *goSMTP.Conn) sasl.Server {
return sasl.NewLoginServer(func(address, password string) error { return sasl.NewLoginServer(func(address, password string) error {
user, err := conn.Server().Backend.Login(address, password) user, err := conn.Server().Backend.Login(nil, address, password)
if err != nil { if err != nil {
return err return err
} }
conn.SetUser(user) conn.SetSession(user)
return nil return nil
}) })
}) })
@ -85,14 +85,16 @@ func (s *smtpServer) ListenAndServe() {
l.Error("SMTP failed: ", err) l.Error("SMTP failed: ", err)
return return
} }
defer s.server.Close() defer s.server.Close() //nolint[errcheck]
l.Info("SMTP server stopped") l.Info("SMTP server stopped")
} }
// Stops the server. // Stops the server.
func (s *smtpServer) Close() { func (s *smtpServer) Close() {
s.server.Close() if err := s.server.Close(); err != nil {
log.WithError(err).Error("Failed to close the connection")
}
} }
func (s *smtpServer) monitorDisconnectedUsers() { func (s *smtpServer) monitorDisconnectedUsers() {
@ -102,9 +104,11 @@ func (s *smtpServer) monitorDisconnectedUsers() {
for address := range ch { for address := range ch {
log.Info("Disconnecting all open SMTP connections for ", address) log.Info("Disconnecting all open SMTP connections for ", address)
disconnectUser := func(conn *goSMTP.Conn) { disconnectUser := func(conn *goSMTP.Conn) {
connUser := conn.User() connUser := conn.Session()
if connUser != nil { if connUser != nil {
_ = conn.Close() if err := conn.Close(); err != nil {
log.WithError(err).Error("Failed to close the connection")
}
} }
} }
s.server.ForEachConn(disconnectUser) s.server.ForEachConn(disconnectUser)

View File

@ -44,7 +44,11 @@ type smtpUser struct {
backend *smtpBackend backend *smtpBackend
user bridgeUser user bridgeUser
storeUser storeUserProvider storeUser storeUserProvider
username string
addressID string addressID string
from string
to []string
} }
// newSMTPUser returns struct implementing go-smtp/session interface. // newSMTPUser returns struct implementing go-smtp/session interface.
@ -53,8 +57,9 @@ func newSMTPUser(
eventListener listener.Listener, eventListener listener.Listener,
smtpBackend *smtpBackend, smtpBackend *smtpBackend,
user bridgeUser, user bridgeUser,
username string,
addressID string, addressID string,
) (goSMTPBackend.User, error) { ) (goSMTPBackend.Session, error) {
storeUser := user.GetStore() storeUser := user.GetStore()
if storeUser == nil { if storeUser == nil {
return nil, errors.New("user database is not initialized") return nil, errors.New("user database is not initialized")
@ -66,6 +71,7 @@ func newSMTPUser(
backend: smtpBackend, backend: smtpBackend,
user: user, user: user,
storeUser: storeUser, storeUser: storeUser,
username: username,
addressID: addressID, addressID: addressID,
}, nil }, nil
} }
@ -145,6 +151,55 @@ func (su *smtpUser) getAPIKeyData(recipient string) (apiKeys []pmapi.PublicKey,
return su.client().GetPublicKeysForEmail(recipient) return su.client().GetPublicKeysForEmail(recipient)
} }
// Discard currently processed message.
func (su *smtpUser) Reset() {
log.Trace("Resetting the session")
su.from = ""
su.to = []string{}
}
// Set return path for currently processed message.
func (su *smtpUser) Mail(from string, opts goSMTPBackend.MailOptions) error {
log.WithField("from", from).WithField("opts", opts).Trace("Setting mail from")
// REQUIRETLS and SMTPUTF8 have to be announced to be used by client.
// Bridge does not use those extensions so this should not happen.
if opts.RequireTLS {
return errors.New("REQUIRETLS extension is not supported")
}
if opts.UTF8 {
return errors.New("SMTPUTF8 extension is not supported")
}
if opts.Auth != nil && *opts.Auth != "" && *opts.Auth != su.username {
return errors.New("changing identity is not supported")
}
su.from = from
return nil
}
// Add recipient for currently processed message.
func (su *smtpUser) Rcpt(to string) error {
log.WithField("to", to).Trace("Adding recipient")
if to != "" {
su.to = append(su.to, to)
}
return nil
}
// Set currently processed message contents and send it.
func (su *smtpUser) Data(r io.Reader) error {
log.Trace("Sending the message")
if su.from == "" {
return errors.New("missing sender")
}
if len(su.to) == 0 {
return errors.New("missing recipient")
}
return su.Send(su.from, su.to, r)
}
// Send sends an email from the given address to the given addresses with the given body. // Send sends an email from the given address to the given addresses with the given body.
func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err error) { //nolint[funlen] func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err error) { //nolint[funlen]
// Called from go-smtp in goroutines - we need to handle panics for each function. // Called from go-smtp in goroutines - we need to handle panics for each function.

View File

@ -1,29 +1,29 @@
Feature: SMTP auth Feature: SMTP auth
Scenario: Ask EHLO Scenario: Ask EHLO
Given there is connected user "user" Given there is connected user "user"
When SMTP client sends EHLO When SMTP client sends "EHLO example.com"
Then SMTP response is "OK" Then SMTP response is "OK"
Scenario: Authenticates successfully and EHLO successfully Scenario: Authenticates successfully and EHLO successfully
Given there is connected user "user" Given there is connected user "user"
When SMTP client authenticates "user" When SMTP client authenticates "user"
Then SMTP response is "OK" Then SMTP response is "OK"
When SMTP client sends EHLO When SMTP client sends "EHLO example.com"
Then SMTP response is "OK" Then SMTP response is "OK"
Scenario: Authenticates with bad password Scenario: Authenticates with bad password
Given there is connected user "user" Given there is connected user "user"
When SMTP client authenticates "user" with bad password When SMTP client authenticates "user" with bad password
Then SMTP response is "SMTP error: 454 backend/credentials: incorrect password" Then SMTP response is "SMTP error: 454 4.7.0 backend/credentials: incorrect password"
Scenario: Authenticates with disconnected user Scenario: Authenticates with disconnected user
Given there is disconnected user "user" Given there is disconnected user "user"
When SMTP client authenticates "user" When SMTP client authenticates "user"
Then SMTP response is "SMTP error: 454 account is logged out, use the app to login again" Then SMTP response is "SMTP error: 454 4.7.0 account is logged out, use the app to login again"
Scenario: Authenticates with no user Scenario: Authenticates with no user
When SMTP client authenticates with username "user@pm.me" and password "bridgepassword" When SMTP client authenticates with username "user@pm.me" and password "bridgepassword"
Then SMTP response is "SMTP error: 454 user user@pm.me not found" Then SMTP response is "SMTP error: 454 4.7.0 user user@pm.me not found"
Scenario: Authenticates with capital letter Scenario: Authenticates with capital letter
Given there is connected user "userAddressWithCapitalLetter" Given there is connected user "userAddressWithCapitalLetter"
@ -43,7 +43,7 @@ Feature: SMTP auth
Scenario: Authenticates with more addresses - disabled address Scenario: Authenticates with more addresses - disabled address
Given there is connected user "userMoreAddresses" Given there is connected user "userMoreAddresses"
When SMTP client authenticates "userMoreAddresses" with address "disabled" When SMTP client authenticates "userMoreAddresses" with address "disabled"
Then SMTP response is "SMTP error: 454 user .* not found" Then SMTP response is "SMTP error: 454 4.7.0 user .* not found"
@ignore-live @ignore-live
Scenario: Authenticates with secondary address of account with disabled primary address Scenario: Authenticates with secondary address of account with disabled primary address

View File

@ -0,0 +1,83 @@
Feature: SMTP initiation
Scenario: Empty FROM
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<>"
Then SMTP response is "OK"
Scenario: Send without FROM and TO
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "SMTP error: 502 5.5.1 Missing RCPT TO command."
Scenario: Reset is the same as without FROM and TO
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me>"
Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<user@pm.me>"
Then SMTP response is "OK"
When SMTP client sends "RSET"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "SMTP error: 502 5.5.1 Missing RCPT TO command"
Scenario: Send without FROM
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<user@pm.me>"
Then SMTP response is "SMTP error: 502 5.5.1 Missing MAIL FROM command."
Scenario: Send without TO
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me>"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "SMTP error: 502 5.5.1 Missing RCPT TO command."
Scenario: Send with empty FROM
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<>"
Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<user@pm.me>"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "OK"
When SMTP client sends "hello\r\n."
Then SMTP response is "SMTP error: 554 5.0.0 Error: transaction failed, blame it on the weather: missing sender"
Scenario: Send with empty TO
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me>"
Then SMTP response is "OK"
When SMTP client sends "RCPT TO:<>"
Then SMTP response is "OK"
When SMTP client sends "DATA"
Then SMTP response is "OK"
When SMTP client sends "hello\r\n."
Then SMTP response is "SMTP error: 554 5.0.0 Error: transaction failed, blame it on the weather: missing recipient"
Scenario: Allow BODY parameter of MAIL FROM command
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me> BODY=7BIT"
Then SMTP response is "OK"
Scenario: Allow AUTH parameter of MAIL FROM command
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
When SMTP client sends "MAIL FROM:<user@pm.me> AUTH=<>"
Then SMTP response is "OK"

View File

@ -38,4 +38,4 @@ Feature: SMTP wrong messages
""" """
Then SMTP response is "SMTP error: 554 Error: transaction failed, blame it on the weather: failed to create new parser: unexpected EOF" Then SMTP response is "SMTP error: 554 5.0.0 Error: transaction failed, blame it on the weather: failed to create new parser: unexpected EOF"

View File

@ -33,10 +33,10 @@ func SMTPActionsAuthFeatureContext(s *godog.Suite) {
s.Step(`^SMTP client authenticates with username "([^"]*)" and password "([^"]*)"$`, smtpClientAuthenticatesWithUsernameAndPassword) s.Step(`^SMTP client authenticates with username "([^"]*)" and password "([^"]*)"$`, smtpClientAuthenticatesWithUsernameAndPassword)
s.Step(`^SMTP client logs out$`, smtpClientLogsOut) s.Step(`^SMTP client logs out$`, smtpClientLogsOut)
s.Step(`^SMTP client sends message$`, smtpClientSendsMessage) s.Step(`^SMTP client sends message$`, smtpClientSendsMessage)
s.Step(`^SMTP client sends EHLO$`, smtpClientSendsEHLO)
s.Step(`^SMTP client "([^"]*)" sends message$`, smtpClientNamedSendsMessage) s.Step(`^SMTP client "([^"]*)" sends message$`, smtpClientNamedSendsMessage)
s.Step(`^SMTP client sends message with bcc "([^"]*)"$`, smtpClientSendsMessageWithBCC) s.Step(`^SMTP client sends message with bcc "([^"]*)"$`, smtpClientSendsMessageWithBCC)
s.Step(`^SMTP client "([^"]*)" sends message with bcc "([^"]*)"$`, smtpClientNamedSendsMessageWithBCC) s.Step(`^SMTP client "([^"]*)" sends message with bcc "([^"]*)"$`, smtpClientNamedSendsMessageWithBCC)
s.Step(`^SMTP client sends "([^"]*)"$`, smtpClientSendsCommand)
} }
func smtpClientAuthenticates(bddUserID string) error { func smtpClientAuthenticates(bddUserID string) error {
@ -93,12 +93,6 @@ func smtpClientSendsMessage(message *gherkin.DocString) error {
return smtpClientNamedSendsMessage("smtp", message) return smtpClientNamedSendsMessage("smtp", message)
} }
func smtpClientSendsEHLO() error {
res := ctx.GetSMTPClient("smtp").SendCommands("EHLO ateist.test")
ctx.SetSMTPLastResponse("smtp", res)
return nil
}
func smtpClientNamedSendsMessage(clientID string, message *gherkin.DocString) error { func smtpClientNamedSendsMessage(clientID string, message *gherkin.DocString) error {
return smtpClientNamedSendsMessageWithBCC(clientID, "", message) return smtpClientNamedSendsMessageWithBCC(clientID, "", message)
} }
@ -112,3 +106,11 @@ func smtpClientNamedSendsMessageWithBCC(clientID, bcc string, message *gherkin.D
ctx.SetSMTPLastResponse(clientID, res) ctx.SetSMTPLastResponse(clientID, res)
return nil return nil
} }
func smtpClientSendsCommand(command string) error {
command = strings.ReplaceAll(command, "\\r", "\r")
command = strings.ReplaceAll(command, "\\n", "\n")
res := ctx.GetSMTPClient("smtp").SendCommands(command)
ctx.SetSMTPLastResponse("smtp", res)
return nil
}

View File

@ -11,3 +11,7 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
### Removed ### Removed
* GODT-651 Build creates proper binary names. * GODT-651 Build creates proper binary names.
* GODT-148 Allow import (using the Import-Export app) of already encrypted messages as is. * GODT-148 Allow import (using the Import-Export app) of already encrypted messages as is.
* GODT-202 Update to latest go-smtp.
### Fixed
* GODT-135 Support parameters in SMTP `FROM MAIL` command, such as `BODY=7BIT`, or empty value `FROM MAIL:<>` used by some clients.