From 39b7f6678c98cadcdc3abfbcb447d8eb0daa9eb0 Mon Sep 17 00:00:00 2001 From: Alexander Lehmann Date: Sun, 16 Mar 2025 17:46:45 +0100 Subject: [PATCH] fix: emails are considered as medium spam by rspamd (#337) --- backend/internal/service/email_service.go | 25 +++++++++++++++++++++++ backend/internal/utils/email/composer.go | 6 +++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/backend/internal/service/email_service.go b/backend/internal/service/email_service.go index 5a6fc4f5..28fcf370 100644 --- a/backend/internal/service/email_service.go +++ b/backend/internal/service/email_service.go @@ -18,6 +18,8 @@ import ( "os" ttemplate "text/template" "time" + "github.com/google/uuid" + "strings" ) type EmailService struct { @@ -84,6 +86,29 @@ func SendEmail[V any](srv *EmailService, toEmail email.Address, template email.T c.AddHeaderRaw("Content-Type", fmt.Sprintf("multipart/alternative;\n boundary=%s;\n charset=UTF-8", boundary), ) + + c.AddHeader("MIME-Version", "1.0") + c.AddHeader("Date", time.Now().Format(time.RFC1123Z)) + + // to create a message-id, we need the FQDN of the sending server, but that may be a docker hostname or localhost + // so we use the domain of the from address instead (the same as Thunderbird does) + // if the address does not have an @ (which would be unusual), we use hostname + + from_address := srv.appConfigService.DbConfig.SmtpFrom.Value + domain := "" + if strings.Contains(from_address, "@") { + domain = strings.Split(from_address, "@")[1] + } else { + hostname, err := os.Hostname() + if err != nil { + // can that happen? we just give up + return fmt.Errorf("failed to get own hostname: %w", err) + } else { + domain = hostname + } + } + c.AddHeader("Message-ID", "<" + uuid.New().String() + "@" + domain + ">") + c.Body(body) // Connect to the SMTP server diff --git a/backend/internal/utils/email/composer.go b/backend/internal/utils/email/composer.go index f0bec933..9017ffa7 100644 --- a/backend/internal/utils/email/composer.go +++ b/backend/internal/utils/email/composer.go @@ -45,7 +45,11 @@ func genAddressHeader(name string, addresses []Address, maxLength int) string { } else { email = fmt.Sprintf("<%s>", addr.Email) } - writeHeaderQ(hl, addr.Name) + if isPrintableASCII(addr.Name) { + writeHeaderAtom(hl, addr.Name) + } else { + writeHeaderQ(hl, addr.Name) + } writeHeaderAtom(hl, " ") writeHeaderAtom(hl, email) }