E-Mail-Events
Wir senden Events, während jeder Empfänger den Zustellprozess durchläuft. Ein Versand an drei Adressen erzeugt drei unabhängige Streams, korreliert über email_id und recipient_id. Diese Seite definiert die E-Mail-Event-Typen. Siehe Webhooks für Signaturen, Wiederholungen, Reihenfolge und Replay.
Jeder Empfänger startet bei email.accepted, dann email.processed. Ein Broadcast-Empfänger ist eine eigene Nachricht und bekommt daher auch eine eigene email.accepted, allerdings nur in den Events API und im E-Mail-Log, nicht als Webhook. Von dort wird die Nachricht vom empfangenden Server akzeptiert (email.delivered), verzögert und erneut versucht (email.deferred, was sich zu zugestellt oder gebounced auflöst), vom empfangenden Server abgelehnt (email.bounced) oder erhält gar keinen Zustellversuch (email.rejected). Nach einer Zustellung kann der Stream mit email.out_of_band_bounce, email.complained, email.opened, email.clicked, email.unsubscribed und email.list_unsubscribed weitergehen.
Jeder Empfänger endet in genau einem terminalen Status: delivered, bounced, complained oder rejected, zurückgegeben als status pro Empfänger von GET /v1/email/messages/{message_id}/recipients. Engagement-Events ändern ihn nie: Ein Empfänger, der geöffnet hat, bleibt delivered. Ein verspäteter Bounce-Report ändert ihn jedoch, weil der empfangende Server eine bereits erteilte Annahme zurückzieht, sodass der Empfänger von delivered zu bounced wechselt. Die Nachricht als Ganzes hat ihren eigenen zusammengefassten Status und Zähler pro Zustand auf GET /v1/email/messages/{message_id}.
Der Event-Envelope
Events kommen als Drei-Felder-Envelope an, den jeder Webhook verwendet: type, timestamp (wann das Event eingetreten ist, RFC 3339) und ein typspezifisches data-Objekt.
Codebeispiel
{
"type": "email.delivered",
"timestamp": "2026-07-23T14:51:47.107Z",
"data": {
"email_id": "em_01ky7qc398fmxraqtxn604zeq9",
"recipient_id": "er_01ky7qc398fmwsc96nt6anrbqs",
"workspace_id": "ws_01ky7m21hjffh9s8kq76gyb1xf",
"recipient": "delivered@messagebird.dev",
"recipient_role": "to",
"tags": [{ "name": "category", "value": "welcome" }],
"metadata": { "order_id": "ord_123" },
"broadcast_id": null
}
}Jedes ausgehende Event enthält email_id, recipient_id, workspace_id, die recipient-Adresse und deren Envelope recipient_role (to, cc oder bcc). Es gibt außerdem tags und metadata aus dem Versandauftrag zurück, damit Sie das Event mit Ihren Datensätzen korrelieren können. Jeder optionale Wert ist null, wenn der Versand keinen hatte, einschließlich broadcast_id: Es benennt den Broadcast, zu dem ein Versand gehört, sodass Sie die Events eines Broadcasts gruppieren können, ohne jeden Versand einzeln nachzuschlagen, und es ist null bei einem Versand ohne Broadcast. Ein Sonderfall meldet null für einen Versand, der einen hatte: Ein Abmeldelink aus E-Mails, die vor Einführung des Feldes gesendet wurden, benennt keinen Broadcast. Ein Opt-out über einen solchen Link meldet daher null bei email.unsubscribed und email.list_unsubscribed, unabhängig davon, ob ein Broadcast die E-Mail gesendet hat. Behandeln Sie null bei diesen beiden Events als nicht aussagekräftig, sonst zählen Sie die Opt-outs eines Broadcasts zu niedrig. broadcast_id erreicht Sie nur über den Webhook: Die Events API unten geben jedes Event ohne dieses Feld zurück. Event-Typen fügen Felder hinzu, die in den Abschnitten Lebenszyklus, Engagement, Suppression und Inbound beschrieben werden.
Dieselben Events sind nachträglich über GET /v1/email/messages/{message_id}/events abfragbar, wo jedes außerdem eine id (ev_-Präfix) und eine occurred_at hat. Nutzen Sie sie zum Nachfüllen, Replay oder Abgleich mit dem, was Ihr Endpunkt empfangen hat. Einige Felder erreichen Sie nur über diese API und nicht über den Webhook; die jeweilige Event-Beschreibung kennzeichnet jedes einzelne.
Lebenszyklus-Events
email.accepted
Wir haben den Versand angenommen und mit der Zustellvorbereitung begonnen. Wird einmal pro angefordertem Empfänger ausgelöst und ist das erste Event in diesem Stream. Ein Broadcast-Empfänger bekommt ebenfalls eines, weil jeder Empfänger eine eigene Nachricht ist, aber es wird aufgezeichnet statt zugestellt: Lesen Sie es aus den Events API oder dem E-Mail-Log, nicht von Ihrem Webhook-Endpunkt. Payload: nur die Identity-Basis.
email.processed
Die Nachricht ist aufgebaut und zur Zustellung an den Mailserver des Empfängers eingereiht. Payload: nur die Identity-Basis über den Webhook; die Events API ergänzen mailbox_provider und mailbox_provider_region, die Klassifizierung des empfangenden Mailsystems (zum Beispiel gmail, NA), vorhanden wenn ermittelbar, sonst null. Der Vergleich des timestamp dieses Events mit dem von email.accepted ergibt Ihre eigene Verarbeitungszeit bei einem einzelnen Versand. Ein Broadcast hat kein solches Intervall: Annahme und Verarbeitung tragen denselben Dispatch-Zeitpunkt, sodass die beiden Zeitstempel übereinstimmen statt eine Verarbeitung einzurahmen, und die Annahme erreicht Sie nur über die Events API, als occurred_at.
email.delivered
Der empfangende Mailserver hat die Nachricht akzeptiert und die Verantwortung dafür übernommen. Dieses Event bestätigt weder Inbox-Platzierung noch Lesen. Inbox Insights liefert stichprobenbasierte Platzierungsschätzungen; Öffnungs- und Klick-Events zeichnen Tracking-Anfragen auf. Payload: nur die Identity-Basis über den Webhook; die Events API ergänzen sending_ip, die Adresse, von der die Nachricht gesendet wurde, was relevant ist, wenn ein Zustellproblem auf eine IP zurückgeht, plus mailbox_provider und mailbox_provider_region.
email.deferred
Ein vorübergehender Fehler: Der empfangende Server hat uns gebeten, es später erneut zu versuchen (volles Postfach, Greylisting, Begrenzung der Anfragerate). Wir wiederholen automatisch, und der Empfänger löst sich schließlich zu email.delivered oder email.bounced auf, sodass dieses Event informativ und nicht terminal ist, und ein Empfänger kann vorher mehrfach verzögert werden. Payload: bounce_type, bounce_class, defer_reason (der vom Server angegebene Grund) und sending_ip über den Webhook; die Events API ergänzen mailbox_provider und mailbox_provider_region.
Fehler-Events
email.bounced
Ein permanenter Fehler zum Zeitpunkt SMTP: Der empfangende Server hat die Nachricht abgelehnt, und der terminale Status des Empfängers wird bounced. Payload: bounce_type (siehe Klassifizierungstabelle), bounce_class, bounce_code (der SMTP-Antwortcode, zum Beispiel 550), bounce_description (der vom Server angegebene Grund) und sending_ip über den Webhook; die Events API ergänzen mailbox_provider und mailbox_provider_region. Ein Hard Bounce unterdrückt die Adresse.
email.out_of_band_bounce
Ein verspäteter Bounce: Der empfangende Server hat die Nachricht zum Zeitpunkt SMTP akzeptiert und danach einen Bounce-Report gesendet. Er hat dieselbe Klassifizierung wie email.bounced (bounce_type, bounce_class, bounce_code, bounce_description, sending_ip über den Webhook; mailbox_provider und mailbox_provider_region aus den Events API). Wenn der Report als Bounce klassifiziert wird (jede Klasse in der Tabelle), hat der Server seine frühere Annahme zurückgezogen, sodass der Empfänger von delivered zu bounced wechselt. Reports, deren Klasse nicht in der Tabelle steht, etwa Auto-Replies, werden auf der Timeline aufgezeichnet und lassen den Status unverändert. Ein harter Out-of-Band-Bounce unterdrückt die Adresse ebenfalls.
email.rejected
Der Empfänger hat den Remote-Mailserver nie erreicht, es wurde also kein Zustellversuch unternommen. Das unterscheidet eine Ablehnung von einem Bounce, bei dem der empfangende Server das Nein ausspricht. Payload: rejection_reason, auch im Empfänger-Datensatz, einer von:
| rejection_reason | Bedeutung |
|---|---|
| recipient_suppressed | Der Empfänger ist auf Workspace-Ebene blockiert, durch die Suppressionsliste oder eine erklärte Präferenz, sodass kein Zustellversuch unternommen wurde |
| transmission_failed | Die Nachricht konnte nicht zur Zustellung übermittelt werden |
| generation_failure | Die Nachricht konnte nicht zur Zustellung aufgebaut werden, ein Template- oder Inhaltsproblem |
| policy_rejection | Die Versandrichtlinie hat die Nachricht abgelehnt |
| domain_unverified | Die Absendedomain war nicht verifiziert |
| quota_exceeded | Das Versandkontingent der Organisation wurde erreicht |
| recipient_not_allowed | Der Empfänger war für diesen Versand nicht zulässig; Versand über eine gemeinsame Onboarding-Domain erreicht nur verifizierte Mitglieder Ihres Workspace |
Die Events API ergänzen außerdem mailbox_provider und mailbox_provider_region, wenn das empfangende Mailsystem vor der Ablehnung klassifiziert werden konnte.
email.complained
Der Empfänger hat die Nachricht als Spam markiert, und der Mailbox-Anbieter hat dies über seine Feedback-Schleife zurückgemeldet. Beschwerden kommen nach der Zustellung und setzen den terminalen Status auf complained. Payload: feedback_type, die Art des vom Anbieter gesendeten Reports, zum Beispiel abuse oder fraud, und null, wenn der Anbieter keine Angabe machte, plus mailbox_provider und mailbox_provider_region aus den Events API. Eine Beschwerde unterdrückt die Adresse für Marketing-E-Mails. Halten Sie Ihre Beschwerderate niedrig: Anbieter drosseln Absender, die Reports ansammeln.
Engagement-Events
email.opened
Das Tracking-Pixel im Nachrichtentext wurde geladen. Payload: ip_address und user_agent, wenn bekannt; die Events API ergänzen is_prefetched, country (ISO 3166-1 alpha-2, abgeleitet von der Client-IP), mailbox_provider und mailbox_provider_region. Prüfen Sie is_prefetched, bevor Sie eine Öffnung zählen. Es ist true, wenn eine Inbox-Datenschutzfunktion das Pixel automatisch abgerufen hat, anstatt dass eine Person die Nachricht geöffnet hat, und das Mitzählen solcher Abrufe bläht Ihre Öffnungsrate auf. Öffnungs- und Klick-Tracking behandelt die Instrumentierung.
email.clicked
Der Empfänger hat einen getrackten Link angeklickt. Payload: url (der angeklickte Link), ip_address und user_agent, wenn bekannt; die Events API ergänzen country, mailbox_provider und mailbox_provider_region. Klicks sind in der Regel ein stärkeres Engagement-Signal als Öffnungen, weil Datenschutz-Proxys Tracking-Pixel automatisch laden können.
email.unsubscribed
Der Empfänger hat den Abmeldelink im Nachrichtentext verwendet. Payload: nur die Identity-Basis über den Webhook; die Events API ergänzen mailbox_provider und mailbox_provider_region. Zeichnet eine Opt-out-Präferenz auf, die Marketing-E-Mails blockiert. Abmeldelinks beschreibt, wie der Link in Ihre E-Mail gelangt.
email.list_unsubscribed
Der Empfänger hat den Ein-Klick-Abmeldebutton verwendet, den der Mailbox-Anbieter in seiner eigenen UI rendert, gesteuert über die List-Unsubscribe-Header der Nachricht. Payload: nur die Identity-Basis über den Webhook (plus mailbox_provider und mailbox_provider_region aus den Events API); der Mechanismus ist der Event-Typ selbst, weshalb er von email.unsubscribed getrennt ist. Zeichnet ebenfalls eine Opt-out-Präferenz auf, die Marketing-E-Mails blockiert.
Events auf Nachrichtenebene
Zwei Events beschreiben die Nachricht als Ganzes statt einen einzelnen Empfänger, sodass ihr data die Felder email_id, workspace_id, tags und metadata hat, aber keine Empfänger-Identität. Beide gehören zum zeitgesteuerten Versand.
email.scheduled
Wir haben einen Versand mit einem scheduled_at in der Zukunft angenommen. Payload: die Nachrichtenebene-Basis plus scheduled_at. Wenn dieser Zeitpunkt eintritt, startet der Lebenszyklus pro Empfänger bei email.accepted.
email.canceled
Eine geplante Nachricht wurde abgebrochen, bevor sie versendet wurde, sodass sie keinerlei Empfänger-Lebenszyklus-Events erzeugt. Payload: nur die Nachrichtenebene-Basis.
Inbound- und Mailbox-Events
email.received deckt eingehende E-Mails ab. Es wird ausgelöst, wenn wir eine eingehende Nachricht empfangen und parsen. Sein Payload umfasst die inbound_message_id, Adressierung, Betreff und Authentifizierungsergebnisse. Setup, Payload und der Abruf-API sind in E-Mail empfangen beschrieben. Eine Mailbox hat darüber hinaus ihre eigene email_mailbox.*-Familie, behandelt im Mailbox-Leitfaden.
Bounce-Klassifizierung
bounce_class ist die numerische Bounce-Klassifizierung, die bei email.bounced, email.out_of_band_bounce und email.deferred enthalten ist. Sie fasst sich in die grobe Klasse bounce_type zusammen und behält den feingranularen Code, sodass Sie ein volles Postfach von einem Routing-Fehler unterscheiden können, obwohl beide als soft gemeldet werden:
| bounce_class | bounce_type | Bedeutung |
|---|---|---|
| 1 | undetermined | Die Antwort des empfangenden Servers war mehrdeutig |
| 10, 30 | hard | Permanenter Fehler: ungültige Adresse oder eine Domain, die nicht existiert |
| 20 to 24, 40, 70, 100 | soft | Vorübergehender Fehler: volles Postfach, Server vorübergehend nicht erreichbar, DNS- oder Routing-Problem |
| 25 | admin | Administrative Ablehnung: Relaying verweigert, Domain auf Blocklist |
| 50 to 54 | block | Der empfangende Server hat die sendende IP abgelehnt |
Jede Klasse außerhalb dieser Liste wird auf undetermined abgebildet. Nur hard-Bounces unterdrücken die Adresse; soft, block, admin und undetermined tun dies nicht, weil die Adresse möglicherweise noch zustellbar ist.
Auto-Suppression
Zwei Events fügen einen Empfänger automatisch zur Suppressionsliste des Workspace hinzu, und sie blockieren unterschiedliche E-Mails:
| Event | Suppression reason | Was blockiert wird |
|---|---|---|
| email.bounced oder email.out_of_band_bounce mit bounce_type: "hard" | hard_bounce | Alle E-Mails, einschließlich transaktionaler |
| email.complained | complaint | Marketing-E-Mails; transaktionale werden weiterhin gesendet |
Ein Hard Bounce blockiert alles, weil die Adresse selbst nicht mehr existiert. Eine Beschwerde blockiert nur Marketing, weil jemand, der Ihren Newsletter als Spam gemeldet hat, trotzdem noch seine Passwortzurücksetzung benötigt.
email.unsubscribed und email.list_unsubscribed blockieren E-Mails auf die gleiche Weise wie eine Beschwerde, nur Marketing, aber über einen anderen Datensatz: Statt eine Suppression hinzuzufügen, zeichnen sie das Opt-out des Empfängers als erklärte Präferenz auf. Was ein Opt-out bewirkt behandelt diesen Datensatz vollständig.
Jeder Eintrag löst ein email_suppression.created-Event aus, das die suppression_id, die unterdrückte email, die reason und die workspace_id enthält. Das vollständige Datensatzschema und die manuelle Verwaltung von Einträgen finden Sie im Suppressions-Leitfaden.
Spätere Versendungen an eine unterdrückte Adresse werden sofort als email.rejected mit rejection_reason: "recipient_suppressed" abgelehnt und zählen nie gegen Ihre Zustellbarkeit.
Nächste Schritte
- Webhooks & Events: Endpunkt-Setup, Signaturverifizierung, Wiederholungen und Replay
- Suppressions: Wie die Suppressionsliste funktioniert und wie Sie sie verwalten
- Abmeldelinks: Die Pfade hinter email.unsubscribed und email.list_unsubscribed einrichten
- Testing & Sandbox: Sandbox-Versendungen erzeugen echte Events über den normalen Pfad, was der günstigste Weg ist, Ihren Handler zu testen
- Webhooks richtig gemacht: zuverlässige Zustellungsereignisse: Ein Video, das einen Webhook erstellt und die eintreffenden Events zeigt
Related resources
Continue with the documentation, guides and examples for this topic. Resources are in English.
Watch the guideGetting started with emailExplore the capabilityEmailFollow the learning pathBuild your first integrationImplementation guideSend your first email
Try the practice and get an implementation brief