From 5bea8e8c73511f90aa7c8b80fe49357862a84b92 Mon Sep 17 00:00:00 2001
From: Drew DeVault <sir@cmpwn.com>
Date: Mon, 6 Jan 2020 10:49:48 -0500
Subject: [PATCH] email: generate message ID headers
This GenerateMessageId is taken from go-message:
https://github.com/emersion/go-message/blob/master/mail/mail.go
I am the original author of this file; I agree to distribute it in
alertmanager regardless of the original license.
Signed-off-by: Drew DeVault <sir@cmpwn.com>
---
notify/email/email.go | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/notify/email/email.go b/notify/email/email.go
index 73fcf577..529e4333 100644
--- a/notify/email/email.go
+++ b/notify/email/email.go
@@ -16,7 +16,9 @@ package email
import (
"bytes"
"context"
+ "crypto/rand"
"crypto/tls"
+ "encoding/binary"
"fmt"
"mime"
"mime/multipart"
@@ -25,11 +27,13 @@ import (
"net/mail"
"net/smtp"
"net/textproto"
+ "os"
"strings"
"time"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
+ "github.com/martinlindhe/base36"
"github.com/pkg/errors"
commoncfg "github.com/prometheus/common/config"
@@ -241,6 +245,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
fmt.Fprintf(buffer, "Date: %s\r\n", time.Now().Format(time.RFC1123Z))
fmt.Fprintf(buffer, "Content-Type: multipart/alternative; boundary=%s\r\n", multipartWriter.Boundary())
+ fmt.Fprintf(buffer, "Message-ID: %s\r\n", generateMessageID())
fmt.Fprintf(buffer, "MIME-Version: 1.0\r\n\r\n")
// TODO: Add some useful headers here, such as URL of the alertmanager
@@ -314,6 +319,26 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
return false, nil
}
+// Generates an RFC 2822-compliant Message-Id based on the informational draft
+// "Recommendations for generating Message IDs", for lack of a better
+// authoritative source.
+func generateMessageID() string {
+ var (
+ now bytes.Buffer
+ nonce []byte = make([]byte, 8)
+ )
+ binary.Write(&now, binary.BigEndian, time.Now().UnixNano())
+ rand.Read(nonce)
+ hostname, err := os.Hostname()
+ if err != nil {
+ hostname = "localhost"
+ }
+ return fmt.Sprintf("<%s.%s@%s>",
+ base36.EncodeBytes(now.Bytes()),
+ base36.EncodeBytes(nonce),
+ hostname)
+}
+
type loginAuth struct {
username, password string
}
--
2.24.1