Wissensdatenbank
Webhooks
Ihrem Endpunkt mitteilen, wenn Mail eintrifft, statt Sie pollen zu lassen.
Details
- Heute nutzbar unter Einstellungen → Webhooks und über die API: einen https-Endpunkt registrieren, auswählen, welche der zwanzig Events er möchte, und das Signatur-Secret mit dem Präfix whsec_ kopieren, das bei der Erstellung und bei der Rotation gezeigt wird und danach nie wieder. Auslieferungen sind echte signierte POSTs, die vom Postfach selbst und nicht von einem API-Aufruf ausgelöst werden; sie feuern also bei eingehender Mail und bei Öffnungen und Klicks, ganz gleich, was die Nachricht gesendet hat. Das Senden feuert von jeder Oberfläche, und früher feuerte es nur von einigen: Ein Versand über die API, MCP, eine Vorlage oder eine Regel löste email.sent aus, eine aus dem Composer der App gesendete Nachricht dagegen nicht, weil der Composer direkt in das Postfach schreibt und nicht über den Sendedienst, der das Event ausgab. Das Event wird jetzt am Postfach selbst ausgelöst, wo alle zusammentreffen; in der App verfassen, für Dienstag planen und an die API posten sind also drei Wege, denselben Webhook auszulösen. Ein aufgeschobener Versand sagt es zweimal: email.scheduled oder email.queued bei der Annahme, email.sent, wenn er tatsächlich hinausgeht, und email.cancelled, wenn Sie ihn zwischendurch zurücknehmen. Zehn Endpunkte pro Postfach, durchgesetzt überall dort, wo einer registriert wird, und nicht nur auf diesem Bildschirm.
- Die Events kommen in drei Familien. Fünfzehn betreffen eine einzelne Nachricht: email.received, email.replied, email.sent, email.delivered, email.failed, email.cancelled, email.scheduled, email.queued (das Undo-Send-Geschwister von scheduled), email.delivery_delayed, email.bounced, email.complained, email.suppressed, email.opened, email.clicked und email.downloaded. email.sent bedeutet, dass der Sendedienst die Nachricht angenommen hat, email.delivered, dass der empfangende Server das getan hat, und email.delivery_delayed, dass sie noch nicht angekommen ist und weiterhin erneut versucht wird. email.replied feuert zusammen mit email.received, wenn die eintreffende Nachricht eine bereits im Postfach liegende beantwortet; ein Konsument, der beide möchte, bekommt beide. email.downloaded feuert, wenn eine Person eine Datei abruft, die als Download-Link hinausgegangen ist, wobei derselbe Klassifizierer Scanner und Link-Vorschauen aus der Zählung heraushält, und es nennt keinen Empfänger, weil der Link für alle, an die die Nachricht ging, derselbe ist. Drei betreffen eine Domain: domain.verified, wenn sie zu empfangen beginnt, domain.sending_changed, wenn sich ihr Sendeurteil ändert, und domain.deleted, wenn sie entfernt wird, ob Sie darum gebeten haben oder der Sieben-Tage-Reaper sie unverifiziert verworfen hat. Zwei betreffen die Sperrliste selbst, die etwas anderes ist als email.suppressed: suppression.added, wenn eine Adresse daraufkommt, suppression.removed, wenn eine wieder erlaubt wird. Keines davon zu abonnieren bedeutet jedes Nachrichten-Event außer email.replied, heute vierzehn, nie eine später hinzugefügte Familie, und die API liest das als ["*"] zurück. Benennen Sie die gewünschten Events, wenn Sie es lieber ausdrücklich hätten. Jede Auslieferung trägt X-OpenEmail-Signature als t=<unix>,v1=<hex>, ein HMAC-SHA-256 über den Zeitstempel, einen Punkt und den rohen Body, dazu X-OpenEmail-Event und X-OpenEmail-Delivery. Verifizieren Sie gegen die Bytes, wie sie eingetroffen sind: Parsen und erneutes Serialisieren ordnet Schlüssel um und zerstört die Signatur. Das Replay-Fenster von 300 Sekunden durchzusetzen ist Sache des Empfängers, und der Verifizierer des SDK verwendet es als Standard.
- Die Registrierung wird für alles abgelehnt, was nicht https oder nicht öffentlich routbar ist (Loopback, RFC1918, Link-Local, CGNAT und die IPv6-Entsprechungen), und Weiterleitungen wird nicht gefolgt; ein 3xx wird also als fehlgeschlagene Auslieferung verbucht und nicht anderswohin verfolgt. Der Empfänger bekommt 5 Sekunden, Endpunkte werden parallel beliefert, zehn davon kosten also weiterhin 5 Sekunden statt 50, und die letzten Versuche sind auf der Seite dieses Endpunkts mit dem Antwortcode und der Dauer aufgelistet.
- Eine Auslieferung wird bis zu fünfmal versucht. Der erste Versuch geht hinaus, während das Event geschieht; ein Fehlschlag, der sich plausibel von selbst erledigen könnte, wird nach 1 Minute erneut versucht, dann nach 5, dann nach 25, dann nach 2 Stunden, was ein Event über etwa zweieinhalb Stunden streckt. Wiederholungen werden als dauerhafte Arbeit gehalten und nicht im Speicher, ein Deploy mitten in diesem Fenster verliert sie also nicht. Wiederholt wird nur, was eine Wiederholung wert ist: ein Timeout, eine abgelehnte Verbindung, 408, 425, 429 oder ein beliebiges 5xx. Jedes andere 4xx ist der Endpunkt, der die Payload bewusst zurückweist, und noch viermal zu fragen wäre die vierfache Last für dieselbe Antwort. Die Event-id wird einmal erzeugt, und jeder Versuch trägt sie in X-OpenEmail-Delivery; ein Empfänger, der dieselbe id zweimal sieht, kann die zweite verwerfen, statt zweimal zu handeln. Nachdem 100 Events in Folge bei jedem Versuch fehlgeschlagen sind, wird der Endpunkt deaktiviert, der Workspace per E-Mail benachrichtigt, und der Grund ist am Endpunkt selbst nachzulesen. Ein Endpunkt, der mit 410 Gone antwortet, wird auf der Stelle deaktiviert.
- Ein Endpunkt, der 100-mal in Folge fehlschlägt, wird abgeschaltet, statt ewig weiter angewählt zu werden, und alle mit Webhook-Zugriff werden per E-Mail benachrichtigt: welcher es ist, was der letzte Versuch gemeldet hat und dass während des Fehlschlagens nichts in die Warteschlange gelegt wurde. Der Zähler ist FORTLAUFEND, und jeder zugestellte Versuch setzt ihn zurück; ein schlechter Nachmittag im vergangenen März kann sich also nicht zu einem heute deaktivierten Endpunkt aufsummieren. Ihn wieder einzuschalten löscht den Zähler gleich mit. Die Konsole unterscheidet die beiden Zustände, statt einen einzigen Umschalter zu zeigen: Ein Endpunkt, den Sie abgeschaltet haben, sieht anders aus als einer, den wir abgeschaltet haben.
- Endpunkte zu verwalten ist eine Aufgabe mit zwei Eingängen. Über die API sind das POST /webhooks, das Patch, das Delete, rotate-secret, test und das Auslieferungsprotokoll, mit je einer Methode im SDK; in der App ist es Einstellungen → Webhooks, gegen dieselbe Registrierung und nicht gegen eine zweite. Das Lesen ist an webhooks:read gebunden, sodass jeder, der eine Integration baut, die Endpunkte und ihre Auslieferungshistorie sehen kann (welcher gefeuert hat, was der Empfänger geantwortet hat, wie lange es gedauert hat), ohne Eigentümer zu sein. Registrieren, Bearbeiten, Testen, Rotieren und Löschen brauchen webhooks:write UND das Eigentum am Postfach, auf beiden Oberflächen, und diese zweite Hälfte ist Absicht: Ein Endpunkt hat keine Adressachse, er empfängt also jede Adresse, die der Workspace hält, samt Betreffzeilen und Empfängern, und keine Berechtigung bedeutet „darf all das zugeschickt bekommen“. Eine Rolle, die Integrationen baut und die Mail nicht liest, steuert ihn stattdessen mit einem Workspace-Schlüssel.