189 lines
6.5 KiB
Markdown
189 lines
6.5 KiB
Markdown
# 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
|
||
|
||
```bash
|
||
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ür `createActionToken` in Admin-Mails, optional)
|
||
|
||
---
|
||
|
||
## Umgebungsvariablen (`.env.local`)
|
||
|
||
```env
|
||
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:
|
||
|
||
```sql
|
||
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`)
|
||
```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-auth` muss eingebunden sein (liefert `createActionToken`)
|
||
- Buttons verweisen auf `GET /api/admin/anfragen-action?token=...`
|
||
|
||
### 6. SMTP testen
|
||
```bash
|
||
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.
|
||
```
|