diff --git a/go.mod b/go.mod
index 06851867..1eef68f5 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,6 @@ go 1.13
// They are in a separate require block to highlight this.
require (
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
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-message v0.12.1-0.20200903165315-e1abe21f389a
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-vcard v0.0.0-20190105225839-8856043f13c5 // indirect
github.com/fatih/color v1.9.0
@@ -75,7 +75,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-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
golang.org/x/crypto => github.com/ProtonMail/crypto v0.0.0-20200818122824-ed5d25e28db8
)
diff --git a/go.sum b/go.sum
index bd9323b0..6380ce30 100644
--- a/go.sum
+++ b/go.sum
@@ -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-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 h1:40SWqY0zE3qCi6ZrtTf5OUdNm5lDnGnjRSq9GgmeTrg=
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=
diff --git a/internal/bridge/credits.go b/internal/bridge/credits.go
index 5913ab56..2aa22075 100644
--- a/internal/bridge/credits.go
+++ b/internal/bridge/credits.go
@@ -15,8 +15,8 @@
// You should have received a copy of the GNU General Public License
// along with ProtonMail Bridge. If not, see .
-// 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
-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;"
diff --git a/internal/imap/server.go b/internal/imap/server.go
index 0628d77e..b3351e1a 100644
--- a/internal/imap/server.go
+++ b/internal/imap/server.go
@@ -126,7 +126,9 @@ func (s *imapServer) ListenAndServe() {
// Stops the server.
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() {
@@ -139,7 +141,9 @@ func (s *imapServer) monitorDisconnectedUsers() {
disconnectUser := func(conn imapserver.Conn) {
connUser := conn.Context().User
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)
diff --git a/internal/importexport/credits.go b/internal/importexport/credits.go
index 9b29292b..b582f358 100644
--- a/internal/importexport/credits.go
+++ b/internal/importexport/credits.go
@@ -15,8 +15,8 @@
// You should have received a copy of the GNU General Public License
// along with ProtonMail Bridge. If not, see .
-// 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
-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;"
diff --git a/internal/smtp/backend.go b/internal/smtp/backend.go
index eae408ee..0611285a 100644
--- a/internal/smtp/backend.go
+++ b/internal/smtp/backend.go
@@ -27,6 +27,7 @@ import (
"github.com/ProtonMail/proton-bridge/pkg/confirmer"
"github.com/ProtonMail/proton-bridge/pkg/listener"
goSMTPBackend "github.com/emersion/go-smtp"
+ "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -70,7 +71,7 @@ func newSMTPBackend(
}
// 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.
defer sb.panicHandler.HandlePanic()
username = strings.ToLower(username)
@@ -97,7 +98,14 @@ func (sb *smtpBackend) Login(username, password string) (goSMTPBackend.User, err
if user.IsCombinedAddressMode() {
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 {
diff --git a/internal/smtp/server.go b/internal/smtp/server.go
index ad06bf5d..f60b8531 100644
--- a/internal/smtp/server.go
+++ b/internal/smtp/server.go
@@ -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 {
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 {
return err
}
- conn.SetUser(user)
+ conn.SetSession(user)
return nil
})
})
@@ -85,14 +85,16 @@ func (s *smtpServer) ListenAndServe() {
l.Error("SMTP failed: ", err)
return
}
- defer s.server.Close()
+ defer s.server.Close() //nolint[errcheck]
l.Info("SMTP server stopped")
}
// Stops the server.
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() {
@@ -102,9 +104,11 @@ func (s *smtpServer) monitorDisconnectedUsers() {
for address := range ch {
log.Info("Disconnecting all open SMTP connections for ", address)
disconnectUser := func(conn *goSMTP.Conn) {
- connUser := conn.User()
+ connUser := conn.Session()
if connUser != nil {
- _ = conn.Close()
+ if err := conn.Close(); err != nil {
+ log.WithError(err).Error("Failed to close the connection")
+ }
}
}
s.server.ForEachConn(disconnectUser)
diff --git a/internal/smtp/user.go b/internal/smtp/user.go
index b438256c..5442647c 100644
--- a/internal/smtp/user.go
+++ b/internal/smtp/user.go
@@ -44,7 +44,11 @@ type smtpUser struct {
backend *smtpBackend
user bridgeUser
storeUser storeUserProvider
+ username string
addressID string
+
+ from string
+ to []string
}
// newSMTPUser returns struct implementing go-smtp/session interface.
@@ -53,8 +57,9 @@ func newSMTPUser(
eventListener listener.Listener,
smtpBackend *smtpBackend,
user bridgeUser,
+ username string,
addressID string,
-) (goSMTPBackend.User, error) {
+) (goSMTPBackend.Session, error) {
storeUser := user.GetStore()
if storeUser == nil {
return nil, errors.New("user database is not initialized")
@@ -66,6 +71,7 @@ func newSMTPUser(
backend: smtpBackend,
user: user,
storeUser: storeUser,
+ username: username,
addressID: addressID,
}, nil
}
@@ -145,6 +151,55 @@ func (su *smtpUser) getAPIKeyData(recipient string) (apiKeys []pmapi.PublicKey,
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.
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.
diff --git a/test/features/bridge/smtp/auth.feature b/test/features/bridge/smtp/auth.feature
index cfa2bf34..7c4188d3 100644
--- a/test/features/bridge/smtp/auth.feature
+++ b/test/features/bridge/smtp/auth.feature
@@ -1,29 +1,29 @@
Feature: SMTP auth
Scenario: Ask EHLO
Given there is connected user "user"
- When SMTP client sends EHLO
+ When SMTP client sends "EHLO example.com"
Then SMTP response is "OK"
Scenario: Authenticates successfully and EHLO successfully
Given there is connected user "user"
When SMTP client authenticates "user"
Then SMTP response is "OK"
- When SMTP client sends EHLO
+ When SMTP client sends "EHLO example.com"
Then SMTP response is "OK"
Scenario: Authenticates with bad password
Given there is connected user "user"
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
Given there is disconnected user "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
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
Given there is connected user "userAddressWithCapitalLetter"
@@ -43,7 +43,7 @@ Feature: SMTP auth
Scenario: Authenticates with more addresses - disabled address
Given there is connected user "userMoreAddresses"
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
Scenario: Authenticates with secondary address of account with disabled primary address
diff --git a/test/features/bridge/smtp/init.feature b/test/features/bridge/smtp/init.feature
new file mode 100644
index 00000000..606fbe27
--- /dev/null
+++ b/test/features/bridge/smtp/init.feature
@@ -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:"
+ Then SMTP response is "OK"
+ When SMTP client sends "RCPT TO:"
+ 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:"
+ 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:"
+ 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:"
+ 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:"
+ 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: 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: AUTH=<>"
+ Then SMTP response is "OK"
diff --git a/test/features/bridge/smtp/send/failures.feature b/test/features/bridge/smtp/send/failures.feature
index f641dd2d..e4b62421 100644
--- a/test/features/bridge/smtp/send/failures.feature
+++ b/test/features/bridge/smtp/send/failures.feature
@@ -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"
diff --git a/test/smtp_actions_test.go b/test/smtp_actions_test.go
index 0283e404..6aa12e06 100644
--- a/test/smtp_actions_test.go
+++ b/test/smtp_actions_test.go
@@ -33,10 +33,10 @@ func SMTPActionsAuthFeatureContext(s *godog.Suite) {
s.Step(`^SMTP client authenticates with username "([^"]*)" and password "([^"]*)"$`, smtpClientAuthenticatesWithUsernameAndPassword)
s.Step(`^SMTP client logs out$`, smtpClientLogsOut)
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 with bcc "([^"]*)"$`, smtpClientSendsMessageWithBCC)
s.Step(`^SMTP client "([^"]*)" sends message with bcc "([^"]*)"$`, smtpClientNamedSendsMessageWithBCC)
+ s.Step(`^SMTP client sends "([^"]*)"$`, smtpClientSendsCommand)
}
func smtpClientAuthenticates(bddUserID string) error {
@@ -93,12 +93,6 @@ func smtpClientSendsMessage(message *gherkin.DocString) error {
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 {
return smtpClientNamedSendsMessageWithBCC(clientID, "", message)
}
@@ -112,3 +106,11 @@ func smtpClientNamedSendsMessageWithBCC(clientID, bcc string, message *gherkin.D
ctx.SetSMTPLastResponse(clientID, res)
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
+}
diff --git a/unreleased.md b/unreleased.md
index cacff4f6..a2189f06 100644
--- a/unreleased.md
+++ b/unreleased.md
@@ -11,3 +11,7 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
### Removed
* GODT-651 Build creates proper binary names.
* 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.