feat(mail): one layout for all mails with logo, greeting, cards and footer
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m1s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-31 10:32:33 +01:00
1 parent df06ab10c8
commit 46e1137f18
16 files changed
+475 -60

No files matched your search

+27
View File
@@ -284,3 +284,30 @@ func TestSenderAddressGetsDisplayName(t *testing.T) {
}
}
}
// HTML mails carry the logo as an inline part (multipart/related), plain mails stay single-part
func TestMailLayoutEmbedsLogo(t *testing.T) {
text, htmlBody := renderMail(mailContent{
Greeting: "Hallo Anna",
Intro: "Eine Aufgabe ist fällig <jetzt>:",
Sections: []mailSection{{Title: "Heute", Items: []mailItem{{Title: "Zahnarzt & Co", Meta: "15:30 Uhr"}}}},
Button: &mailButton{Label: "Öffnen", URL: "https://mindsift.example/"},
Footer: "Fußzeile",
})
if !strings.Contains(text, "HEUTE\n• Zahnarzt & Co (15:30 Uhr)") || !strings.Contains(text, "Öffnen: https://mindsift.example/") {
t.Fatalf("text version wrong:\n%s", text)
}
if !strings.Contains(htmlBody, "Zahnarzt &amp; Co") || !strings.Contains(htmlBody, "&lt;jetzt&gt;") {
t.Fatalf("HTML must escape content")
}
msg := string(buildMessage("MindSift <a@example.com>", "b@example.com", "Test", text, htmlBody, time.Now()))
for _, want := range []string{"multipart/alternative", "multipart/related", "Content-ID: <" + mailLogoCID + ">", "Content-Type: image/png"} {
if !strings.Contains(msg, want) {
t.Fatalf("message lacks %q", want)
}
}
plain := string(buildMessage("a@example.com", "b@example.com", "Test", "nur Text", "", time.Now()))
if strings.Contains(plain, "multipart") || strings.Contains(plain, "image/png") {
t.Fatalf("plain mail must stay single-part")
}
}