ZurĂĽck zum Blog
Jul 17, 2026
Engineering
Greta Redaktionsteam

Transaktions-E-Mails in einer KI-gebauten App versenden

Die E-Mail-API direkt im Request-Handler aufzurufen funktioniert in einer Demo und bricht in dem Moment, in dem der Anbieter eine langsame Minute hat. Warum Domain-Authentifizierung und ein queue-basierter, idempotenter Versand das Muster sind, das in der Produktion wirklich hält.

Transaktions-E-Mails in einer KI-gebauten App versenden

Transaktions-E-Mails in einer KI-gebauten App versenden

Kurzantwort

Verschicke Transaktions-E-Mails nicht direkt aus deinem Request-Handler mit einem hartkodierten SMTP-Aufruf. Nutze eine dedizierte E-Mail-API (Resend, Postmark, SES), authentifiziere deine Sende-Domain mit SPF, DKIM und DMARC, bevor du live gehst, und schiebe den eigentlichen Versand in eine Queue, damit ein langsamer E-Mail-Anbieter niemals den Signup- oder Checkout-Flow blockiert, der ihn ausgelöst hat.

Warum "sendEmail() einfach in der Route aufrufen" scheitert

Es fängt harmlos an. Ein Nutzer registriert sich, deine API-Route legt den Account an und ruft dann, noch im selben Request, einen E-Mail-Anbieter auf, um eine Willkommensmail zu verschicken. Bei den ersten zehn Tests funktioniert das einwandfrei.

Dann hat dein E-Mail-Anbieter eine langsame Minute — das passiert, auch bei guten Anbietern — und derselbe Request braucht plötzlich sechs Sekunden länger, weil dein Server auf eine 202-Antwort wartet, die er eigentlich gar nicht synchron braucht. Oder schlimmer: Der Account wird angelegt, der E-Mail-Aufruf wirft einen Fehler, dein Error-Handling macht nichts rückgängig, und der Nutzer hat einen Account, aber nie einen Bestätigungslink erhalten. Er geht davon aus, dass die Registrierung fehlgeschlagen ist, und versucht es erneut.

Ich habe genau diesen Bug in drei verschiedenen Codebasen gesehen. Niemand hat ihn absichtlich geschrieben. Es passiert einfach, wenn "eine E-Mail senden" wie ein Datenbank-Write behandelt wird, statt wie das, was es eigentlich ist: ein Aufruf an einen Drittanbieter-Dienst, den man nicht kontrolliert, der langsam sein kann, fehlschlagen kann und niemals etwas blockieren sollte, auf das der Nutzer wartet.

Das Warnsignal, dass du es falsch machst

Wenn ein Passwort-Reset, eine Quittung oder eine Willkommensmail von Code verschickt wird, der direkt in derselben Funktion sitzt, die den Request des Nutzers verarbeitet, hast du die Uptime deiner App an die Uptime deines E-Mail-Anbieters gekoppelt. Das ist verkehrt herum — eines der beiden sollte einen schlechten Tag haben können, ohne das andere mit runterzuziehen.

Das Muster, das wirklich hält

Ein Transaktions-E-Mail-Setup, das echten Traffic übersteht, hat drei Bestandteile, die zusammenspielen — und keiner davon ist exotisch.

Domain-Authentifizierung, erledigt bevor die erste echte E-Mail verschickt wird. SPF und DKIM sagen empfangenden Mailservern, dass deine App tatsächlich berechtigt ist, als du@deinedomain.com zu senden. DMARC sagt ihnen, was passieren soll, wenn diese Prüfung fehlschlägt. Überspringst du das, landen deine ersten hundert E-Mails im Spam, ganz einfach — Gmail und Outlook geben unauthentifizierten Absendern längst keinen Vertrauensvorschuss mehr. Das ist eine einmalige DNS-Einrichtung, vielleicht zwanzig Minuten, und Anbieter wie Resend und Postmark führen dich genau durch die Einträge, die du hinzufügen musst.

Eine Queue zwischen "etwas ist passiert" und "E-Mail gesendet". Der Signup-Handler ruft nicht die E-Mail-API auf — er schreibt einen Job (send-welcome-email, userId: 123) irgendwo persistent ab, und ein separater Worker holt ihn ab und verschickt ihn. Ist der E-Mail-Anbieter zwei Minuten lang nicht erreichbar, wartet der Job einfach und wird erneut versucht. Der Signup-Request des Nutzers hat längst 200 zurückgegeben und ist weitergelaufen.

Idempotenz beim Versand selbst. Retries sind gut, bis ein Job zweimal läuft und derselbe Kunde vier Minuten auseinander zwei "Ihre Zahlung ist fehlgeschlagen"-Mails bekommt. Gib jedem Job einen eindeutigen Key mit — eine Order-ID, ein Passwort-Reset-Token — und prüfe ihn vor dem Versand, damit ein wiederholter Job, der bereits erfolgreich war, ein No-op ist und keine Dopplung.

Transaktions- und Marketing-E-Mails sind nicht dasselbe Problem

Es ist verlockend, alles — Willkommensmails, wöchentliche Digests, Passwort-Resets — über ein einziges System laufen zu lassen. Lass es. Ein Passwort-Reset muss innerhalb einer Minute ankommen, sonst hat der Nutzer schon aufgegeben und auf "erneut senden" geklickt. Ein wöchentlicher Digest kann eine Stunde warten, das merkt niemand. Beides auf derselben Sende-Domain zu mischen ist außerdem ein Zustellbarkeits-Risiko: Wenn deine Marketing-Mails wegen Spam-Beschwerden markiert werden, willst du nicht, dass das die Domain-Reputation belastet, auf die sich deine Passwort-Resets verlassen. Die meisten Teams landen bei einer eigenen Transaktions-Subdomain (mail.deineapp.com), getrennt von dem, was den Newsletter verschickt.

Ein Vergleich: Inline-Versand vs. Queue-basierter Versand

AspektInline-Versand aus der RouteQueue-basierter Versand mit Worker
Latenz für den NutzerGekoppelt an die Antwortzeit des E-Mail-AnbietersUnbeeinflusst — Request liefert sofort zurück
Verhalten bei Ausfall des AnbietersRequest schlägt fehl oder hängtJob wartet, automatischer Retry
Risiko doppelter E-MailsHoch bei jeder vorgelagerten Retry-LogikNiedrig, wenn der Job einen Idempotenz-Key trägt
Setup-KomplexitätAnfangs niedriger (ein API-Aufruf)Etwas höher (Queue plus Worker)
Wo es brichtBeim ersten langsamen Tag des AnbietersSelten — genau dieses Muster sehen echte Postfächer

Wo das in einer von Greta gebauten App liegt

Da Greta Background Jobs als vollwertigen Bestandteil des Stacks scaffoldet — dasselbe queue-basierte Arbeitsmuster, das in Background Jobs und geplante Tasks ausführen behandelt wird —, bedeutet das Einbinden von Transaktions-E-Mails, einen Job-Typ hinzuzufügen, nicht eine Queue von Grund auf zu bauen. Eine Route wie app/api/webhooks/postmark/route.ts kann sogar Bounce- und Complaint-Events genauso behandeln wie jeden anderen eingehenden Webhook — das Muster, das wir für Signaturprüfung und idempotente Verarbeitung in Webhooks und Drittanbieter-APIs verbinden durchgegangen sind.

Die E-Mail-Templates selbst — Passwort-Reset, Quittung, Einladung — leben als kleine, testbare Funktionen, die Daten entgegennehmen und HTML zurückgeben, sodass du Texte prüfen und anpassen kannst, ohne die Sendelogik überhaupt anzufassen.

FAQ

Welchen E-Mail-Anbieter sollte ich tatsächlich nutzen? Für eine neue App sind sowohl Resend als auch Postmark solide — saubere APIs, gute Zustellbarkeit von Haus aus, angemessene kostenlose Tarife. SES ist bei echtem Volumen günstiger, aber du übernimmst mehr von der Zustellbarkeits-Arbeit selbst. Entscheide dich für einen, authentifiziere die Domain sauber und mach dir darüber hinaus keine allzu großen Gedanken.

Brauche ich schon am ersten Tag eine Queue, auch als Solo-Gründer? Nicht unbedingt für deine ersten fünfzig Nutzer, aber sobald du echte Signups hast, wird eine langsame Anbieter-Antwort zu einer langsamen Registrierung für einen echten Menschen. Das ist ein kleiner Aufwand, den man einbaut, bevor es wichtig wird — verglichen mit einem stressigen Aufwand, den man nach einem Support-Ticket über einen hängenden Registrierungs-Flow nachrüstet.

Wie verhindere ich, dass Transaktions-E-Mails im Spam landen? Authentifiziere die Domain (SPF, DKIM, DMARC), halte Transaktions- und Marketing-Traffic auf getrennten Subdomains und sende von einer Adresse, die Leute wiedererkennen — no-reply@-Adressen schaden dem Engagement, was wiederum der Zustellbarkeit schadet. Wärme eine neue Sende-Domain schrittweise auf, statt vom ersten Tag an mit vollem Volumen zu starten.

Was ist mit E-Mails, die absolut in Echtzeit raus müssen, wie ein Magic-Link-Login? Die können trotzdem über die Queue laufen — ein gut laufender Worker holt einen Job innerhalb ein, zwei Sekunden ab, was schnell genug ist, dass der Nutzer den zusätzlichen Zwischenschritt nicht bemerkt. So behältst du dieselben Zuverlässigkeits-Garantien, statt eine Ausnahme zu schaffen, die zu dem einen Code-Pfad wird, den später niemand mehr zu reparieren weiß.

Fazit

E-Mail fühlt sich wie die einfachste Integration in der ganzen App an — ein API-Aufruf und fertig. Es ist auch die Integration, die am ehesten still und leise auf eine Art scheitert, die niemand bemerkt, bis ein Kunde sagt: "Ich habe meine Quittung nie bekommen." Authentifiziere die Domain, verschiebe den Versand in die Queue, mach ihn idempotent — dann wird es einer der langweiligsten, zuverlässigsten Teile deines Stacks, statt des einen Teils, den du nicht anzufassen wagst.

Starte noch heute mit dem Aufbau deiner App mit Greta.

Ende des Artikels
↑ Zurück nach oben

Baue etwas Echtes

Wenn du es beschreiben kannst, kannst du es bauen.