// src/app/(payload)/api/newsletter/subscribe/route.ts import { NextResponse } from 'next/server' import { getPayload } from 'payload' import config from '@payload-config' import { createNewsletterService } from '@/lib/email/newsletter-service' import { getTenantFromRequest } from '@/lib/email/tenant-email-service' import { rateLimiters } from '@/lib/security/rate-limiter' /** * POST /api/newsletter/subscribe * * Newsletter-Anmeldung mit Double Opt-In * * Body: * - email (required): E-Mail-Adresse * - firstName (optional): Vorname * - lastName (optional): Nachname * - interests (optional): Array von Interessen * - source (optional): Anmeldequelle * - tenantId (optional): Tenant-ID (falls nicht aus Request ermittelbar) */ export async function POST(request: Request): Promise { try { // Rate-Limiting (5 Anmeldungen pro 10 Minuten pro IP) const clientIp = request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || request.headers.get('x-real-ip') || 'unknown' const rateLimitResult = rateLimiters.form.check(clientIp) if (!rateLimitResult.allowed) { return NextResponse.json( { success: false, message: 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.', }, { status: 429, headers: { 'Retry-After': String(Math.ceil(rateLimitResult.retryAfter / 1000)), }, }, ) } const payload = await getPayload({ config }) const body = await request.json() // E-Mail validieren const email = body.email?.trim()?.toLowerCase() if (!email || !isValidEmail(email)) { return NextResponse.json( { success: false, message: 'Bitte geben Sie eine gültige E-Mail-Adresse ein.', }, { status: 400 }, ) } // Tenant ermitteln let tenantId = body.tenantId if (!tenantId) { const tenant = await getTenantFromRequest(payload, request) if (tenant) { tenantId = tenant.id } } if (!tenantId) { return NextResponse.json( { success: false, message: 'Tenant konnte nicht ermittelt werden.', }, { status: 400 }, ) } // Newsletter-Service const newsletterService = createNewsletterService(payload) const result = await newsletterService.subscribe(tenantId, { email, firstName: body.firstName?.trim(), lastName: body.lastName?.trim(), interests: body.interests, source: body.source || 'website', ipAddress: clientIp, userAgent: request.headers.get('user-agent') || undefined, }) return NextResponse.json(result, { status: result.success ? 200 : 400, }) } catch (error) { console.error('[Newsletter Subscribe] Error:', error) return NextResponse.json( { success: false, message: 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.', }, { status: 500 }, ) } } /** * E-Mail-Validierung */ function isValidEmail(email: string): boolean { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ return emailRegex.test(email) }