Zur Dokumentation springen
CLI

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.

NamespaceAuchLesen brauchtÄnderungen brauchen
templatestemplatetemplates:readtemplates:write, und für send zusätzlich emails:send
rulesrulerules:read, einschließlich testrules:write
webhookswebhookwebhooks:readwebhooks: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.

Hilfe
openemail templates --helpopenemail rules create --helpopenemail webhooks replay-delivery --help --json

Vorlagen

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.

BefehlWas es tut
openemail templates listVorlagen 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-startersDie eingebauten Startdesigns auflisten
openemail templates get-starter <slug>Ein Startdesign vollständig lesen, mit seinem Blockbaum und einer gerenderten Vorschau
openemail templates list-fontsDie Webfonts auflisten, die eine Vorlage laden darf
openemail templates renderEinen 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. publish macht sie wieder aktiv.
  • Ein Workspace fasst höchstens 200 Vorlagen, archivierte eingeschlossen, Löschen ist also der einzige Weg, Platz zu schaffen.
  • delete wird mit template_in_use abgelehnt, 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_.

BefehlWas es tut
openemail rules listRegeln 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-runsWas 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, hour und weekday.
  • Operatoren: matches, contains, equals, starts_with, ends_with, gt und lt. gt und lt funktionieren nur bei den Zahlenfeldern, und has_attachment und spam nehmen nur equals mit true oder false.
  • Aktionstypen: label, remove_label, archive, mark_read, star, spam, trash, forward, reply, block_sender und reject. label und remove_label nehmen eine Label-ID wie USER_RECEIPTS, forward nimmt eine Adresse und reply eine Vorlagen-ID oder einen Slug.
  • from_domain trifft auch Subdomains, und hour und weekday werden in UTC gelesen, mit 0 für Sonntag.
  • Eine Regel mit einer reject-Aktion muss auch envelope_from prüfen, sonst wird sie mit reject_needs_envelope abgelehnt.

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_.

BefehlWas es tut
openemail webhooks listDie 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-deliveriesZustellversuche ü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-activityDas 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> --enabled holt ihn zurück.
  • Mit einer Browser-Anmeldung kann nur der Eigentümer des Workspace eine Zustellung mit get-delivery lesen. Alle anderen bekommen owner_only und Exit-Code 4.

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.

CI
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-shipped

Aus 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.

Terminal
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-run

Eine 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.

conditions.json
[  { "field": "from_domain", "op": "equals", "value": "stripe.com" },  { "field": "has_attachment", "op": "equals", "value": "true" }]
actions.json
[  { "type": "label", "value": "USER_RECEIPTS" },  { "type": "archive" }]
Terminal
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" --enabled

Lesen 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.

Terminal
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.

Terminal
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.json

Legen 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.

Terminal
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
  • --since und --until nehmen einen ISO-8601-Zeitpunkt.
  • Eine gescheiterte Zeile, deren nextAttemptAt eine Zeit enthält, hat noch einen automatischen Wiederholungsversuch vor sich.
  • replayRefusal ist null, wenn eine erneute Zustellung hinausginge, und nennt andernfalls, warum sie abgelehnt würde, etwa webhook_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 --json oder --no-input, in CI oder ohne Terminal, kann niemand den Code eingeben, daher bricht der Befehl mit Exit-Code 4 ab und ändert nichts. Führen Sie zuerst openemail verify aus, dann braucht das Profil 60 Minuten lang keinen Code.
  • --yes bestä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.

Terminal
$ 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-runs und jeder webhooks list…-Befehl lesen jeweils eine Seite, 25 Zeilen, sofern --limit nicht bis zu 100 verlangt. Ein Terminal zeigt den --cursor, den Sie für die nächste Seite übergeben.
  • --all liest jede Seite, --max <n> hört nach so vielen Zeilen auf, und --ndjson gibt ein JSON-Objekt pro Zeile aus. Mit --json gibt 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_cursor abgelehnt, mit Exit-Code 7.
  • templates list-sends blättert stattdessen nach Nummer, mit --page und --page-size, meldet total und hat kein --all. Seitennummern verschieben sich, während Mail hinausgeht, grenzen Sie den Zeitraum also mit --days oder --minutes ein, statt tief zu blättern.
  • templates list-starters und templates list-fonts geben den ganzen Katalog auf einmal zurück, und rules reorder gibt jede Regel als einfache Liste in ihrer neuen Reihenfolge zurück.
  • Ein Postfach fasst höchstens 100 Regeln, daher gibt rules list --limit 100 immer jede Regel auf einer Seite zurück.

Flags, die einen zweiten Blick wert sind

  • --template-version ist das Body-Feld version, umbenannt, weil --version die CLI-Version ausgibt. Das Argument <version> von get-version, restore-version und delete-version ist eine Versionsnummer, keine tplv_-ID.
  • --conditions, --actions, --document, --slots, --props und die anderen JSON-Flags nehmen JSON inline, aus einer Datei mit @path oder von stdin mit -. --data nimmt den ganzen Body auf dieselbe Weise, und jedes Flag, das Sie zusätzlich übergeben, überschreibt seinen Schlüssel.
  • --html nimmt das Markup selbst, keine Datei, --html @page.html sendet also den Text @page.html. Übergeben Sie --html "$(cat page.html)" oder setzen Sie html in die Datei, die Sie --data geben.
  • rules update --conditions und --actions ersetzen die ganze Liste, ebenso webhooks update --event-types, --address-allowlist und --domain-allowlist. Lesen Sie den aktuellen Wert, ändern Sie ihn und senden Sie ihn vollständig.
  • Ein leeres --event-types ist 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-version bei templates update, replace-content und restore-version nimmt die Head-Version, die Sie gelesen haben. Hat jemand anderes die Head-Version inzwischen verschoben, bricht der Befehl mit Exit-Code 6 und version_conflict ab und schreibt nichts.
  • rules update <id> --no-enabled schaltet eine Regel aus und behält ihren Platz in der Reihenfolge, so pausieren Sie eine Regel, ohne sie zu löschen.

Der Posteingang,
nach eigenen Regeln.

E-Mail-Infrastruktur für Unternehmen, KI, Agenten und persönliche E-Mail. Gebaut für Skalierung, Privatsphäre und Kontrolle. Alles, was E-Mail vom ersten Tag an hätte haben sollen.

OpenEmail

E-Mail-Infrastruktur für Unternehmen, KI, Agenten und persönliche E-Mail. Gebaut für Skalierung, Privatsphäre und Kontrolle. Alles, was E-Mail vom ersten Tag an hätte haben sollen.

© 2026 OpenEmail. Alle Rechte vorbehalten.