kundencenter/migrations/022_mail_templates.sql
Kundencenter a68b4cf6ec feat: SMTP-Stack mit konfigurierbaren Mailvorlagen
Bisher gab es nur zwei fest im Code verdrahtete E-Mails (Einladung,
Passwort-Reset) und die SMTP-Verbindung kam ausschließlich aus
Umgebungsvariablen. Jetzt:

- SMTP-Verbindung unter Einstellungen > E-Mail konfigurierbar (Host,
  Port, Verschlüsselung, Zugangsdaten verschlüsselt gespeichert,
  Absender), mit Testmail-Versand. Die Mail-Logik wandert dafür nach
  @kc/platform/mail, damit API und Worker sie gemeinsam nutzen.
- Mailvorlagen-Verwaltung: jedes Ereignis hat eine feste "Definition"
  (Name, Auslöser, verfügbare Platzhalter/Daten), Betreff/Text sind
  editierbar, je Vorlage einzeln aktivierbar, mit Testversand anhand
  von Beispieldaten. Unbekannte Platzhalter werden beim Speichern
  abgelehnt.
- Neue Ereignisse verdrahtet: Ticket erstellt (Bestätigung an Kunde),
  Personal antwortet auf Ticket (Benachrichtigung an Kunde), Rechnung
  ausgestellt, sowie die zuvor zurückgestellte Funktion "Panel-
  Zugangsdaten per E-Mail senden" nach einem Passwort-Reset. Diese
  laufen über die Jobqueue (mail.template), analog zu discord.notify.
- Versandprotokoll (letzte 100 Versuche, ohne Inhalte) einsehbar unter
  Einstellungen > E-Mail.
- Migration 022, Rechte email.read (Admin+) / email.write (Superadmin).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 12:53:29 +02:00

54 lines
3.6 KiB
SQL

-- SMTP-Stack: konfigurierbare Verbindung (statt Umgebungsvariablen) und Mailvorlagen mit dokumentierten Platzhaltern.
CREATE TABLE smtp_settings (
id TINYINT PRIMARY KEY DEFAULT 1,
host VARCHAR(253) NULL,
port SMALLINT UNSIGNED NOT NULL DEFAULT 587,
secure_mode ENUM('none','starttls','tls') NOT NULL DEFAULT 'starttls',
username VARCHAR(200) NULL,
secrets_enc TEXT NULL,
from_name VARCHAR(150) NULL,
from_email VARCHAR(254) NULL,
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
updated_by CHAR(36) NULL REFERENCES users(id),
CONSTRAINT chk_smtp_singleton CHECK (id = 1)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO smtp_settings (id) VALUES (1);
-- Vorlagen je Ereignis ("Definition"): Betreff/Text mit {{platzhalter}}, dokumentierte verfügbare Daten je Vorlage.
CREATE TABLE mail_templates (
`key` VARCHAR(60) PRIMARY KEY,
name VARCHAR(150) NOT NULL,
trigger_text VARCHAR(300) NOT NULL,
variables_json JSON NOT NULL,
subject VARCHAR(300) NOT NULL,
body TEXT NOT NULL,
enabled TINYINT(1) NOT NULL DEFAULT 1,
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
updated_by CHAR(36) NULL REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO mail_templates (`key`, name, trigger_text, variables_json, subject, body) VALUES
('invite', 'Zugang eingerichtet', 'Wenn für einen Kunden ein neuer Zugang angelegt wird.',
JSON_ARRAY('name','inviteLink','validDays'),
'Ihr Zugang zum Kundencenter',
'Hallo {{name}},\n\nfür Sie wurde ein Zugang eingerichtet. Bitte legen Sie hier Ihr Passwort fest ({{validDays}} Tage gültig):\n{{inviteLink}}\n'),
('password_reset', 'Passwort zurücksetzen', 'Wenn ein Passwort-Reset angefordert wird (Kunde oder Personal).',
JSON_ARRAY('name','resetLink'),
'Passwort zurücksetzen',
'Hallo {{name}},\n\nüber diesen Link können Sie Ihr Passwort zurücksetzen (1 Stunde gültig):\n{{resetLink}}\n\nWenn Sie das nicht angefordert haben, ignorieren Sie diese E-Mail.\n'),
('panel_credentials', 'Neue Panel-Zugangsdaten', 'Wenn Personal nach dem Neuvergeben eines Panel-Passworts auf „Per E-Mail senden“ klickt.',
JSON_ARRAY('name','resourceName','username','password'),
'Ihre neuen Zugangsdaten für {{resourceName}}',
'Hallo {{name}},\n\nfür {{resourceName}} wurden neue Zugangsdaten vergeben:\n\nBenutzername: {{username}}\nPasswort: {{password}}\n\nBitte bewahren Sie die Zugangsdaten sicher auf und ändern Sie das Passwort nach der ersten Anmeldung, falls möglich.\n'),
('ticket_created', 'Ticket erstellt (Bestätigung an Kunde)', 'Wenn ein Kunde selbst ein neues Ticket erstellt.',
JSON_ARRAY('name','number','subject'),
'Ticket {{number}} wurde erstellt',
'Hallo {{name}},\n\nIhr Ticket „{{subject}}“ ({{number}}) wurde bei uns erstellt. Wir melden uns, sobald es eine Antwort gibt.\n'),
('ticket_message', 'Antwort auf Ticket (an Kunde)', 'Wenn Personal auf ein Kunden-Ticket antwortet (keine interne Notiz).',
JSON_ARRAY('name','number','subject'),
'Neue Antwort zu Ticket {{number}}',
'Hallo {{name}},\n\nes gibt eine neue Antwort zu Ihrem Ticket „{{subject}}“ ({{number}}). Bitte im Kundencenter ansehen und bei Bedarf antworten.\n'),
('invoice_issued', 'Rechnung erstellt', 'Wenn eine Rechnung ausgestellt wird.',
JSON_ARRAY('name','number','amount','dueDate'),
'Ihre Rechnung {{number}}',
'Hallo {{name}},\n\nIhre Rechnung {{number}} über {{amount}} wurde erstellt, fällig am {{dueDate}}. Sie können sie im Kundencenter einsehen und als PDF herunterladen.\n');