Generate pseudo-random Message-Id header for each outgoing emails

This commit is contained in:
wpetit 2020-07-09 14:00:17 +02:00
parent 3a1d08661b
commit 754922b250
1 changed files with 47 additions and 0 deletions

View File

@ -2,11 +2,21 @@ package mail
import ( import (
"crypto/tls" "crypto/tls"
"fmt"
"math/rand"
"net/mail"
"strconv"
"strings"
"time"
"github.com/pkg/errors" "github.com/pkg/errors"
gomail "gopkg.in/mail.v2" gomail "gopkg.in/mail.v2"
) )
var (
ErrUnexpectedEmailAddressFormat = errors.New("unexpected email address format")
)
type SendFunc func(*SendOption) type SendFunc func(*SendOption)
type SendOption struct { type SendOption struct {
@ -124,6 +134,20 @@ func (m *Mailer) Send(funcs ...SendFunc) error {
message.SetHeader(h.Field, h.Values...) 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) message.SetBody(opt.Body.Type, opt.Body.Content, opt.Body.PartSetting)
for _, b := range opt.AlternativeBodies { for _, b := range opt.AlternativeBodies {
@ -158,3 +182,26 @@ func (m *Mailer) openConnection() (gomail.SendCloser, error) {
return conn, nil 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)
}