package web
import (
"bytes"
"html/template"
"net/http"
"net/url"
"strings"
"forge.gpl-nas.de/physiobase/internal/mailer"
"forge.gpl-nas.de/physiobase/internal/store"
)
// E-Mail-Clients ignorieren externe CSS-Dateien → schlichte Inline-Stile.
var mailHTML = template.Must(template.New("mail").Parse(`
{{.Title}}
{{.Title}}
{{.Date}}
Guten Tag {{.Name}},
hier ist Ihre Zusammenfassung zum Nachlesen.
{{.Body}}
Viele Grüße
{{.Practice}}
Diese Nachricht enthält persönliche Gesundheitsinformationen und ist nur für {{.Name}} bestimmt.
`))
func mailText(name, title, date, body, practice string) string {
var b strings.Builder
b.WriteString("Guten Tag " + name + ",\n\nhier ist Ihre Zusammenfassung zum Nachlesen.\n\n")
b.WriteString(title + " (" + date + ")\n" + strings.Repeat("=", len([]rune(title))) + "\n\n")
b.WriteString(body + "\n\nViele Grüße\n" + practice + "\n\n")
b.WriteString("Diese Nachricht enthält persönliche Gesundheitsinformationen und ist nur für " + name + " bestimmt.\n")
return b.String()
}
// mailBlockReason: warum (noch) nicht gesendet werden kann; leer = alles bereit.
func (s *Server) mailBlockReason(p store.Patient) string {
switch {
case !s.cfg.SMTP.Enabled():
return "Der E-Mail-Versand ist nicht eingerichtet (PHYSIOBASE_SMTP_* in .env)."
case p.Email == "":
return "Für diesen Patienten ist keine E-Mail-Adresse hinterlegt."
case !mailer.ValidAddress(p.Email):
return "Die hinterlegte E-Mail-Adresse ist ungültig."
case !p.EmailConsent:
return "Es fehlt die Einwilligung in den Versand per E-Mail (Stammdaten des Patienten)."
}
return ""
}
func (s *Server) sendSummary(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
x, p, ok := s.loadSummary(w, r)
if !ok {
return
}
if reason := s.mailBlockReason(p); reason != "" {
redirect(w, r, "/zusammenfassung/%d?fehler=%s#senden", x.ID, url.QueryEscape(reason))
return
}
body := Printable(x.Body)
var html bytes.Buffer
if err := mailHTML.Execute(&html, map[string]any{
"Title": x.Title, "Date": deDate(x.Date), "Name": p.Name, "Practice": s.cfg.PracticeName,
"Body": funcs["md"].(func(string) template.HTML)(body),
}); err != nil {
s.fail(w, r, err)
return
}
msg := mailer.Message{
To: p.Email, Subject: x.Title, FromName: s.cfg.PracticeName,
Text: mailText(p.Name, x.Title, deDate(x.Date), body, s.cfg.PracticeName), HTML: html.String(),
}
err := mailer.Send(ctx, s.cfg.SMTP, msg)
entry := store.MailLog{Recipient: p.Email, Subject: x.Title, OK: err == nil}
if err != nil {
entry.Error = err.Error()
s.log.Error("e-mail fehlgeschlagen", "zusammenfassung", x.ID, "err", err)
} else {
s.log.Info("e-mail gesendet", "zusammenfassung", x.ID, "patient", p.ID)
}
if lerr := s.st.LogMail(ctx, x.ID, p.ID, entry); lerr != nil {
s.log.Error("versandprotokoll", "err", lerr)
}
if err != nil {
redirect(w, r, "/zusammenfassung/%d?fehler=%s#senden", x.ID, url.QueryEscape("Senden fehlgeschlagen: "+err.Error()))
return
}
redirect(w, r, "/zusammenfassung/%d?gesendet=1#senden", x.ID)
}