diff --git a/cmd/expiration-mailer/main.go b/cmd/expiration-mailer/main.go index bf56aea75..e9b976729 100644 --- a/cmd/expiration-mailer/main.go +++ b/cmd/expiration-mailer/main.go @@ -19,6 +19,7 @@ import ( "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli" "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock" "github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1" + "github.com/letsencrypt/boulder/cmd" "github.com/letsencrypt/boulder/core" blog "github.com/letsencrypt/boulder/log" @@ -72,7 +73,7 @@ func (m *mailer) sendNags(parsedCert *x509.Certificate, contacts []*core.AcmeURL return err } startSending := m.clk.Now() - err = m.mailer.SendMail(emails, msgBuf.String()) + err = m.mailer.SendMail(emails, "Certificate expiration notice", msgBuf.String()) if err != nil { m.stats.Inc("Mailer.Expiration.Errors.SendingNag.SendFailure", 1, 1.0) return err diff --git a/cmd/expiration-mailer/main_test.go b/cmd/expiration-mailer/main_test.go index 26ac81c17..d0a83576c 100644 --- a/cmd/expiration-mailer/main_test.go +++ b/cmd/expiration-mailer/main_test.go @@ -50,7 +50,7 @@ func (m *mockMail) Clear() { m.Messages = []string{} } -func (m *mockMail) SendMail(to []string, msg string) (err error) { +func (m *mockMail) SendMail(to []string, subject, msg string) (err error) { for range to { m.Messages = append(m.Messages, msg) } diff --git a/mail/mailer.go b/mail/mailer.go index dc3a6b366..094583c41 100644 --- a/mail/mailer.go +++ b/mail/mailer.go @@ -6,13 +6,17 @@ package mail import ( + "fmt" + "math/rand" "net" "net/smtp" + "strings" + "time" ) // Mailer provides the interface for a mailer type Mailer interface { - SendMail([]string, string) error + SendMail([]string, string, string) error } // MailerImpl defines a mail transfer agent to use for sending mail @@ -35,9 +39,26 @@ func New(server, port, username, password string) MailerImpl { } } +func (m *MailerImpl) generateMessage(to []string, subject, body string) []byte { + now := time.Now().UTC() + headers := []string{ + fmt.Sprintf("To: %s", strings.Join(to, ", ")), + fmt.Sprintf("From: %s", m.From), + fmt.Sprintf("Subject: %s", subject), + fmt.Sprintf("Date: %s", now.Format("Mon Jan 2 2006 15:04:05 -0700")), + fmt.Sprintf("Message-Id: <%s.%d.%s>", now.Format("20060102T150405"), rand.Int63(), m.From), + } + return []byte(fmt.Sprintf("%s\r\n\r\n%s\r\n", strings.Join(headers, "\r\n"), body)) +} + // SendMail sends an email to the provided list of recipients. The email body // is simple text. -func (m *MailerImpl) SendMail(to []string, msg string) (err error) { - err = smtp.SendMail(net.JoinHostPort(m.Server, m.Port), m.Auth, m.From, to, []byte(msg)) - return +func (m *MailerImpl) SendMail(to []string, subject, msg string) error { + return smtp.SendMail( + net.JoinHostPort(m.Server, m.Port), + m.Auth, + m.From, + to, + m.generateMessage(to, subject, msg), + ) }