6.5 KiB
Modul: Email-System
SMTP-Versand mit Nodemailer (STARTTLS Port 587), Queue-Fallback in Supabase bei Versandfehlern, exponentielles Retry (max 10 Versuche). Unterstützt HTML + Plaintext, HMAC-signierte Action-Buttons in Admin-Mails (7 Tage gültig, One-Time-Use).
Enthaltene Dateien
| Ziel im neuen Projekt | Quelle |
|---|---|
lib/mailer.ts |
Haupt-Mailer (Nodemailer + alle Email-Funktionen) |
lib/email-queue.ts |
Queue-System (Supabase-Fallback + Worker) |
app/api/admin/email-queue/route.ts |
Admin-API: Queue-Status anzeigen |
app/api/admin/smtp-test/route.ts |
Admin-API: SMTP-Verbindung testen |
Hinweis: [id]-Ordner in files/ entsprechen Next.js Dynamic-Route-Ordnern [id].
Voraussetzungen
npm install nodemailer
npm install -D @types/nodemailer
Benötigt außerdem:
lib/supabase.ts(Service Client für Queue-Speicherung)lib/admin-auth.ts(fürcreateActionTokenin Admin-Mails, optional)
Umgebungsvariablen (.env.local)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=user@example.com
SMTP_PASS=password
SMTP_FROM=noreply@example.com # Absender
SMTP_TO=admin@example.com # Admin-Inbox
COMPANY_PHONE=+49123456789 # Wird in Mails angezeigt
APP_URL=https://example.com # Basis-URL für Links in Mails
NEXTAUTH_SECRET=your-secret # HMAC-Key für Action-Tokens
Datenbank-Migration (Supabase)
Tabelle email_queue muss in lib/supabase.ts als Type definiert und in Supabase existieren:
CREATE TABLE email_queue (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
to_addr text NOT NULL,
subject text NOT NULL,
html text NOT NULL,
text text,
attempts int DEFAULT 0,
max_attempts int DEFAULT 10,
status text DEFAULT 'pending' CHECK (status IN ('pending','sent','failed')),
last_error text,
next_retry_at timestamptz DEFAULT now(),
created_at timestamptz DEFAULT now(),
sent_at timestamptz
);
CREATE INDEX idx_email_queue_pending ON email_queue(status, next_retry_at) WHERE status = 'pending';
Einbindung Schritt für Schritt
1. Dateien kopieren
Alle Dateien aus files/ in die entsprechenden Pfade des neuen Projekts kopieren.
2. Mailer an Projekt anpassen (lib/mailer.ts)
Die Datei enthält projektspezifische Email-Funktionen (Anfragen, Kunden-Bestätigungen etc.). Folgende Funktionen beibehalten oder anpassen:
sendeKontaktEmail(data)→ bleibt meist unverändert- Alle anderen Funktionen nach Bedarf umbenennen/entfernen
- Firmenname/Branding in HTML-Templates ersetzen (Suche nach
Mietpark Hahn)
3. Queue-Worker starten (instrumentation.ts)
// instrumentation.ts (Projekt-Root)
import { startEmailQueueWorker } from "@/lib/email-queue";
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
startEmailQueueWorker();
}
}
4. Email-Queue Typ in lib/supabase.ts ergänzen
Im Database-Typ die email_queue Tabelle mit den Feldern aus der Migration ergänzen.
5. Action-Buttons (optional)
Wenn Admin-Mails HMAC-signierte Buttons enthalten sollen (z.B. "Bestätigen / Ablehnen"):
- Modul
02-admin-authmuss eingebunden sein (liefertcreateActionToken) - Buttons verweisen auf
GET /api/admin/anfragen-action?token=...
6. SMTP testen
curl -X POST http://localhost:3000/api/admin/smtp-test \
-H "Content-Type: application/json" \
-d '{"to":"test@example.com"}'
Anpassungspunkte
| Was | Wo |
|---|---|
| HTML-Templates (Firmenname, Farben) | lib/mailer.ts – alle html-Variablen |
| Email-Betreffs | lib/mailer.ts – alle subject-Zeilen |
| Retry-Intervalle | lib/email-queue.ts – calcNextRetry() |
| Max. Versuche | lib/email-queue.ts – maxAttempts: 10 |
| Queue-Worker-Intervall | lib/email-queue.ts – setInterval(60_000) |
| SMTP Port (465 statt 587) | lib/mailer.ts – secure: true, port: 465 |
Integrations-Prompt
Kopiere diesen Prompt in eine neue KI-Konversation, nachdem du die files/ in dein Projekt kopiert hast. Ersetze alle [PLATZHALTER].
Ich integriere das Email-System-Modul (Nodemailer + Supabase Queue) in mein bestehendes Next.js/Supabase-Projekt.
PROJEKT-KONTEXT:
- Projektname: [PROJEKTNAME]
- Admin-Email (Empfänger): [ADMIN_EMAIL]
- SMTP-Absender: [SMTP_FROM_EMAIL]
- App-URL (für Links in Mails): [https://beispiel.de]
BEREITS KOPIERTE DATEIEN (aus modules/01-email-system/files/):
- lib/mailer.ts
- lib/email-queue.ts
- app/api/admin/email-queue/route.ts
- app/api/admin/smtp-test/route.ts
AUFGABEN – führe sie der Reihe nach aus:
1. SUPABASE-MIGRATION: Führe folgendes SQL im Supabase SQL-Editor aus:
CREATE TABLE email_queue (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
to_addr text NOT NULL, subject text NOT NULL,
html text NOT NULL, text text,
attempts int DEFAULT 0, max_attempts int DEFAULT 10,
status text DEFAULT 'pending' CHECK (status IN ('pending','sent','failed')),
last_error text, next_retry_at timestamptz DEFAULT now(),
created_at timestamptz DEFAULT now(), sent_at timestamptz
);
CREATE INDEX idx_email_queue_pending ON email_queue(status, next_retry_at) WHERE status = 'pending';
2. SUPABASE-TYPEN: Lies lib/supabase.ts und ergänze in Database.public.Tables:
email_queue: { Row: { id: string; to_addr: string; subject: string; html: string; text: string | null; attempts: number; max_attempts: number; status: string; last_error: string | null; next_retry_at: string; created_at: string; sent_at: string | null } }
3. BRANDING: Ersetze in lib/mailer.ts alle Vorkommen von "Mietpark Hahn" durch "[PROJEKTNAME]".
Passe außerdem die Farben im HTML-Template an (aktuell #f7d334 für Buttons).
4. QUEUE-WORKER: Lies instrumentation.ts (oder erstelle sie im Projekt-Root falls nicht vorhanden).
Ergänze/ersetze den Inhalt um:
import { startEmailQueueWorker } from "@/lib/email-queue";
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") startEmailQueueWorker();
}
5. ENV-VARIABLEN: Ergänze .env.local um:
SMTP_HOST=[SMTP_HOST]
SMTP_PORT=587
SMTP_USER=[SMTP_USER]
SMTP_PASS=[SMTP_PASS]
SMTP_FROM=[SMTP_FROM_EMAIL]
SMTP_TO=[ADMIN_EMAIL]
COMPANY_PHONE=[TELEFON]
APP_URL=[https://beispiel.de]
NEXTAUTH_SECRET=[MIN_32_ZEICHEN_ZUFAELLIGER_STRING]
6. TEST: Starte den Dev-Server und sende eine Test-Email:
curl -X POST http://localhost:3000/api/admin/smtp-test \
-H "Content-Type: application/json" \
-d '{"to":"[ADMIN_EMAIL]"}'
Lies jede Datei vor dem Bearbeiten. Melde wenn alle Schritte abgeschlossen sind.