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

+54 -4
View File
@@ -8,12 +8,63 @@ import (
"time"
"github.com/sandrodach/mindsift/internal/domain"
"github.com/sandrodach/mindsift/internal/storage"
)
// --- MULTI-CHANNEL ALARM DISPATCHER (EMAIL, DISCORD, CUSTOM WEBHOOK) ---
func (s *Server) sendEmailNotification(toEmail, subject, bodyText string) error {
return s.sendEmailHTML(toEmail, subject, bodyText, "")
// sendMailContent sends a mail in the common MindSift look (mailtemplate.go), as text and HTML.
func (s *Server) sendMailContent(toEmail, subject string, c mailContent) error {
text, htmlBody := renderMail(c)
return s.sendEmailHTML(toEmail, subject, text, htmlBody)
}
// Footers: why a mail came
const (
mailFooterAlarms = "Du bekommst diese E-Mail, weil du E-Mail-Benachrichtigungen eingeschaltet hast. Ändern kannst du das in MindSift unter Kontoeinstellungen → Alarme."
mailFooterAccount = "Diese E-Mail betrifft dein MindSift-Konto und kommt deshalb unabhängig von deinen Benachrichtigungen."
)
// priorityLabel / priorityTone: how a task's priority reads and is coloured in mails
func priorityLabel(p string) string {
switch p {
case "urgent":
return "Dringend"
case "high":
return "Wichtig"
case "low":
return "Niedrig"
}
return "Normal"
}
func priorityTone(p string) string {
switch p {
case "urgent":
return "danger"
case "high":
return "warning"
}
return ""
}
// dueAlarmMail: one task is due now.
func (s *Server) dueAlarmMail(a storage.DueTaskAlarm, due string) mailContent {
meta := "Fällig: " + due
if a.Priority != "" && a.Priority != "normal" {
meta += " · " + priorityLabel(a.Priority)
}
c := mailContent{
Preheader: "Fällig: " + a.Title,
Greeting: mailGreeting(time.Now(), a.UserName),
Intro: "Eine deiner Aufgaben ist jetzt fällig:",
Sections: []mailSection{{Items: []mailItem{{Title: a.Title, Meta: meta, Body: a.Notes, Tone: priorityTone(a.Priority)}}}},
Footer: mailFooterAlarms,
}
if link := s.notifyLink(); link != "" {
c.Button = &mailButton{Label: "In MindSift öffnen", URL: link}
}
return c
}
// sendEmailHTML sends text plus an optional HTML version (multipart/alternative).
@@ -181,8 +232,7 @@ func (s *Server) startAlarmTicker() {
}
case "email":
if a.AlarmEmail != "" {
emailBody := fmt.Sprintf("Hallo,\n\ndeine Aufgabe in MindSift ist fällig:\n\nAufgabe: %s\nFällig am: %s\nPriorität: %s\nNotizen: %s\n", a.Title, due, a.Priority, desc)
if err := s.sendEmailNotification(a.AlarmEmail, "⏰ Aufgabe fällig: "+a.Title, emailBody); err == nil {
if err := s.sendMailContent(a.AlarmEmail, "⏰ Fällig: "+a.Title, s.dueAlarmMail(a, due)); err == nil {
sentAny = true
}
}