From f276ff3d903b6ab4a0535c3f0bb3d60df070d451 Mon Sep 17 00:00:00 2001 From: Victor Vrantchan Date: Tue, 10 Jan 2017 23:56:32 -0500 Subject: [PATCH] Wrap email errs (#884) * wrap errors returned by SMTP client * remove client hello --- server/mail/mail.go | 80 +++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/server/mail/mail.go b/server/mail/mail.go index f0d35f6416..478c3f98b7 100644 --- a/server/mail/mail.go +++ b/server/mail/mail.go @@ -7,6 +7,7 @@ import ( "net/smtp" "github.com/kolide/kolide-ose/server/kolide" + "github.com/pkg/errors" ) func NewService() kolide.MailService { @@ -27,11 +28,17 @@ type sender interface { func Test(mailer kolide.MailService, e kolide.Email) error { mailBody, err := getMessageBody(e) if err != nil { - return err + return errors.Wrap(err, "failed to get message body") } - if svc, ok := mailer.(sender); ok { - return svc.sendMail(e, mailBody) + svc, ok := mailer.(sender) + if !ok { + return nil + } + + err = svc.sendMail(e, mailBody) + if err != nil { + return errors.Wrap(err, "sending mail") } return nil @@ -45,7 +52,7 @@ const ( func getMessageBody(e kolide.Email) ([]byte, error) { body, err := e.Mailer.Message() if err != nil { - return nil, err + return nil, errors.Wrap(err, "get mailer message") } mime := `MIME-version: 1.0;` + "\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) } +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 { smtpHost := fmt.Sprintf("%s:%d", e.Config.SMTPServer, e.Config.SMTPPort) - var auth smtp.Auth - if e.Config.SMTPAuthenticationType == kolide.AuthTypeUserNamePassword { - switch e.Config.SMTPAuthenticationMethod { - 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 + auth, err := smtpAuth(e) + if err != nil { + return errors.Wrap(err, "failed to get smtp auth") } + + 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) if err != nil { - return err + return errors.Wrap(err, "could not dial smtp host") } defer client.Close() - if err = client.Hello(""); err != nil { - return err - } if e.Config.SMTPEnableStartTLS { if ok, _ := client.Extension("STARTTLS"); ok { config := &tls.Config{ @@ -106,30 +124,34 @@ func (m mailService) sendMail(e kolide.Email, msg []byte) error { InsecureSkipVerify: !e.Config.SMTPVerifySSLCerts, } if err = client.StartTLS(config); err != nil { - return err + return errors.Wrap(err, "startTLS error") } } } if auth != 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 { - return err + return errors.Wrap(err, "could not issue mail to provided address") } for _, recip := range e.To { if err = client.Rcpt(recip); err != nil { - return err + return errors.Wrap(err, "failed to get recipient") } } writer, err := client.Data() if err != nil { - return nil + return errors.Wrap(err, "getting client data") } _, err = writer.Write(msg) 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 }