From 754922b2503ca8569df7c3c4de7d1709c01c413b Mon Sep 17 00:00:00 2001 From: William Petit Date: Thu, 9 Jul 2020 14:00:17 +0200 Subject: [PATCH] Generate pseudo-random Message-Id header for each outgoing emails --- internal/mail/send.go | 47 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/internal/mail/send.go b/internal/mail/send.go index 05da094..38a00eb 100644 --- a/internal/mail/send.go +++ b/internal/mail/send.go @@ -2,11 +2,21 @@ package mail import ( "crypto/tls" + "fmt" + "math/rand" + "net/mail" + "strconv" + "strings" + "time" "github.com/pkg/errors" gomail "gopkg.in/mail.v2" ) +var ( + ErrUnexpectedEmailAddressFormat = errors.New("unexpected email address format") +) + type SendFunc func(*SendOption) type SendOption struct { @@ -124,6 +134,20 @@ func (m *Mailer) Send(funcs ...SendFunc) error { message.SetHeader(h.Field, h.Values...) } + froms := message.GetHeader("From") + + var sendDomain string + + if len(froms) > 0 { + sendDomain, err = extractEmailDomain(froms[0]) + if err != nil { + return err + } + } + + messageID := generateMessageID(sendDomain) + message.SetHeader("Message-Id", messageID) + message.SetBody(opt.Body.Type, opt.Body.Content, opt.Body.PartSetting) for _, b := range opt.AlternativeBodies { @@ -158,3 +182,26 @@ func (m *Mailer) openConnection() (gomail.SendCloser, error) { return conn, nil } + +func extractEmailDomain(email string) (string, error) { + address, err := mail.ParseAddress(email) + if err != nil { + return "", errors.Wrapf(err, "could not parse email address '%s'", email) + } + + addressParts := strings.SplitN(address.Address, "@", 2) + if len(addressParts) != 2 { // nolint: gomnd + return "", errors.WithStack(ErrUnexpectedEmailAddressFormat) + } + + domain := addressParts[1] + + return domain, nil +} + +func generateMessageID(domain string) string { + // Based on https://www.jwz.org/doc/mid.html + timestamp := strconv.FormatInt(time.Now().UnixNano(), 36) + random := strconv.FormatInt(rand.Int63(), 36) + return fmt.Sprintf("<%s.%s@%s>", timestamp, random, domain) +}