diff --git a/notify/email/email.go b/notify/email/email.go index 73fcf577..33225403 100644 --- a/notify/email/email.go +++ b/notify/email/email.go @@ -18,6 +18,7 @@ import ( "context" "crypto/tls" "fmt" + "math/rand" "mime" "mime/multipart" "mime/quotedprintable" @@ -25,6 +26,7 @@ import ( "net/mail" "net/smtp" "net/textproto" + "os" "strings" "time" @@ -41,9 +43,10 @@ import ( // Email implements a Notifier for email notifications. type Email struct { - conf *config.EmailConfig - tmpl *template.Template - logger log.Logger + conf *config.EmailConfig + tmpl *template.Template + logger log.Logger + hostname string } // New returns a new Email notifier. @@ -57,7 +60,13 @@ func New(c *config.EmailConfig, t *template.Template, l log.Logger) *Email { if _, ok := c.Headers["From"]; !ok { c.Headers["From"] = c.From } - return &Email{conf: c, tmpl: t, logger: l} + + h, err := os.Hostname() + // If we can't get the hostname, we'll use localhost + if err != nil { + h = "localhost.localdomain" + } + return &Email{conf: c, tmpl: t, logger: l, hostname: h} } // auth resolves a string of authentication mechanisms. @@ -236,6 +245,10 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { fmt.Fprintf(buffer, "%s: %s\r\n", header, mime.QEncoding.Encode("utf-8", value)) } + if _, ok := n.conf.Headers["Message-Id"]; !ok { + fmt.Fprintf(buffer, "Message-Id: %s\r\n", fmt.Sprintf("<%d.%d@%s>", time.Now().UnixNano(), rand.Uint64(), n.hostname)) + } + multipartBuffer := &bytes.Buffer{} multipartWriter := multipart.NewWriter(multipartBuffer) diff --git a/notify/email/email_test.go b/notify/email/email_test.go index 595d9912..0d1720b9 100644 --- a/notify/email/email_test.go +++ b/notify/email/email_test.go @@ -356,7 +356,7 @@ func TestEmailNotifyWithoutAuthentication(t *testing.T) { t.Fatal(err) } - _, _, err = notifyEmail( + mail, _, err := notifyEmail( &config.EmailConfig{ Smarthost: c.Smarthost, To: emailTo, @@ -367,6 +367,18 @@ func TestEmailNotifyWithoutAuthentication(t *testing.T) { c.Server, ) require.NoError(t, err) + var ( + foundMsgID bool + headers []string + ) + for k := range mail.Headers { + if strings.ToLower(k) == "message-id" { + foundMsgID = true + break + } + headers = append(headers, k) + } + require.True(t, foundMsgID, "Couldn't find 'message-id' in %v", headers) } // TestEmailNotifyWithSTARTTLS connects to the server, upgrades the connection