E-Mail- und Newsletter-Betrieb
Dieser Leitfaden beschreibt die produktive Einrichtung für transaktionale Auth-E-Mails, Workspace-Einladungen und den Newsletter. Die Anwendung hält Zustell- und Consent-Status in der eigenen Datenbank; Resend ist austauschbarer Transport- und Kontakt-Provider.
Verantwortlichkeiten und Zugriffe
Abschnitt betitelt „Verantwortlichkeiten und Zugriffe“- Das Resend-Konto muss mit einer organisationsgebundenen Adresse angelegt werden. Mindestens zwei interne Personen erhalten Zugriff für Notfälle; normale Entwicklung benötigt keinen Dashboard-Zugriff.
- API-Key und Webhook-Secret liegen ausschließlich im Secret Store der Server-Laufzeit. Sie dürfen weder in Git noch in Client-Umgebungsvariablen, Screenshots, Tickets oder Logs erscheinen.
- Der produktive API-Key erhält nur die für Versand, Kontakte und Topics benötigten Rechte. Bei Rollenwechsel, Verdacht auf Offenlegung und spätestens nach dem internen Rotationsintervall wird er ersetzt. Während der Rotation können alter und neuer Key nur kurz parallel gültig sein.
- Marketing und transaktionale E-Mails verwenden getrennte Absenderadressen. Für unterschiedliche Reputation ist eine eigene Versand-Subdomain empfohlen.
Domain und DNS
Abschnitt betitelt „Domain und DNS“- Die Versand-Subdomain in Resend anlegen und ausschließlich die dort erzeugten SPF-/MX- und DKIM-Einträge beim DNS-Provider übernehmen.
- Warten, bis Resend die Domain als
verifiedmeldet. Vorher keinen produktiven Versand aktivieren. - DMARC zunächst mit
p=noneund einer überwachten Reporting-Adresse einführen. Nach Prüfung aller legitimen Absender schrittweise aufquarantineund anschließendrejectverschärfen. - Je eine Testmail über den transaktionalen und den Marketing-Absender senden und in den
empfangenen Headern
spf=pass,dkim=passunddmarc=passkontrollieren.
Die DNS-Werte werden nicht in dieser Dokumentation kopiert, weil sie pro Resend-Domain erzeugt werden. Abweichende oder doppelte SPF-Einträge sind vor dem Rollout zu bereinigen.
Für die aktuelle Produktivumgebung gilt:
- Versand-Domain:
mail.orbinaut.ccl-dev.com - Transaktionaler Absender:
Orbinaut <no-reply@mail.orbinaut.ccl-dev.com> - Marketing-Absender:
Orbinaut Newsletter <newsletter@mail.orbinaut.ccl-dev.com>
Beide Absender liegen auf derselben verifizierten Versand-Domain. Eine zusätzliche Resend-Domain
ist dafür nicht nötig. Die DMARC-Policy der übergeordneten Domain wird vor einer Änderung geprüft,
damit andere Absender unter ccl-dev.com nicht unbeabsichtigt beeinträchtigt werden.
Server-Konfiguration
Abschnitt betitelt „Server-Konfiguration“| Variable | Zweck |
|---|---|
RESEND_API_KEY |
Server-only API-Key |
RESEND_TRANSACTIONAL_FROM |
Verifizierter Absender für Auth und Einladungen |
RESEND_MARKETING_FROM |
Verifizierter Absender für Newsletter |
RESEND_NEWSLETTER_TOPIC_ID |
Topic, in das erst nach Double-Opt-in synchronisiert wird |
RESEND_NEWSLETTER_TOPIC_NAME |
Interner Anzeigename des freigegebenen Topics |
RESEND_NEWSLETTER_SEGMENT_ID |
Einziger für das Admin-UI freigegebener Broadcast-Segment-Identifier |
RESEND_NEWSLETTER_SEGMENT_NAME |
Interner Anzeigename des freigegebenen Segments |
ADMIN_NEWSLETTER_TEST_RECIPIENTS |
Kommagetrennte, serverseitige Allowlist interner Testempfänger |
ADMIN_AUTH_SUPPORT_SEARCH_LIMIT |
Maximale Auth-Supportsuchen pro Plattform-Admin und Minute, Standard 20 |
NEWSLETTER_SUBSCRIBE_RATE_LIMIT |
Maximale öffentliche Newsletter-Anmeldungen pro Client und Zeitfenster, Standard 10 |
NEWSLETTER_SUBSCRIBE_RATE_WINDOW_SECONDS |
Zeitfenster des öffentlichen Newsletter-Limits in Sekunden, Standard 600 |
RESEND_WEBHOOK_SECRET |
Signaturprüfung eingehender Webhooks |
RESEND_DAILY_SEND_LIMIT |
Kanalübergreifendes lokales Tageslimit, Standard 100 |
RESEND_MONTHLY_SEND_LIMIT |
Kanalübergreifendes lokales Monatslimit, Standard 3000 |
RESEND_PLAN_NAME |
Kontrolliert gepflegte Tarifbezeichnung für das Admin-Dashboard |
RESEND_USAGE_WARNING_PERCENT |
Warnschwelle für Tages- und Monatsquote, Standard 80 |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET |
Google-OAuth-Zugangsdaten |
RESEND_API_BASE_URL ist ausschließlich für lokale E2E-Tests vorgesehen. In Produktion akzeptiert
die Anwendung nur den offiziellen HTTPS-Endpunkt. Eine teilweise Resend-Konfiguration gilt als
Fehlkonfiguration und muss vor dem Deployment behoben werden. Unter NODE_ENV=production gilt
auch eine vollständig fehlende Resend-Konfiguration als Startfehler; die Fehlermeldung nennt alle
fehlenden Variablen.
Brand-Asset in E-Mails
Abschnitt betitelt „Brand-Asset in E-Mails“Die HTML-Templates laden das kompakte Orbinaut-Markenzeichen über die öffentliche, unveränderliche
URL https://waitlist.orbinaut.ccl-dev.com/brand/orbinaut-mark.webp. Die Ressource wird ohne
empfängerspezifische Parameter oder Tracking-ID eingebunden. Der Pfad muss bei Deployments der
Waitlist stabil und öffentlich erreichbar bleiben. Weil E-Mail-Clients externe Bilder blockieren
können, enthält der Header zusätzlich die textbasierte Wortmarke und das Bild einen Alt-Text; die
Handlung und alle sicherheitsrelevanten Informationen dürfen nie ausschließlich im Bild stehen.
Dokploy
Abschnitt betitelt „Dokploy“Die oben aufgeführten Variablen werden ausschließlich an der Dokploy-Anwendung api gesetzt.
web, waitlist und admin erhalten weder API-Key noch Webhook-Secret. In Dokploy sind mindestens
diese produktiven Werte zu hinterlegen:
RESEND_TRANSACTIONAL_FROM=Orbinaut <no-reply@mail.orbinaut.ccl-dev.com>RESEND_MARKETING_FROM=Orbinaut Newsletter <newsletter@mail.orbinaut.ccl-dev.com>RESEND_DAILY_SEND_LIMIT=100RESEND_MONTHLY_SEND_LIMIT=3000RESEND_API_KEY, RESEND_NEWSLETTER_TOPIC_ID und RESEND_WEBHOOK_SECRET werden als Secrets aus
Resend übernommen und niemals in Dokumentation oder Deployment-Logs kopiert. Anschließend wird
die API neu deployed; erst ein erfolgreicher Start und Healthcheck bestätigen die Konfiguration.
Für Google OAuth werden in Google Cloud ausschließlich die produktiven Better-Auth-Callback-URLs
der jeweiligen Umgebung eingetragen. Lokale oder fremde Origins dürfen nicht in der produktiven
Client-Konfiguration stehen. Die Test-Variable GOOGLE_OAUTH_TEST_BASE_URL ist außerhalb von
NODE_ENV=test technisch gesperrt.
Der öffentliche Newsletter-Endpunkt bildet den Client aus X-Real-IP beziehungsweise dem ersten
Wert von X-Forwarded-For und speichert davon ausschließlich einen SHA-256-Fingerprint. Der
vorgeschaltete, vertrauenswürdige Edge-Proxy muss beide Header bei jeder Anfrage überschreiben;
ungeprüfte, vom Internet-Client gelieferte Forwarding-Header dürfen die Anwendung nicht erreichen.
Fehlt in einer direkten lokalen Umgebung ein solcher Header, greift ein gemeinsames
unknown-client-Limit.
Webhook
Abschnitt betitelt „Webhook“Im Resend-Dashboard einen HTTPS-Webhook auf
https://<api-host>/api/webhooks/resend mit folgenden Events einrichten:
email.deliveredemail.bouncedemail.complainedemail.failedcontact.updated
Das Signing Secret als RESEND_WEBHOOK_SECRET hinterlegen. Die Anwendung prüft die Svix-Signatur
gegen den unveränderten Request-Body und speichert die svix-id eindeutig. Wiederholte Zustellung
derselben ID ist dadurch wirkungslos. Nach der Einrichtung je ein Testevent auslösen und den
HTTP-Status 200 sowie den aktualisierten lokalen Status kontrollieren.
Consent- und Zustellregeln
Abschnitt betitelt „Consent- und Zustellregeln“- Eine Newsletter-Anmeldung startet lokal als
pending. Vor dem Klick auf den zeitlich begrenzten Bestätigungslink findet keine Synchronisation zu Resend statt. - Nur
confirmedplus erfolgreicher Provider-Sync ist für Newsletter-Versand berechtigt. - Abmeldung, Bounce und Complaint unterdrücken den weiteren Versand lokal. Diese lokale Sperre ist maßgeblich, auch wenn Resend nicht erreichbar ist.
- Öffentliche Newsletter-Anmeldungen werden vor Kontaktanlage und E-Mail-Versand persistent pro Client begrenzt; die bestehende Adress-Cooldown- und globale Versandquote bleiben zusätzliche Schutzschichten.
- Empfänger werden im Zustellprotokoll nur als SHA-256-Hash gespeichert. Tokens werden ausschließlich gehasht gespeichert und sind einmalig verwendbar.
- Einzelne E-Mail-Anfragen verwenden einen fachlichen Idempotency-Key. Die Resend-Broadcast-API bietet dafür keinen Idempotency-Key: Die Anwendung reserviert deshalb genau eine lokale Publish-Anfrage, friert einen unveränderlichen Snapshot ein, legt erst einen Provider-Entwurf an und sendet diesen anschließend. Ein unklarer Provider-Timeout wird nicht automatisch wiederholt. Provider- und Quotenfehler werden als begrenzte Fehlercodes gespeichert, nicht als vollständige Payloads.
Newsletter-Veröffentlichung im Admin-UI
Abschnitt betitelt „Newsletter-Veröffentlichung im Admin-UI“Nur aktive Plattform-Admins erreichen das Modul. Entwürfe bestehen aus Betreff, Preheader, Überschrift, Text, optionalem HTTPS-CTA und der typisierten Vornamen-Personalisierung. Freies HTML, aktive Inhalte, unbekannte Variablen und unsichere URLs werden serverseitig abgelehnt. Vorschau, Testmail und Broadcast verwenden denselben Renderer; Impressum, Datenschutz und One-Click-Abmeldung werden zentral ergänzt.
Vor dem Versand zeigt das UI die lokal erneut ermittelte Zahl der Kontakte an, die sowohl
confirmed als auch beim Provider synced und dem konfigurierten Topic zugeordnet sind. Diese Zahl
muss ausdrücklich bestätigt werden und wird unmittelbar in der serialisierbaren Publish-Transaktion
noch einmal geprüft. Das konfigurierte Resend-Segment ist ausschließlich für diese synchronisierten
Topic-Kontakte zu verwenden; seine Pflege ist eine kontrollierte Betriebsänderung. Ein geplanter
Versand muss mindestens zehn Minuten in der Zukunft liegen und
kann bis fünf Minuten vor dem Termin storniert werden. failed ist absichtlich ein sicherer
Endzustand: Nach einem unklaren Provider-Ergebnis findet kein blinder Retry statt; der Zustand wird
zuerst im Resend-Dashboard und Audit-Log abgeglichen.
E-Mail- und Consent-Betrieb im Admin-UI
Abschnitt betitelt „E-Mail- und Consent-Betrieb im Admin-UI“Das Modul „E-Mail-Betrieb“ liest Tages- und Monatsverbrauch aus den von Resend gelieferten
Quota-Headern. Sind diese nicht verfügbar, zeigt es ausdrücklich die lokalen, in
mail_delivery reservierten Sendungen als Fallback an. Die Tarifbezeichnung stammt aus
RESEND_PLAN_NAME, da Resend keinen separaten API-Endpunkt für den aktuellen Tarif bereitstellt.
Eine Warnung erscheint ab RESEND_USAGE_WARNING_PERCENT; die lokalen Hard-Limits bleiben davon
unabhängig wirksam.
Domainstatus und SPF-/DKIM-/DMARC-Status werden serverseitig über die Resend-Domain-API gelesen.
Das Browser-UI erhält weder DNS-Werte noch API-Key oder rohe Providerantworten. Nur die Domains der
konfigurierten Absender werden berücksichtigt. Fehlt eine Domain oder meldet sie einen anderen
Zustand als verified, ist dies vor dem nächsten Versand als Betriebsabweichung zu behandeln.
Zustellübersichten enthalten ausschließlich Versandtyp, Kanal, Zeitpunkt, Status, begrenzten Fehlercode und einen zwölfstelligen Empfänger-Fingerprint. Newsletter-Adressen sind in Listen redigiert. Die vollständige Adresse und der Consent-Nachweis werden nur für einen einzelnen Kontakt über eine auditierte Mutation geladen. Der bestätigte CSV-Export ist auf 1.000 gefilterte, adressfreie Zustellzeilen begrenzt und gegen Spreadsheet-Formelinjektion kodiert.
Ein manueller Provider-Sync-Retry ist nur für lokal weiterhin confirmed und technisch
failed/not_synced zulässig. Jeder Versuch besitzt eine eindeutige Request-ID und einen
persistierten Endzustand; derselbe Request ruft Resend auch nach einem Fehler kein zweites Mal auf.
pending und unsubscribed können über das Admin-UI nicht aktiviert werden. Ändert sich der
Consent während eines Provideraufrufs, bleibt der lokale Status maßgeblich und die Provideranlage
wird bestmöglich kompensiert.
Signierte Webhooks speichern weiterhin nur Payload-Hash und begrenzte Betriebsmetadaten. Erfolgreich
verarbeitete Event-IDs sind endgültig dedupliziert. Schlägt eine verifizierte Verarbeitung fehl,
bleibt der Event als failed sichtbar; eine erneute Providerzustellung derselben ID darf ihn
idempotent verarbeiten. Ungültige Signaturen werden nicht persistiert.
Benutzer- und Auth-Support im Admin-UI
Abschnitt betitelt „Benutzer- und Auth-Support im Admin-UI“Das Modul „Auth-Support“ ist ausschließlich für aktive Plattform-Admins erreichbar. Die Suche akzeptiert E-Mail-Adresse oder Better-Auth-Benutzer-ID, ist paginiert und pro Admin begrenzt. Listen zeigen nur die technische Benutzer-ID, eine redigierte Adresse, Verifizierungsstatus und Erstellungszeit. Der Suchwert selbst wird nicht in das Audit-Log übernommen.
Der auditierte Einzelabruf zeigt verfügbare Auth-Methoden und aktive Sessions ohne Tokens,
IP-Adressen oder User Agents. credential wird lediglich als password ausgewiesen; OAuth-/SSO-
Provider erscheinen als Providerkategorie, niemals mit Account-Identifiern, Access-/Refresh-Tokens
oder Secrets. Das MVP bietet keine Änderung verknüpfter Identitäten, keine Passwortsetzung und keine
Impersonation. „Nicht administrativ gesperrt“ beschreibt nur den administrativen Sperrstatus; ein
temporäres Endpoint-Rate-Limit ist keine Kontosperre.
Eine erneute Verifizierungs- oder Recovery-Mail verlangt explizite Bestätigung, eine nicht-sensitive Begründung und eine höchstens zehn Minuten alte Admin-Sitzung. Der Server ruft dafür den regulären Better-Auth-Endpunkt mit der bereits im Konto hinterlegten Adresse auf. Dadurch bleiben die gleichen Redirect-Prüfungen, Enumeration-Antworten und Rate Limits wirksam. Recovery ist nur für Konten mit Passwortmethode, Verifizierung nur für noch unbestätigte Konten zulässig.
Einzelne oder alle Sessions werden anhand ihrer opaque Session-ID serverseitig gelöscht. Sessiontokens verlassen die API nie. Wiederholung und parallele Ausführung sind sicher: Bereits entfernte Sessions erzeugen keinen neuen Zustand, werden aber als unverändertes Ergebnis auditiert. Der Widerruf greift unmittelbar bei der nächsten authentifizierten Anfrage.
Störungen und Wiederanlauf
Abschnitt betitelt „Störungen und Wiederanlauf“- Bei Fehlern zuerst
mail_delivery.status,failure_code, Tages-/Monatszähler undnewsletter_contact.provider_sync_statusprüfen. Keine Rohadressen oder Tokens in Tickets oder Chat kopieren. - Bei
provider_rate_limitedoderprovider_unavailablekeine ungeprüfte Massenschleife starten. Ursache und Providerstatus klären; danach nur fehlgeschlagene, idempotente Vorgänge gezielt erneut ausführen. - Bei
daily_quota_exceededodermonthly_quota_exceededVersand stoppen. Ein höheres Limit wird erst nach Kosten- und Missbrauchsprüfung als Server-Konfiguration freigegeben. - Bei Bounce/Complaint den lokalen Suppression-Status nicht zurücksetzen. Eine Freigabe erfordert eine dokumentierte fachliche Prüfung und bei Marketing eine neue wirksame Einwilligung.
- Bei kompromittiertem Key: Key in Resend sperren, neuen Key im Secret Store setzen, Anwendung neu starten, relevante Zugriffs- und Zustellereignisse prüfen und den Vorfall dokumentieren.
- Bei fehlgeschlagenen Webhooks zuerst Signaturprüfung, Event-ID,
failure_codeundattempt_countprüfen. Keine Payload aus Logs rekonstruieren oder in Tickets kopieren. Eine erneute Zustellung derselben Provider-ID ist zulässig; eine künstlich neue ID darf nicht erzeugt werden. - Bei Consent-/Topic-Abweichungen keinen Kontakt manuell auf
confirmedsetzen. Den ursprünglichen DOI-Nachweis prüfen und nur den freigegebenen, bestätigten Sync-Retry verwenden. Nach einem unklaren Providerergebnis zuerst Providerzustand und Audit-Request-ID abgleichen.
Datenschutzfreigabe
Abschnitt betitelt „Datenschutzfreigabe“Vor Produktionsbetrieb sind Resend-DPA, aktuelle Subprozessorliste und die Rechtsgrundlage der US-Übermittlung zu dokumentieren. Resend nennt im DPA EU-Standardvertragsklauseln und eine EU-US-DPF-Zertifizierung. Die öffentliche Datenschutzerklärung und der AVV führen Resend als Empfänger beziehungsweise Unterauftragsverarbeiter. Änderungen der Subprozessoren müssen über den internen Datenschutzprozess bewertet werden.
Release-Checkliste
Abschnitt betitelt „Release-Checkliste“- Domainstatus und SPF/DKIM/DMARC für beide Absender geprüft
- Secrets vollständig und ausschließlich serverseitig gesetzt
- Topic vorhanden; Testkontakt wird erst nach Double-Opt-in synchronisiert
- Broadcast-Segment, Topic, Marketing-Absender und interne Test-Allowlist kontrolliert gesetzt
- Tarifname, lokale Limits und Warnschwelle kontrolliert gesetzt; Provider-Quota-Header sichtbar
- Versanddomains sowie SPF, DKIM und DMARC im E-Mail-Betriebsmodul
verified - Admin-Vorschau, Testmail, stale Empfängerzahl, Sofort-/Planversand, Storno und Provider-Ausfall geprüft
- redigierte Zustell-/Consent-Listen, auditierter Einzelnachweis, minimierter Export und idempotenter Sync-Retry geprüft
- Signiertes Webhook-Testevent und Duplikat erfolgreich verarbeitet
- Auth-Verifikation, Passwort-Reset, Magic Link und Workspace-Einladung zugestellt
- Brand-Asset öffentlich erreichbar; Mail bleibt mit blockierten Remote-Bildern verständlich
- Abmeldung, Bounce/Complaint, Provider-Ausfall und lokale Quoten geprüft
- Datenschutz- und AVV-Texte veröffentlicht
- Relevante E2E-Suite sowie gesamtes Release-Gate erfolgreich
- Auth-Supportsuche, Step-up, reguläre Verifizierungs-/Recovery-Mail, Einzel-/Gesamtwiderruf, Rate Limit, Replay, Parallelität und negative Workspace-Autorisierung geprüft

