import { BRAND, BRAND_COLORS } from "@/lib/brand"; import { DOCUMENT_THEME } from "@/lib/document-brand"; /** * Brandfähige E-Mail-Template-Basis (Story S6). * * SMTP und der Einladungs-/Reset-Flow kommen erst mit Paket 4 — dieses Modul * liefert das Craftvia-Gerüst, damit die Templates nur noch Inhalt * einsetzen müssen und das CD nicht neu erfunden wird. * * Bewusste Einschränkungen für E-Mail-Clients: * - keine CSS-Variablen, keine externen Stylesheets → alles inline * - Tabellen-Layout statt Flex/Grid (Outlook) * - Logo als absolute URL, kein Inline-SVG (viele Clients rendern es nicht) * - immer eine Plaintext-Alternative mitschicken (`renderTextEmail`) */ export type EmailContent = { /** Betreff — wird nicht in den Body gerendert, nur durchgereicht */ subject: string; /** Überschrift im Body */ heading: string; /** Absätze; jeder Eintrag wird ein
*/ paragraphs: string[]; /** Optionaler Call-to-Action */ action?: { label: string; url: string }; /** Kleingedrucktes über der Fußzeile (z. B. Gültigkeitsdauer eines Links) */ note?: string; /** * Zusatzzeile in der Fußzeile — für den Abmelde-/Präferenzhinweis bei * Benachrichtigungsmails. Sicherheitsrelevante Transaktionsmails (Reset, * Passwortwechsel) setzen ihn bewusst NICHT: sie sind nicht abbestellbar. */ footerNote?: string; }; /** * Basis-URL für absolute Links/Bilder in Mails. Relative Pfade funktionieren in * E-Mail-Clients nicht. */ function baseUrl(): string { return (process.env.AUTH_URL ?? process.env.NEXTAUTH_URL ?? "http://localhost:3000").replace( /\/+$/, "" ); } function escapeHtml(s: string): string { return s .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } /** Absenderzeile für den `From`-Header. */ export function emailSender(address: string): string { return `${BRAND.name} <${address}>`; } /** Signatur-/Fußzeilentext. */ export function emailSignature(): string { return `${BRAND.name} — ${BRAND.tagline}`; } /** * Rendert eine Mail im Craftvia-CD (Hafengrau-Grund, Lotsenblau, Signalorange-CTA). * Rückgabe ist ein vollständiges HTML-Dokument. */ export function renderHtmlEmail(content: EmailContent): string { const url = baseUrl(); const t = DOCUMENT_THEME; const paragraphs = content.paragraphs .map( (p) => `
${escapeHtml(p)}
` ) .join(""); const action = content.action ? `| ${escapeHtml(content.action.label)} |
${escapeHtml(content.note)}
` : ""; return `