summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorCarlos Tadeu Panato Junior <ctadeu@gmail.com>2018-03-01 12:58:35 +0100
committerGitHub <noreply@github.com>2018-03-01 12:58:35 +0100
commit4b5541db46d75182a7a83b1361ed785b401b9118 (patch)
tree2f2a8f985f9e88770c253196e6d8313ac3a102cf /utils
parent6e024c45b50d31c20eb0d509263d3e0f888847de (diff)
downloadchat-4b5541db46d75182a7a83b1361ed785b401b9118.tar.gz
chat-4b5541db46d75182a7a83b1361ed785b401b9118.tar.bz2
chat-4b5541db46d75182a7a83b1361ed785b401b9118.zip
[PLT-8024] Support LOGIN authentication method for SMTP (#8140)
* [PLT-8024] Support LOGIN authentication method for SMTP * added initial unit tests
Diffstat (limited to 'utils')
-rw-r--r--utils/mail.go58
-rw-r--r--utils/mail_test.go64
2 files changed, 117 insertions, 5 deletions
diff --git a/utils/mail.go b/utils/mail.go
index 9023f7090..2bc0ce9e1 100644
--- a/utils/mail.go
+++ b/utils/mail.go
@@ -5,6 +5,8 @@ package utils
import (
"crypto/tls"
+ "errors"
+ "io"
"mime"
"net"
"net/mail"
@@ -15,8 +17,6 @@ import (
"net/http"
- "io"
-
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/html2text"
"github.com/mattermost/mattermost-server/model"
@@ -26,6 +26,56 @@ func encodeRFC2047Word(s string) string {
return mime.BEncoding.Encode("utf-8", s)
}
+type authChooser struct {
+ smtp.Auth
+ Config *model.Config
+}
+
+func (a *authChooser) Start(server *smtp.ServerInfo) (string, []byte, error) {
+ a.Auth = LoginAuth(a.Config.EmailSettings.SMTPUsername, a.Config.EmailSettings.SMTPPassword, a.Config.EmailSettings.SMTPServer+":"+a.Config.EmailSettings.SMTPPort)
+ for _, method := range server.Auth {
+ if method == "PLAIN" {
+ a.Auth = smtp.PlainAuth("", a.Config.EmailSettings.SMTPUsername, a.Config.EmailSettings.SMTPPassword, a.Config.EmailSettings.SMTPServer+":"+a.Config.EmailSettings.SMTPPort)
+ break
+ }
+ }
+ return a.Auth.Start(server)
+}
+
+type loginAuth struct {
+ username, password, host string
+}
+
+func LoginAuth(username, password, host string) smtp.Auth {
+ return &loginAuth{username, password, host}
+}
+
+func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
+ if !server.TLS {
+ return "", nil, errors.New("unencrypted connection")
+ }
+
+ if server.Name != a.host {
+ return "", nil, errors.New("wrong host name")
+ }
+
+ return "LOGIN", []byte{}, nil
+}
+
+func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
+ if more {
+ switch string(fromServer) {
+ case "Username:":
+ return []byte(a.username), nil
+ case "Password:":
+ return []byte(a.password), nil
+ default:
+ return nil, errors.New("Unkown fromServer")
+ }
+ }
+ return nil, nil
+}
+
func connectToSMTPServer(config *model.Config) (net.Conn, *model.AppError) {
var conn net.Conn
var err error
@@ -75,9 +125,7 @@ func newSMTPClient(conn net.Conn, config *model.Config) (*smtp.Client, *model.Ap
}
if *config.EmailSettings.EnableSMTPAuth {
- auth := smtp.PlainAuth("", config.EmailSettings.SMTPUsername, config.EmailSettings.SMTPPassword, config.EmailSettings.SMTPServer+":"+config.EmailSettings.SMTPPort)
-
- if err = c.Auth(auth); err != nil {
+ if err = c.Auth(&authChooser{Config: config}); err != nil {
return nil, model.NewAppError("SendMail", "utils.mail.new_client.auth.app_error", nil, err.Error(), http.StatusInternalServerError)
}
}
diff --git a/utils/mail_test.go b/utils/mail_test.go
index 068c90c60..31a4f8996 100644
--- a/utils/mail_test.go
+++ b/utils/mail_test.go
@@ -7,6 +7,9 @@ import (
"strings"
"testing"
+ "net/smtp"
+
+ "github.com/mattermost/mattermost-server/model"
"github.com/stretchr/testify/require"
)
@@ -169,3 +172,64 @@ func TestSendMailUsingConfig(t *testing.T) {
}
}
}*/
+
+func TestAuthMethods(t *testing.T) {
+ config := model.Config{
+ EmailSettings: model.EmailSettings{
+ EnableSMTPAuth: model.NewBool(false),
+ SMTPUsername: "test",
+ SMTPPassword: "fakepass",
+ SMTPServer: "fakeserver",
+ SMTPPort: "25",
+ },
+ }
+
+ auth := &authChooser{Config: &config}
+ tests := []struct {
+ desc string
+ server *smtp.ServerInfo
+ err string
+ }{
+ {
+ desc: "auth PLAIN success",
+ server: &smtp.ServerInfo{Name: "fakeserver:25", Auth: []string{"PLAIN"}, TLS: true},
+ },
+ {
+ desc: "auth PLAIN unencrypted connection fail",
+ server: &smtp.ServerInfo{Name: "fakeserver:25", Auth: []string{"PLAIN"}, TLS: false},
+ err: "unencrypted connection",
+ },
+ {
+ desc: "auth PLAIN wrong host name",
+ server: &smtp.ServerInfo{Name: "wrongServer:999", Auth: []string{"PLAIN"}, TLS: true},
+ err: "wrong host name",
+ },
+ {
+ desc: "auth LOGIN success",
+ server: &smtp.ServerInfo{Name: "fakeserver:25", Auth: []string{"LOGIN"}, TLS: true},
+ },
+ {
+ desc: "auth LOGIN unencrypted connection fail",
+ server: &smtp.ServerInfo{Name: "wrongServer:999", Auth: []string{"LOGIN"}, TLS: true},
+ err: "wrong host name",
+ },
+ {
+ desc: "auth LOGIN wrong host name",
+ server: &smtp.ServerInfo{Name: "fakeserver:25", Auth: []string{"LOGIN"}, TLS: false},
+ err: "unencrypted connection",
+ },
+ }
+
+ for i, test := range tests {
+ t.Run(test.desc, func(t *testing.T) {
+ _, _, err := auth.Start(test.server)
+ got := ""
+ if err != nil {
+ got = err.Error()
+ }
+ if got != test.err {
+ t.Errorf("%d. got error = %q; want %q", i, got, test.err)
+ }
+ })
+ }
+}