From 9dcd716f91262b3709fcbddf25458fe49a442a0a Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Wed, 1 Apr 2020 19:56:40 +0530 Subject: [PATCH] Add support for SMTP 'LOGIN' auth --- config.toml.sample | 2 +- internal/messenger/emailer.go | 37 +++++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/config.toml.sample b/config.toml.sample index 93545f0..962c4ca 100644 --- a/config.toml.sample +++ b/config.toml.sample @@ -79,7 +79,7 @@ max_idle = 10 host = "my.smtp.server" port = "25" - # cram | plain | empty for no auth + # "cram", "plain", or "login". Empty string for no auth. auth_protocol = "cram" username = "xxxxx" password = "" diff --git a/internal/messenger/emailer.go b/internal/messenger/emailer.go index 36f1291..7e22fc8 100644 --- a/internal/messenger/emailer.go +++ b/internal/messenger/emailer.go @@ -1,6 +1,7 @@ package messenger import ( + "errors" "fmt" "math/rand" "net/smtp" @@ -11,6 +12,12 @@ import ( const emName = "email" +// loginAuth is used for enabling SMTP "LOGIN" auth. +type loginAuth struct { + username string + password string +} + // Server represents an SMTP server's credentials. type Server struct { Name string @@ -42,10 +49,16 @@ func NewEmailer(srv ...Server) (Messenger, error) { for _, server := range srv { s := server var auth smtp.Auth - if s.AuthProtocol == "cram" { + switch s.AuthProtocol { + case "cram": auth = smtp.CRAMMD5Auth(s.Username, s.Password) - } else if s.AuthProtocol == "plain" { + case "plain": auth = smtp.PlainAuth("", s.Username, s.Password, s.Host) + case "login": + auth = &loginAuth{username: s.Username, password: s.Password} + case "": + default: + return nil, fmt.Errorf("unknown SMTP auth typer '%s'", s.AuthProtocol) } pool, err := email.NewPool(fmt.Sprintf("%s:%d", s.Host, s.Port), s.MaxConns, auth) @@ -115,3 +128,23 @@ func (e *emailer) Push(fromAddr string, toAddr []string, subject string, m []byt func (e *emailer) Flush() error { return nil } + +// https://gist.github.com/andelf/5118732 +// Adds support for SMTP LOGIN auth. +func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) { + 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 SMTP fromServer") + } + } + return nil, nil +}