Wrap email errs (#884)

* wrap errors returned by SMTP client

* remove client hello
This commit is contained in:
Victor Vrantchan 2017-01-10 23:56:32 -05:00 committed by GitHub
parent efca0947ec
commit f276ff3d90

View File

@ -7,6 +7,7 @@ import (
"net/smtp" "net/smtp"
"github.com/kolide/kolide-ose/server/kolide" "github.com/kolide/kolide-ose/server/kolide"
"github.com/pkg/errors"
) )
func NewService() kolide.MailService { func NewService() kolide.MailService {
@ -27,11 +28,17 @@ type sender interface {
func Test(mailer kolide.MailService, e kolide.Email) error { func Test(mailer kolide.MailService, e kolide.Email) error {
mailBody, err := getMessageBody(e) mailBody, err := getMessageBody(e)
if err != nil { if err != nil {
return err return errors.Wrap(err, "failed to get message body")
} }
if svc, ok := mailer.(sender); ok { svc, ok := mailer.(sender)
return svc.sendMail(e, mailBody) if !ok {
return nil
}
err = svc.sendMail(e, mailBody)
if err != nil {
return errors.Wrap(err, "sending mail")
} }
return nil return nil
@ -45,7 +52,7 @@ const (
func getMessageBody(e kolide.Email) ([]byte, error) { func getMessageBody(e kolide.Email) ([]byte, error) {
body, err := e.Mailer.Message() body, err := e.Mailer.Message()
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "get mailer message")
} }
mime := `MIME-version: 1.0;` + "\r\n" mime := `MIME-version: 1.0;` + "\r\n"
content := `Content-Type: text/html; charset="UTF-8";` + "\r\n" content := `Content-Type: text/html; charset="UTF-8";` + "\r\n"
@ -74,31 +81,42 @@ func (m mailService) SendEmail(e kolide.Email) error {
return m.sendMail(e, msg) return m.sendMail(e, msg)
} }
func smtpAuth(e kolide.Email) (smtp.Auth, error) {
if e.Config.SMTPAuthenticationType != kolide.AuthTypeUserNamePassword {
return nil, nil
}
var auth smtp.Auth
switch e.Config.SMTPAuthenticationMethod {
case kolide.AuthMethodCramMD5:
auth = smtp.CRAMMD5Auth(e.Config.SMTPUserName, e.Config.SMTPPassword)
case kolide.AuthMethodPlain:
auth = smtp.PlainAuth("", e.Config.SMTPUserName, e.Config.SMTPPassword, e.Config.SMTPServer)
default:
return nil, fmt.Errorf("unknown SMTP auth type '%d'", e.Config.SMTPAuthenticationMethod)
}
return auth, nil
}
func (m mailService) sendMail(e kolide.Email, msg []byte) error { func (m mailService) sendMail(e kolide.Email, msg []byte) error {
smtpHost := fmt.Sprintf("%s:%d", e.Config.SMTPServer, e.Config.SMTPPort) smtpHost := fmt.Sprintf("%s:%d", e.Config.SMTPServer, e.Config.SMTPPort)
var auth smtp.Auth auth, err := smtpAuth(e)
if e.Config.SMTPAuthenticationType == kolide.AuthTypeUserNamePassword { if err != nil {
switch e.Config.SMTPAuthenticationMethod { return errors.Wrap(err, "failed to get smtp auth")
case kolide.AuthMethodCramMD5:
auth = smtp.CRAMMD5Auth(e.Config.SMTPUserName, e.Config.SMTPPassword)
return smtp.SendMail(smtpHost, auth, e.Config.SMTPSenderAddress, e.To, msg)
case kolide.AuthMethodPlain:
auth = smtp.PlainAuth("", e.Config.SMTPUserName, e.Config.SMTPPassword, e.Config.SMTPServer)
default:
return fmt.Errorf("Unknown SMTP auth type '%d'", e.Config.SMTPAuthenticationMethod)
}
} else {
auth = nil
} }
if e.Config.SMTPAuthenticationMethod == kolide.AuthMethodCramMD5 {
err = smtp.SendMail(smtpHost, auth, e.Config.SMTPSenderAddress, e.To, msg)
if err != nil {
return errors.Wrap(err, "failed to send mail. cramd5 auth method")
}
return nil
}
client, err := smtp.Dial(smtpHost) client, err := smtp.Dial(smtpHost)
if err != nil { if err != nil {
return err return errors.Wrap(err, "could not dial smtp host")
} }
defer client.Close() defer client.Close()
if err = client.Hello(""); err != nil {
return err
}
if e.Config.SMTPEnableStartTLS { if e.Config.SMTPEnableStartTLS {
if ok, _ := client.Extension("STARTTLS"); ok { if ok, _ := client.Extension("STARTTLS"); ok {
config := &tls.Config{ config := &tls.Config{
@ -106,30 +124,34 @@ func (m mailService) sendMail(e kolide.Email, msg []byte) error {
InsecureSkipVerify: !e.Config.SMTPVerifySSLCerts, InsecureSkipVerify: !e.Config.SMTPVerifySSLCerts,
} }
if err = client.StartTLS(config); err != nil { if err = client.StartTLS(config); err != nil {
return err return errors.Wrap(err, "startTLS error")
} }
} }
} }
if auth != nil { if auth != nil {
if err = client.Auth(auth); err != nil { if err = client.Auth(auth); err != nil {
return err return errors.Wrap(err, "client auth error")
} }
} }
if err = client.Mail(e.Config.SMTPSenderAddress); err != nil { if err = client.Mail(e.Config.SMTPSenderAddress); err != nil {
return err return errors.Wrap(err, "could not issue mail to provided address")
} }
for _, recip := range e.To { for _, recip := range e.To {
if err = client.Rcpt(recip); err != nil { if err = client.Rcpt(recip); err != nil {
return err return errors.Wrap(err, "failed to get recipient")
} }
} }
writer, err := client.Data() writer, err := client.Data()
if err != nil { if err != nil {
return nil return errors.Wrap(err, "getting client data")
} }
_, err = writer.Write(msg) _, err = writer.Write(msg)
if err = writer.Close(); err != nil { if err = writer.Close(); err != nil {
return err return errors.Wrap(err, "failed to close writer")
} }
return client.Quit()
if err := client.Quit(); err != nil {
return errors.Wrap(err, "error on client quit")
}
return nil
} }