Vorlagen, Regeln und Webhooks
Jeder `templates`-, `rules`- und `webhooks`-Befehl: gespeicherte Bodys, die Sie per Slug senden, Regeln, die eingehende Mail ablegen, und signierte Ereignisse für Ihren eigenen Server.
Drei Namespaces
Mit diesen drei Namespaces läuft ein Postfach, ohne dass jemand zusieht. templates speichert Bodys, die Sie oft senden, rules legt Mail beim Eintreffen ab, und webhooks sagt Ihrem eigenen Server, was passiert ist. Jeder Befehl ist eine SDK-Methode unter ihrem Namen in Kebab-Case, webhooks.rotateSecret ist also openemail webhooks rotate-secret, und er liest Argumente und Flags wie jeder andere Ressourcenbefehl.
| Namespace | Auch | Lesen braucht | Änderungen brauchen |
|---|---|---|---|
| templates | template | templates:read | templates:write, und für send zusätzlich emails:send |
| rules | rule | rules:read, einschließlich test | rules:write |
| webhooks | webhook | webhooks:read | webhooks:write, einschließlich test und replay-delivery |
Diese Seite listet jeden Befehl und das, was Sie wissen sollten, bevor Sie ihn in ein Skript packen. Für jedes Argument und Flag, mit seinem Typ, den nötigen Scopes, seinem Endpunkt und dem Rückgabewert, führen Sie openemail <namespace> <verb> --help aus. Fügen Sie --json hinzu, um dieselbe Seite als JSON zu erhalten.
openemail templates --helpopenemail rules create --helpopenemail webhooks replay-delivery --help --jsonVorlagen
Bodys, die einmal gespeichert und oft gesendet werden, mit Versionen, Vorschauen und typisierten Props. Jeder Befehl, der <id-or-slug> nimmt, akzeptiert die tpl_-ID oder den Slug. Der Slug ändert sich nie, wenn die Vorlage umbenannt wird, legen Sie in Skripten also den Slug fest.
| Befehl | Was es tut |
|---|---|
| openemail templates list | Vorlagen auflisten, zuletzt aktualisierte zuerst. --status behält Entwürfe, aktive oder archivierte, --search trifft Namen, Slugs und Betreffzeilen, und --sort wählt die Reihenfolge |
| openemail templates get <id-or-slug> | Eine Vorlage mit ihrer vollständigen Head-Version lesen, einschließlich Body |
| openemail templates create --name <value> | Eine Vorlage und ihre erste Version anlegen. Sie bleibt ein Entwurf, außer Sie übergeben --publish, und --starter füllt sie mit einem Startdesign |
| openemail templates update <id-or-slug> | Name, Slug, Beschreibung oder Status bearbeiten, oder den Entwurfs-Body. Versände behalten die veröffentlichte Version, bis Sie veröffentlichen |
| openemail templates duplicate <id-or-slug> | Die Head-Version in eine neue Vorlage kopieren, die als Entwurf beginnt |
| openemail templates replace-content <id-or-slug> | Den Body gegen den eines Startdesigns (--starter) oder einer anderen Vorlage (--from-template-id) tauschen. Fragt nach einer Bestätigung |
| openemail templates delete <id-or-slug> | Eine Vorlage und jede Version löschen. Fragt nach einer Bestätigung |
| openemail templates list-versions <id-or-slug> | Die Versionen auflisten, neueste zuerst, ohne ihre Bodys |
| openemail templates get-version <id-or-slug> <version> | Eine Version mit ihrem Body lesen, ohne den Entwurf anzufassen |
| openemail templates publish <id-or-slug> | Den Entwurf veröffentlichen, sodass Versände ihn verwenden. Eine Head-Version zu veröffentlichen, die schon live ist, ändert nichts |
| openemail templates restore-version <id-or-slug> <version> | Den Body einer älteren Version als Entwurf zurückholen. Fragt nach einer Bestätigung |
| openemail templates delete-version <id-or-slug> <version> | Eine Version löschen. Die Live-Version, die Head-Version und die einzige Version werden abgelehnt. Fragt nach einer Bestätigung |
| openemail templates list-starters | Die eingebauten Startdesigns auflisten |
| openemail templates get-starter <slug> | Ein Startdesign vollständig lesen, mit seinem Blockbaum und einer gerenderten Vorschau |
| openemail templates list-fonts | Die Webfonts auflisten, die eine Vorlage laden darf |
| openemail templates render | Einen Body rendern, der nirgends gespeichert ist, aus --html oder --document |
| openemail templates preview <id-or-slug> | Eine gespeicherte Vorlage mit --props und --slots rendern, Entwürfe eingeschlossen, ohne sie zu senden |
| openemail templates get-analytics <id-or-slug> | Versände, Öffnungen und Klicks in einem Zeitraum, nach Tag, nach Quelle und nach Version |
| openemail templates list-sends <id-or-slug> | Die einzelnen Nachrichten, die die Vorlage gesendet hat, neueste zuerst, seitenweise |
| openemail templates send <id-or-slug> --from <value> --to <a,b> | Eine E-Mail senden, gerendert aus der veröffentlichten Version oder aus der, die --template-version festlegt |
Eine Vorlage hat eine Head-Version, die ein Entwurf ist, solange sie unveröffentlichte Änderungen hat, und eine veröffentlichte Version, die ein Versand ohne --template-version verwendet. create ohne --publish, eine Body-Änderung mit update, replace-content und restore-version schreiben alle den Entwurf, Empfänger sehen also nichts Neues bis publish.
- Eine archivierte Vorlage verweigert den Versand mit
template_archived.publishmacht sie wieder aktiv. - Ein Workspace fasst höchstens 200 Vorlagen, archivierte eingeschlossen, Löschen ist also der einzige Weg, Platz zu schaffen.
deletewird mittemplate_in_useabgelehnt, solange ein geplanter Broadcast oder einer in der Warteschlange die Vorlage noch nennt.
Regeln
Bedingungen und Aktionen, die auf eingehende Mail angewendet werden, in der Reihenfolge, die rules list zeigt. Eine Regel wirkt nur auf Mail, die eintrifft, während sie aktiviert ist. Kein Befehl wendet eine Regel auf Mail an, die schon im Postfach ist, und mit rules test sehen Sie, was sie erfassen würde. Regel-IDs beginnen mit rul_.
| Befehl | Was es tut |
|---|---|
| openemail rules list | Regeln in der Reihenfolge auflisten, in der sie laufen. --enabled oder --no-enabled behält eine Art |
| openemail rules get <id> | Eine Regel lesen, mit matchCount und lastMatchedAt |
| openemail rules create --name <value> --conditions <json|@file|-> --actions <json|@file|-> | Eine Regel am Ende der Reihenfolge anlegen. Sie ist aktiviert, außer Sie übergeben --no-enabled |
| openemail rules update <id> | Eine Regel ändern. --conditions und --actions ersetzen die ganze Liste, und --position verschiebt nur diese Regel |
| openemail rules delete <id> | Eine Regel löschen. Was sie schon getan hat, bleibt in list-runs. Fragt nach einer Bestätigung |
| openemail rules reorder <rule-ids...> | Die Reihenfolge aller Regeln auf einmal festlegen, wobei jede Regel genau einmal genannt wird |
| openemail rules test <id> | Eine Regel probeweise gegen Mail laufen lassen, die schon im Postfach ist. Sie ändert nichts und funktioniert auch mit einer deaktivierten Regel |
| openemail rules list-runs | Was Regeln tatsächlich mit eingehender Mail getan haben, neueste zuerst. --rule-id und --thread-id grenzen es ein |
--conditions ist eine Liste von { field, op, value }-Objekten, verknüpft durch --match all oder --match any, wobei value immer ein String ist und negate: true eine Bedingung umkehrt. --actions ist eine Liste von { type, value }-Objekten, die der Reihe nach angewendet werden. Eine Regel nimmt 1 bis 20 Bedingungen und 1 bis 10 Aktionen, und ein Postfach fasst höchstens 100 Regeln.
- Bedingungsfelder:
from,from_domain,envelope_from,to,cc,bcc,recipient,reply_to,delivered_to,subject,body,header,list_id,attachment_name,attachment_type,has_attachment,attachment_size,message_size,spam,hourundweekday. - Operatoren:
matches,contains,equals,starts_with,ends_with,gtundlt.gtundltfunktionieren nur bei den Zahlenfeldern, undhas_attachmentundspamnehmen nurequalsmittrueoderfalse. - Aktionstypen:
label,remove_label,archive,mark_read,star,spam,trash,forward,reply,block_senderundreject.labelundremove_labelnehmen eine Label-ID wieUSER_RECEIPTS,forwardnimmt eine Adresse undreplyeine Vorlagen-ID oder einen Slug. from_domaintrifft auch Subdomains, undhourundweekdaywerden in UTC gelesen, mit0für Sonntag.- Eine Regel mit einer
reject-Aktion muss auchenvelope_fromprüfen, sonst wird sie mitreject_needs_envelopeabgelehnt.
Webhooks
Endpunkte auf Ihrem eigenen Server, die signierte Postfach-Ereignisse empfangen, mit ihren Signaturgeheimnissen, ihrem Zustellprotokoll und einem Audit-Log jeder Änderung. Endpunkt-IDs beginnen mit whe_ und Zustellungs-IDs mit whd_.
| Befehl | Was es tut |
|---|---|
| openemail webhooks list | Die Endpunkte im Workspace auflisten, neueste zuerst, mit ihrem Zustand |
| openemail webhooks get <id> | Einen Endpunkt lesen. Das Signaturgeheimnis ist nie Teil eines Lesezugriffs |
| openemail webhooks create --url <value> | Einen HTTPS-Endpunkt registrieren. Gibt das Signaturgeheimnis aus, das einzige Mal, dass Sie es sehen |
| openemail webhooks update <id> | URL, Ereignisse, Allowlists oder Aktivierung ändern. Jede Liste ersetzt die gespeicherte |
| openemail webhooks delete <id> | Einen Endpunkt und sein Zustellprotokoll löschen. Fragt nach einer Bestätigung |
| openemail webhooks rotate-secret <id> | Ein neues Signaturgeheimnis ausstellen. Das alte funktioniert sofort nicht mehr. Fragt nach einer Bestätigung |
| openemail webhooks test <id> | Ein signiertes synthetisches email.sent-Ereignis senden und melden, wie die Zustellung lief |
| openemail webhooks list-deliveries <id> | Die Zustellversuche eines Endpunkts, neueste zuerst. --status, --since und --until grenzen sie ein |
| openemail webhooks get-delivery <id> <delivery-id> | Ein Versuch vollständig: der gesendete Body, die Antwort Ihres Servers, jeder Versuch des Ereignisses und ob eine erneute Zustellung angenommen würde |
| openemail webhooks replay-delivery <id> <delivery-id> | Ein gespeichertes Ereignis jetzt erneut an den Endpunkt senden |
| openemail webhooks list-workspace-deliveries | Zustellversuche über alle Endpunkte oder die, die --endpoint-ids nennt |
| openemail webhooks list-activity <id> | Das Audit-Log eines Endpunkts: wer ihn angelegt, geändert, getestet, erneut zugestellt oder entfernt hat |
| openemail webhooks list-workspace-activity | Das Audit-Log aller Endpunkte, entfernte eingeschlossen |
Lassen Sie --event-types weg, und ein Endpunkt empfängt die Standardauswahl, die email.*-Ereignisse außer email.replied. email.replied, die domain.*-Ereignisse und die suppression.*-Ereignisse erreichen ihn nur, wenn Sie sie nennen. --address-allowlist und --domain-allowlist beschränken einen Endpunkt auf einige Adressen oder Domains, so wie sie einen API-Schlüssel beschränken.
- Ein Workspace fasst 10 Endpunkte, sofern der Support sein Limit nicht erhöht hat.
- Ein Endpunkt, bei dem 100 Zustellungen in Folge scheitern, wird vom Server abgeschaltet, und
webhooks update <id> --enabledholt ihn zurück. - Mit einer Browser-Anmeldung kann nur der Eigentümer des Workspace eine Zustellung mit
get-deliverylesen. Alle anderen bekommenowner_onlyund Exit-Code4.
Eine Vorlage prüfen und dann veröffentlichen
templates preview rendert genau das, was ein Versand mit denselben Werten erzeugen würde, Entwürfe eingeschlossen, und braucht nur templates:read, daher kann es sogar ein Nur-Lese-Schlüssel ausführen. Es meldet eine fehlende Pflicht-Prop als Warnung, wo send sie ablehnen würde, lassen Sie den Build also bei jeder Warnung scheitern. publish ist bei jedem Deploy sicher, weil das Veröffentlichen einer Head-Version, die schon live ist, nichts ändert.
draft=$(openemail templates get order-shipped --json | jq .latestVersion)openemail templates preview order-shipped --template-version "$draft" \ --props '{"orderId":"AC-4192","customer":"Ada"}' --json | jq -e '.warnings == []'openemail templates publish order-shippedAus einer Vorlage senden
Legen Sie die Version fest, damit eine morgen veröffentlichte Überarbeitung nicht ändert, was dieser Code sendet, und übergeben Sie einen Idempotency-Key, der aus dem Auslöser des Versands abgeleitet ist, damit eine Wiederholung nach einer verlorenen Antwort die erste Nachricht erneut abspielt, statt eine zweite zu senden. --dry-run gibt die Methode, die URL, die Header mit geschwärzten Anmeldedaten und den Body aus, sendet nichts und endet mit Exit-Code 0. Führen Sie es ohne --dry-run erneut aus, um zu senden.
openemail templates send order-shipped \ --from 'Acme <[email protected]>' \ --to [email protected] \ --template-version 5 \ --props '{"orderId":"AC-4192","customer":"Ada"}' \ --idempotency-key order-shipped:AC-4192 \ --dry-runEine Regel testen, bevor sie läuft
Legen Sie die Regel ausgeschaltet an, lassen Sie sie probeweise gegen aktuelle Mail laufen und schalten Sie sie ein, sobald sie erfasst, was Sie meinten. Mit einer Browser-Anmeldung fragen rules create und rules update nach einem Bestätigungscode, den ein Skript nicht eingeben kann, führen Sie also zuerst openemail verify aus. In den nächsten 60 Minuten führt dieses Profil sie ohne Nachfrage aus.
[ { "field": "from_domain", "op": "equals", "value": "stripe.com" }, { "field": "has_attachment", "op": "equals", "value": "true" }][ { "type": "label", "value": "USER_RECEIPTS" }, { "type": "archive" }]openemail verifyrule=$(openemail rules create --name 'Stripe receipts' \ --conditions @conditions.json --actions @actions.json --no-enabled --json | jq -r .id)openemail rules test "$rule" --days 30 --limit 100openemail rules update "$rule" --enabledLesen Sie die Warnungen von rules test vor seinen Treffern. field_unevaluable bedeutet, dass eine Bedingung etwas liest, das gespeicherte Mail nicht mehr enthält, sodass der Test sie nicht beurteilen konnte, und forward_unverified bedeutet, dass ein Weiterleitungsziel nicht hier gehostet ist. wouldApply listet, was die Regel deklariert: Eine Weiterleitung an eine Adresse, die nicht bestätigt hat, scheitert trotzdem, wenn echte Mail eintrifft.
Eine Regel an die erste Stelle setzen und sehen, warum eine Nachricht verschoben wurde
rules reorder nimmt jede Regel des Postfachs genau einmal. Eine ausgelassene oder doppelt genannte Regel wird abgelehnt, und nichts bewegt sich. rules list gibt die IDs in der Reihenfolge zurück, in der sie laufen, setzen Sie also die gewünschte vor die übrigen.
first=rul_4f1c9a2b7d3e8f6a0b5c1d2eopenemail rules reorder "$first" $(openemail rules list --all --ndjson \ | jq -r --arg first "$first" 'select(.id != $first) | .id')openemail rules list-runs --thread-id CAHk7pQ2x9LmZ4 --json | jq '.items[] | {ruleName, actions, failures}'list-runs ist das Protokoll dessen, was wirklich passiert ist. Jede Zeile ist eine Regel, die auf eine Nachricht zutraf, mit den Aktionen, die gewirkt haben, und in failures denen, die das Postfach abgelehnt hat, etwa eine Antwort an einen Absender, der an diesem Tag schon eine bekommen hat. Jede Zeile behält den Namen, den die Regel damals hatte, sodass --rule-id auch für eine inzwischen gelöschte Regel funktioniert.
Einen Webhook registrieren und beweisen, dass er funktioniert
webhooks create zeigt das Signaturgeheimnis einmal, und kein späterer Befehl zeigt es wieder. Mit --json steht es im JSON auf stdout, während die Erinnerung, es zu speichern, auf stderr geht, sodass sich die Ausgabe weiterhin parsen lässt. webhooks test sendet ein signiertes synthetisches email.sent-Ereignis, egal was der Endpunkt abonniert, und es wird keine Mail gesendet.
openemail verifyopenemail webhooks create --url https://hooks.acme.com/openemail \ --event-types email.received,email.bounced,email.complained \ --description 'Support desk sync' --json > endpoint.jsonjq -r .secret endpoint.jsonopenemail webhooks test "$(jq -r .id endpoint.json)" --json | jq .deliveryrm endpoint.jsonLegen Sie das Geheimnis in Ihren Secret Store, bevor Sie die Datei löschen. test endet mit Exit-Code 0, auch wenn Ihr Server scheitert, lesen Sie also delivery.status: delivered für eine 2xx-Antwort und failed für alles andere, eine Weiterleitung eingeschlossen, da Weiterleitungen nie gefolgt wird. Ein responseCode von null bedeutet, dass gar keine Antwort ankam.
Gescheiterte Zustellungen finden und eine erneut senden
Listen Sie nach einem Ausfall auf Ihrer Seite auf, was über alle Endpunkte gescheitert ist, prüfen Sie, dass eine erneute Zustellung angenommen würde, und senden Sie das Ereignis erneut. Eine erneute Zustellung trägt dieselbe Ereignis-ID, sodass ein Empfänger, der bereits verarbeitete IDs verwirft, sie als das Ereignis behandelt, das er kennt.
openemail webhooks list-workspace-deliveries --status failed --since 2026-09-26T00:00:00Z --all --ndjson \ | jq -r '[.endpointId, .id, .eventType, (.responseCode // "no answer")] | @tsv'openemail webhooks get-delivery whe_3f9c2a7b1e4d8f60a5c7b92d whd_8c1e4a7f2b9d3e6a0c5f1b28 --json | jq .replayRefusalopenemail webhooks replay-delivery whe_3f9c2a7b1e4d8f60a5c7b92d whd_8c1e4a7f2b9d3e6a0c5f1b28--sinceund--untilnehmen einen ISO-8601-Zeitpunkt.- Eine gescheiterte Zeile, deren
nextAttemptAteine Zeit enthält, hat noch einen automatischen Wiederholungsversuch vor sich. replayRefusalistnull, wenn eine erneute Zustellung hinausginge, und nennt andernfalls, warum sie abgelehnt würde, etwawebhook_disabled, solange der Endpunkt abgeschaltet ist.- Erneute Zustellungen gehen ein Ereignis nach dem anderen. Kein Befehl sendet jede gescheiterte Zustellung erneut.
Bestätigungscodes
Mit einer Browser-Anmeldung fragen vier dieser Befehle nach einem Bestätigungscode, bevor sie etwas ändern, wie die Web-App: rules create, rules update, webhooks create und webhooks update. Ein API-Schlüssel wird nie gefragt. Jeder andere Befehl auf dieser Seite läuft ohne Code, Löschbefehle und webhooks rotate-secret eingeschlossen.
- In einem Terminal schickt Ihnen die CLI einen sechsstelligen Code per E-Mail oder fragt nach einem aus Ihrer Authenticator-App, wenn die Zwei-Faktor-Anmeldung aktiv ist, und führt dann den Befehl einmal aus.
- Unbeaufsichtigt, mit
--jsonoder--no-input, in CI oder ohne Terminal, kann niemand den Code eingeben, daher bricht der Befehl mit Exit-Code4ab und ändert nichts. Führen Sie zuerstopenemail verifyaus, dann braucht das Profil 60 Minuten lang keinen Code. --yesbestätigt ein Löschen, überspringt aber nie einen Code.
Bestätigungen und Probeläufe
Sieben Befehle hier entfernen oder überschreiben etwas, daher bitten sie zuerst um Bestätigung: templates delete, templates delete-version, templates replace-content, templates restore-version, rules delete, webhooks delete und webhooks rotate-secret. Unbeaufsichtigt bricht jeder davon mit Exit-Code 2 ab, außer Sie übergeben --yes.
$ openemail webhooks delete whe_3f9c2a7b1e4d8f60a5c7b92d --no-input✗ Refusing to run unattended. Pass --yes to confirm.$ openemail webhooks delete whe_3f9c2a7b1e4d8f60a5c7b92d --yes--dry-run gibt die erste Anfrage aus, die etwas ändern würde, und endet mit Exit-Code 0, ohne sie zu senden oder um Bestätigung zu bitten. Mit --json gibt es ein einziges { dryRun, request }-Dokument aus. rules test, templates render und templates preview ändern nichts, sind aber POST-Anfragen, daher gibt ein Probelauf sie aus, statt sie auszuführen.
Blättern
templates list,templates list-versions,rules list,rules list-runsund jederwebhooks list…-Befehl lesen jeweils eine Seite, 25 Zeilen, sofern--limitnicht bis zu 100 verlangt. Ein Terminal zeigt den--cursor, den Sie für die nächste Seite übergeben.--allliest jede Seite,--max <n>hört nach so vielen Zeilen auf, und--ndjsongibt ein JSON-Objekt pro Zeile aus. Mit--jsongibt eine Liste ein einziges{ items, hasMore, nextCursor }-Dokument aus, auch mit--all.- Geben Sie einen Cursor mit denselben Filtern und derselben Sortierung zurück, mit denen er kam. Alles andere wird als
invalid_cursorabgelehnt, mit Exit-Code7. templates list-sendsblättert stattdessen nach Nummer, mit--pageund--page-size, meldettotalund hat kein--all. Seitennummern verschieben sich, während Mail hinausgeht, grenzen Sie den Zeitraum also mit--daysoder--minutesein, statt tief zu blättern.templates list-startersundtemplates list-fontsgeben den ganzen Katalog auf einmal zurück, undrules reordergibt jede Regel als einfache Liste in ihrer neuen Reihenfolge zurück.- Ein Postfach fasst höchstens 100 Regeln, daher gibt
rules list --limit 100immer jede Regel auf einer Seite zurück.
Flags, die einen zweiten Blick wert sind
--template-versionist das Body-Feldversion, umbenannt, weil--versiondie CLI-Version ausgibt. Das Argument<version>vonget-version,restore-versionunddelete-versionist eine Versionsnummer, keinetplv_-ID.--conditions,--actions,--document,--slots,--propsund die anderen JSON-Flags nehmen JSON inline, aus einer Datei mit@pathoder von stdin mit-.--datanimmt den ganzen Body auf dieselbe Weise, und jedes Flag, das Sie zusätzlich übergeben, überschreibt seinen Schlüssel.--htmlnimmt das Markup selbst, keine Datei,--html @page.htmlsendet also den Text@page.html. Übergeben Sie--html "$(cat page.html)"oder setzen Siehtmlin die Datei, die Sie--datageben.rules update --conditionsund--actionsersetzen die ganze Liste, ebensowebhooks update --event-types,--address-allowlistund--domain-allowlist. Lesen Sie den aktuellen Wert, ändern Sie ihn und senden Sie ihn vollständig.- Ein leeres
--event-typesist ein Nutzungsfehler. Um einen Endpunkt auf die Standardauswahl zurückzusetzen, senden Sie--data '{"eventTypes":[]}', und um seine Zustellungen zu stoppen, übergeben Sie--no-enabled. --expected-versionbeitemplates update,replace-contentundrestore-versionnimmt die Head-Version, die Sie gelesen haben. Hat jemand anderes die Head-Version inzwischen verschoben, bricht der Befehl mit Exit-Code6undversion_conflictab und schreibt nichts.rules update <id> --no-enabledschaltet eine Regel aus und behält ihren Platz in der Reihenfolge, so pausieren Sie eine Regel, ohne sie zu löschen.