„Gesendet, aber nicht angekommen“: So debuggt ein Produktteam E-Mail-Zustellung wirklich
Kaum ein Support-Ticket fühlt sich so unerquicklich an wie: „Ich habe die E-Mail gesendet, aber nichts kommt an.“ Für Nutzer ist es ein schwarzes Loch. Für ein Produktteam ist es ein Mix aus Zustellbarkeit, UX, Telemetrie und sauberen Fehlermeldungen. Und ja: In vielen Fällen ist die E-Mail technisch angekommen – nur nicht dort, wo der Nutzer sucht, oder nicht in dem Zeitfenster, das er erwartet.
Dieser Beitrag ist ein praxisnahes Debug-Playbook aus Produktteam-Sicht: Wie du das Problem in klare Kategorien zerlegst, welche Datenpunkte wirklich helfen, wie du Support und Engineering synchronisierst – und wie du mit kleinen UX-Änderungen die Anzahl solcher Fälle spürbar senkst.
1) Zuerst klären: Was bedeutet „nicht erhalten“ genau?
„Nicht erhalten“ ist keine technische Diagnose, sondern ein Symptom. Als Produktteam musst du zunächst die Definition des Fehlers festnageln, bevor du debuggen kannst. Die wichtigsten Varianten:
- Inbox nicht gefunden: Mail ist im Spam/Promotion/Updates gelandet oder wurde gefiltert.
- Verzögert: Mail kommt erst nach Minuten oder sogar Stunden (Greylisting, Throttling, Queue).
- Hard Bounce: Adresse existiert nicht oder Provider lehnt dauerhaft ab.
- Soft Bounce: Temporärer Fehler (Mailbox full, Rate limit, transient DNS/Connection issues).
- Block/Policy Reject: DMARC/Policy, Reputation, Content, oder Domain/Provider-Blockliste.
- Send ist nie passiert: Event wurde im UI als „gesendet“ angezeigt, aber Job/Queue schlug fehl.
- Falsche Zieladresse: Tippfehler, Alias/Weiterleitung, Corporate Gateway, Catch-all.
- Falscher Kanal: Nutzer erwartet eine E-Mail, aber System sendet Push/SMS oder umgekehrt.
In der Praxis bedeutet das: Jede Debug-Session beginnt mit Kontext-Fragen, die du idealerweise nicht im Ticket erfragen musst, sondern schon als strukturierte Telemetrie hast.
2) Das Mindest-Set an Datenpunkten, das jedes Produkt haben sollte
Wenn „gesendet, aber nicht angekommen“ regelmäßig auftaucht, fehlt dir meistens nicht der Mail-Provider – sondern Observability. Als Produktteam brauchst du einen durchgängigen Trace vom UI-Event bis zum Provider-Feedback. Mindestens:
- Message ID (eindeutiger Identifier, über alle Systeme hinweg stabil).
- Timestamp-Kette: UI-Trigger, Job erstellt, Job gestartet, Provider accepted, delivered/bounced.
- Envelope vs. Header: tatsächlicher Empfänger (RCPT TO) und sichtbarer To/CC in den Headern.
- Provider Response Codes: SMTP Status (2xx/4xx/5xx) plus Rohtext.
- Routing-Metadaten: sendende IP/Domain, DKIM Selector, Return-Path, Subdomain/Pool.
- Kampagnen-/Template-Version: welche Vorlage, welche Feature-Flags, welche Locale.
- User Context: Empfänger-Domain (gmail.com, outlook.com, corporate), Region, Account-Typ.
Product Reality Check: Wenn dein Support diese Daten erst „zusammensuchen“ muss, verliert ihr Zeit und eskaliert zu früh. Das Ziel ist, dass ein Ticket in wenigen Minuten in eine Kategorie fällt: Inbox/Delay/Bounce/Reject/No Send.
3) Ein robustes Debug-Framework: Von innen nach außen
Debugging wird zuverlässig, wenn du immer den gleichen Pfad gehst: Produkt → Queue → Provider → Empfänger. Nicht umgekehrt. Das vermeidet „wir probieren alles“.
Schritt A: Produkt-/App-Layer (UI & API)
- Hat der Nutzer wirklich „Send“ ausgelöst? (Button-Klick, API call, retried request)
- Welche Adresse wurde übermittelt? (Client vs. Server normalisiert, Lowercase, Trim)
- Wurde ein Erfolg angezeigt? Falls ja: basiert er auf „Job queued“ oder „Provider accepted“?
- Idempotency: Kann ein Retry doppelt senden oder bricht er still ab?
Produktteams machen hier oft einen UX-Fehler: „Erfolgreich gesendet“ wird angezeigt, sobald der Job in die Queue geschrieben wurde. Das ist für Systeme okay, aber für Nutzer irreführend. Besser sind zwei Zustände: „Wird gesendet“ (queued) und „Versand bestätigt“ (provider accepted).
Schritt B: Queue/Worker-Layer
- Wurde der Job konsumiert? (Worker Log + Message ID)
- Gab es Retries? Wie viele, in welchem Backoff, mit welcher letzten Fehlermeldung?
- Rate Limits: Wurde throttled? Ist das sichtbar?
- Dead-letter Queue: Liegt die Nachricht dort?
Typischer Produktbug: Der Worker sendet erfolgreich, aber der Status wird nicht zurückgeschrieben. Dann steht im System „gesendet“, aber es fehlt das Provider-Acceptance-Signal. Umgekehrt kann ein Job auch scheitern, während das UI schon Erfolg signalisiert.
Schritt C: Provider-Layer (SMTP & Events)
- Accepted: Hat der Provider mit 250/2xx angenommen?
- Bounce: 5xx = dauerhaft, 4xx = temporär (meist mit Retry-Pfad).
- Suppression: Wurde die Adresse intern blockiert (z. B. früherer Hard Bounce)?
- Feedback Loops: Spam complaints, die Reputation beeinflussen.
Aus Produktteam-Sicht ist „accepted“ nicht gleich „delivered“. Aber „accepted“ ist ein harter Schnittpunkt: Ab dort sind UI/Backend selten der Schuldige, sondern Policy, Reputation, Content oder Empfänger-System.
4) Der häufigste Grund: Die Mail ist da – nur nicht in der Inbox
Wenn Nutzer „nicht angekommen“ sagen, meinen sie oft „nicht in meinem Posteingang sichtbar“. Gerade bei Gmail, Outlook und Firmen-Mail-Systemen kann eine Nachricht in andere Bereiche sortiert werden. Als Produktteam solltest du dafür einen Standard-Antwortblock haben, aber noch besser: UX-Guidance direkt im Produkt.
Spam/Promotions/Quarantäne
- Gmail: Spam, „Werbung“, „Benachrichtigungen“ – auch abhängig vom Inhalt.
- Outlook: Junk, „Other“ vs. „Focused Inbox“.
- Corporate: Secure Email Gateway (SEG) mit Quarantäne, die nur Admins sehen.
Produktmaßnahme: Wenn es um Login-Codes oder Magic Links geht, bau eine kompakte Hilfe ein: „Bitte prüfe auch Spam/Junk/Promotions. In Firmenumgebungen kann die Mail in Quarantäne landen.“ Das spart Tickets, ohne dass du technisch etwas ändern musst.
5) Verzögerungen: Warum „kommt nicht“ oft „kommt später“ bedeutet
Verzögerungen sind perfide, weil sie wie „nicht angekommen“ wirken. Typische Ursachen:
- Greylisting: Empfänger sagt zunächst „versuch später nochmal“ (4xx), erwartet Retry.
- Throttling: Provider nimmt nur eine bestimmte Rate an, der Rest wird verzögert.
- Queue Backlog: Worker-Stau, Deployments, Incident, Rate-Limits.
- DNS/TLS Hiccups: Kurzzeitige Netzwerkprobleme führen zu Retries.
Als Produktteam solltest du hier zwei Dinge priorisieren: transparente Zustände und klare Retry-Policy. Wenn ein OTP nur 10 Minuten gültig ist, aber der Provider im Grenzfall 6–8 Minuten verzögert, erzeugst du unabsichtlich eine Failure-Spirale: Nutzer klickt erneut, System sendet erneut, Reputation leidet, Verzögerung steigt.
Produkt-Check: TTL vs. reale Zustellzeit
Prüfe, ob die Gültigkeitsdauer von Codes/Links zur realen Zustellzeit passt. Für viele Produkte ist ein etwas längeres Zeitfenster (oder die Möglichkeit, den Code erneut zu schicken) der günstigste Fix. Wichtig ist, dass „erneut senden“ nicht unlimitiert ist, sondern mit Backoff und Anti-Abuse Schutz arbeitet.
6) Technische Klassiker: SPF, DKIM, DMARC – und warum sie aus Produkt-Sicht wichtig sind
Viele Teams behandeln SPF/DKIM/DMARC als reines Infra-Thema. In Wahrheit ist es ein Produktproblem, weil Zustellbarkeit direkt Conversion und Retention beeinflusst.
SPF
SPF prüft, ob die sendende IP/Server im DNS der Domain autorisiert ist. Fehler entstehen oft durch mehrere Provider, veraltete Einträge oder zu viele DNS-Lookups.
DKIM
DKIM signiert die Mail kryptografisch. Wenn Signaturen fehlen oder ungültig sind, sinkt Vertrauen bei Empfängern – und bei strengen Policies kann die Mail abgelehnt werden.
DMARC
DMARC verbindet SPF/DKIM mit Alignment-Regeln und einer Policy (none/quarantine/reject). Bei „reject“ kann eine falsch konfigurierte Absender-Domain dazu führen, dass E-Mails konsequent verschwinden.
Produktteam-Takeaway: Du brauchst ein Dashboard, das zeigt, ob du für wichtige Mail-Typen (OTP, Welcome, Reset) saubere Authentifizierung hast. Und du brauchst Alerts, wenn plötzlich mehr Rejects auftreten.
7) „Accepted, aber nie delivered“: Reputation, Content und Policies
Wenn der Provider „accepted“ meldet, aber Nutzer weiterhin nichts sehen, bist du oft im Feld Inbox Placement oder Silent Filtering. Typische Trigger:
- Sender Reputation: neue IPs/Domains, hohe Bounce-Rate, viele Beschwerden.
- Content Flags: zu viele Links, URL-Shortener, aggressive Keywords, ungewöhnliche HTML-Struktur.
- Domain Mismatch: sichtbarer From-Name/Domain passt nicht zum Return-Path.
- List-Unsubscribe/Headers fehlen: bei Marketing-Mails ein Qualitätsmerkmal.
- Attachment/Inline Images: je nach Provider riskanter, besonders bei neuen Sendern.
Hier hilft ein produktorientierter Ansatz: Trenne Mail-Streams. OTP/Reset laufen über einen konservativen, „sauberen“ Stream mit minimalem HTML, klarer Betreffzeile und wenig Links. Marketing/Newsletter ist ein eigener Stream. Damit schützt du die kritischen Transaktionsmails vor Reputation-Schäden durch Kampagnen.
8) Support-Playbook: Fragen, die wirklich weiterhelfen
Support darf nicht raten. Gib ihnen ein kurzes, strukturiertes Formular, das sie im Ticket abarbeiten. Ideal ist, wenn das Produkt schon viel automatisch befüllt (Message ID, Status, Provider Response).
- Welche Adresse und welche Domain? (z. B. gmail.com, outlook.com, Firmen-Domain)
- Wann wurde gesendet? (Zeitzone, ungefähre Minute)
- Welche Mail-Art? (OTP, Reset, Invite, Receipt, Newsletter)
- Spam/Junk/Quarantäne geprüft? (inkl. Promotions/Focused Inbox)
- Weiterleitung/alias aktiv? (Apple Hide My Email, Gmail Aliases, Firmen-Routing)
Wichtig: Support sollte keine 10-Minuten-Checkliste an Nutzer schicken, wenn im System bereits klar ist, dass es ein Hard Bounce war. Das wirkt unseriös. Umgekehrt sollte man bei „delivered“ nicht sofort Infra eskalieren, sondern zuerst Inbox/Quarantäne adressieren.
9) Produkt-UX Fixes, die „Sent but not received“ drastisch reduzieren
1) Status klar benennen
Zeige nicht „gesendet“, wenn es nur „queued“ ist. Nutze klare Zustände: Wird gesendet → Versand bestätigt → Zugestellt (wenn verfügbar). Wenn „zugestellt“ nicht sicher messbar ist, bleib ehrlich: „Vom Mailserver angenommen“.
2) „Erneut senden“ mit Schutz
Biete einen erneuten Versand an, aber mit Cooldown (z. B. 30–60 Sekunden) und klarer Anzeige, wann der nächste Versuch möglich ist. Kombiniere es mit einem Hinweis: „Bitte prüfe auch Spam/Junk – besonders bei Firmen-E-Mail.“
3) Alternative Zustellwege anbieten
Wenn es um Login/OTP geht, ist ein zweiter Kanal Gold wert: Backup-E-Mail, Push, SMS oder authenticator-based Codes. Produktteams unterschätzen, wie viele Nutzer in strengen Corporate-Umgebungen hängen, wo Mails verzögert oder gefiltert werden.
4) Saubere „Change Email“-Journey
Viele Fälle sind schlicht Tippfehler. Unterstütze: Autocomplete, Domain-Hinweise („me.com“ vs „mac.com“), Warnungen bei häufigen Fehlern und eine schnelle Möglichkeit, die Adresse zu korrigieren, ohne den gesamten Flow neu zu starten.
5) Content minimal für kritische Mails
OTP- und Reset-Mails sollten extrem robust sein: wenig HTML, klare Textversion, kein unnötiges Tracking, stabile Betreffzeilen. In der Praxis verbessert das nicht nur Zustellbarkeit, sondern auch Vertrauen.
10) Ein Incident-ähnlicher Ablauf: So arbeitet das Team effizient
Wenn die Fälle zunehmen, behandel es wie einen Mini-Incident. Ein Beispiel-Ablauf:
- Triage: Welche Domains sind betroffen? Ist es regional? Betrifft es nur OTP oder alles?
- Signals: Bounce-Rate, Reject-Rate, Queue-Lag, Provider Errors, Spam complaints.
- Scope: Einzelne Provider (z. B. Outlook) vs. global. Neue Deployments oder DNS-Änderungen?
- Mitigation: Rate reduzieren, Stream wechseln, Templates vereinfachen, Retries anpassen.
- Comms: Status-Update im Produkt oder Status-Page, falls massiv.
- Postmortem: Root Cause + dauerhafte Fixes (Auth, Observability, UX).
Der Produktaspekt ist hier entscheidend: Selbst wenn die technische Ursache „nur“ Reputation oder Provider-Policy ist, kannst du mit UX-Guidance, klaren Statusmeldungen und alternativen Kanälen die Auswirkungen stark abfedern.
11) Praxisbeispiel: Das typische Ticket – und wie man es sauber auflöst
Stell dir vor, ein Nutzer schreibt: „Ich habe den Code angefordert, aber es kommt nichts an.“ Früher ging es. Der Support sieht im Dashboard: Message ID vorhanden, Provider hat mit 250 accepted. Kein Bounce. Keine Rejects.
Produktteam-Interpretation: Das ist sehr wahrscheinlich Inbox Placement oder Corporate Quarantine. Der Support antwortet nicht mit generischem „Bitte warten“, sondern gezielt: Spam/Junk/Promotions prüfen, Fokus/Andere bei Outlook, Firmen-Quarantäne beim Admin erfragen, und parallel die Option „Code erneut senden“ nach Ablauf des Cooldowns anbieten.
Zusätzlich schaut Engineering in die Metriken: Steigt die Zustellzeit? Gibt es vermehrte 4xx? Falls ja, Retries/Backoff prüfen. Falls nein, ist es eher ein Routing/Inbox-Thema. So wird aus einem diffusen Problem ein kontrollierbarer Prozess.
12) Fazit: Debugging ist zu 50% Technik und zu 50% Produktführung
„Sent but not received“ ist selten ein einzelner Bug. Es ist ein System-Thema: Zustellbarkeit, Telemetrie, klare Zustände im UI, Retry-Policy und Support-Enablement greifen ineinander. Ein starkes Produktteam sorgt dafür, dass jede Nachricht eine Trace hat, jeder Status ehrlich kommuniziert wird und Nutzer nicht im Dunkeln tappen.
Wenn du nur eine Sache heute umsetzt, dann diese: Baue ein Message-Tracing mit eindeutiger ID und zeige im internen Dashboard die gesamte Reise: Trigger → Queue → Provider Accepted → Bounce/Reject/Delay. Damit werden 80% der „mysteriösen“ Fälle in Minuten erklärbar – und dein Produkt wirkt sofort vertrauenswürdiger.