import "server-only"; import { env } from "@/lib/env"; /** * E-Mail-Versand hinter einer Schnittstelle. * * Regel aus CLAUDE.md: externe Dienste hinter Interfaces in lib/integrations/, * damit sie im Test mockbar und im Betrieb abschaltbar sind. Ist MAIL_ENABLED * nicht gesetzt, landet die Nachricht im Log statt beim Empfänger — für * Entwicklung und Testbetrieb genau richtig. * * Die tatsächliche SMTP-Anbindung kommt in Phase 7 (Benachrichtigungen). Bis * dahin steht hier bewusst nur der Vertrag. */ export interface Nachricht { an: string | string[]; betreff: string; text: string; html?: string; antwortAn?: string; anhaenge?: Array<{ dateiname: string; inhalt: Buffer; mimeTyp: string }>; } export interface MailVersand { senden(nachricht: Nachricht): Promise<{ erfolgreich: boolean; kennung?: string; fehler?: string }>; verfuegbar(): boolean; } /** Schreibt statt zu senden. Standard, solange MAIL_ENABLED=false. */ class ProtokollVersand implements MailVersand { verfuegbar(): boolean { return false; } async senden(nachricht: Nachricht) { const empfaenger = Array.isArray(nachricht.an) ? nachricht.an.join(", ") : nachricht.an; console.info( `[mail] (nicht versendet, MAIL_ENABLED=false) an=${empfaenger} betreff="${nachricht.betreff}"`, ); return { erfolgreich: true, kennung: "protokoll" }; } } /** Platzhalter für den echten SMTP-Versand aus Phase 7. */ class SmtpVersand implements MailVersand { verfuegbar(): boolean { return Boolean(env.MAIL_HOST && env.MAIL_FROM); } async senden(nachricht: Nachricht) { const empfaenger = Array.isArray(nachricht.an) ? nachricht.an.join(", ") : nachricht.an; console.warn( `[mail] SMTP-Versand ist erst ab Phase 7 umgesetzt. an=${empfaenger} betreff="${nachricht.betreff}"`, ); return { erfolgreich: false, fehler: "SMTP-Versand noch nicht umgesetzt (Phase 7).", }; } } let versandCache: MailVersand | null = null; export function mail(): MailVersand { if (!versandCache) { versandCache = env.MAIL_ENABLED ? new SmtpVersand() : new ProtokollVersand(); } return versandCache; } /** Nur für Tests: eigene Umsetzung unterschieben. */ export function _mailErsetzen(ersatz: MailVersand | null): void { versandCache = ersatz; }