ドキュメント本文へスキップ
API

ルールを作成する

一方に条件、もう一方にアクションを書きます。指定しない限り有効になります。

POSTapi.openemail.uk/rules

実際の呼び出しを、ご自身のキーで自分のワークスペースに対して実行します。

POST /rules

一方に条件、もう一方にアクションを書きます。指定しない限り有効になります。

rules:write が必要です。201 を返します。position は受け付けません。新しいルールは一覧の末尾に追加され、移動するには POST /rules/reorder を使います。

curl
curl -X POST "$OE/rules" -H "$AUTH" -H "Content-Type: application/json" \  -d '{    "name": "Receipts to their own label",    "match": "all",    "conditions": [      { "field": "from_domain", "op": "matches", "value": "*.stripe.com" },      { "field": "subject", "op": "contains", "value": "receipt" }    ],    "actions": [      { "type": "label", "value": "USER_RECEIPTS" },      { "type": "archive" }    ],    "stopProcessing": true  }'
レスポンス
{  "object": "rule",  "id": "rul_7f3a1c94e05d3862c1f0a44b",  "name": "Receipts to their own label",  "description": null,  "enabled": true,  "position": 3,  "match": "all",  "conditions": [    { "field": "from_domain", "op": "matches", "value": "*.stripe.com", "negate": false },    { "field": "subject", "op": "contains", "value": "receipt", "negate": false }  ],  "actions": [    { "type": "label", "value": "USER_RECEIPTS" },    { "type": "archive" }  ],  "stopProcessing": true,  "lastMatchedAt": null,  "matchCount": 0,  "createdAt": "2026-08-30T10:41:02.000Z",  "updatedAt": "2026-08-30T10:41:02.000Z"}

ここで作成したルールは有効な状態で、次に届くメッセージから作用します。人が意図して行った呼び出しにはそれが正しい既定です。これは MCP の createRule ツールとは逆で、そちらは同じルールを無効な状態で書き込みます。メールをアーカイブすると判断したモデルが、人がルールを読み返す前にアーカイブを始めるべきではないからです。

同じ接続上で name が重複すると rule_name_taken、409 になります。名前は、実行ログや設定画面でルールを見分ける手がかりなので、「Newsletters」という名前のルールが 2 つあるレポートは誰にも読めません。

101 個目のルールは rule_limit_reached、422 です。この上限は会計上の境界ではなくループに入ったスクリプトへの備えであり、ロックはされていません。99 個の時点で同時に走った 2 つの作成は、どちらも成功しえます。

条件で何を問えるか

条件は { field, op, value } で、読み取るヘッダーを指定する任意の header と、任意の negate を伴います。value はワイヤー上では常に string です。数値フィールドは Number(value) の後に数値として比較され、2 つの boolean フィールドはリテラル文字列 "true""false" を取ります。1 つのフィールドに 1 つの型なら OpenAPI ジェネレーターが記述できるスキーマになりますが、3 つの型の union はそうではないからです。

フィールド読み取る対象演算子
`from`From: ヘッダー。ブロックリストと同じやり方で正規化されます。text
`from_domain`From: のドメインと、その親ドメイン。2 ラベルまで遡ります。mail.corp.example.com からのメッセージは corp.example.com にも example.com にも一致し、com には何も一致しません。text
`envelope_from`SMTP の MAIL FROM。メーリングリストでは必ず from と異なり、reject を書いてよい唯一の識別子です。text
`to`, `cc`, `bcc`そのヘッダー内のいずれかのアドレス。text
`recipient`toccbcc のいずれかにあるアドレス。3 つをまとめた省略形です。text
`reply_to`Reply-To ヘッダー。text
`delivered_to`このコピーが配信された正規のアドレス。プラスタグを除去して小文字化したもので、catch-all のエイリアスはこれで一致します。text
`subject`届いたままの件名。text
`body`テキストパート、または HTML をテキストに落としたもの。上限があるので、20 MB の本文が全部スキャンされることはありません。text
`header`任意のヘッダー。条件自身の header フィールドで指定します。そこでは必須で、比較前に小文字化されます。text
`list_id`List-Id ヘッダー。メーリングリストが自身を示す識別子です。text
`attachment_name`いずれかの添付ファイルのファイル名。text
`attachment_type`いずれかの添付ファイルの MIME タイプ。例: application/pdftext
`has_attachment`そもそも添付があるかどうか。equals "true" / "false"
`spam`ルールが走る前に配信パスが下したスパム判定。equals "true" / "false"
`attachment_size`添付ファイルのサイズ(バイト)。いずれか 1 つの添付が条件を満たせば一致します。gt, lt, equals
`message_size`ワイヤー上のメッセージ全体のサイズ(バイト)。gt, lt, equals
`hour`到着した時刻の時。0–23、UTC。gt, lt, equals
`weekday`到着した曜日。0–6、日曜が 0、UTC。gt, lt, equals
演算子動作
`matches`グロブだけです。* は任意の長さの文字列、? は 1 文字にあたります。正規表現はありません。API クライアントから来たパターンは配信パス上で動くので、そこで壊滅的なバックトラックを起こすパターンは、受信できなくなるメールボックスを意味します。
`contains`部分一致。大文字小文字を区別しません。
`equals`値全体の一致。大文字小文字を区別しません。数値フィールドでは数値としての等価比較です。
`starts_with`前方一致。大文字小文字を区別しません。
`ends_with`後方一致。大文字小文字を区別しません。
`gt`, `lt`数値比較。4 つの数値フィールドでのみ使えます。テキストフィールドに gt を使っても一致することはありません。

matches のパターンには、それ自体に少なくとも 2 文字の英数字が必要です。ブロックリストと同じ基準です。裸の * は、受け入れたうえで以後届くすべてのメッセージに静かに一致するのではなく、書き込み時に拒否されます。それはルールではなく障害だからです。

エンジンが答えられない条件(新しいクライアントから来た未知のフィールド、コンパイルできないパターン、contains "")は、false ではなく「そもそも問われなかった質問」として扱われ、negate でも反転しません。この区別は重要です。壊れた条件を false として扱ったうえで否定すると、そのルールはメールボックス内のすべてのメッセージで発火してしまいます。equals "" は尊重されます。「件名が空である」は実際に意味のある問いだからです。

ルールで何ができるか

アクション`value`起きること
`label`ラベル idラベルを追加します。USER_… の id は GET /labels から取得します。
`remove_label`ラベル idラベルを外します。同じラベルを両方に指定した場合は、どちらが後に走ったかに委ねるのではなく、メッセージを振り分ける前に解決します。
`archive`なし受信トレイの外に振り分けます。
`mark_read`なしUNREAD を外します。
`star`なしSTARRED を付けます。
`spam`なしスパムに振り分けます。
`trash`なしゴミ箱に振り分け、ゴミ箱のメッセージが保持しないラベルを外します。
`forward`アドレスコピーを転送します。使う前に下の注記を読んでください。
`reply`テンプレートの id または slug公開済みのテンプレートで自動返信します。下のループガードの対象です。
`block_sender`なし送信者をブロックリストに追加し、次のメッセージは入口で拒否されます。
`reject`なしSMTP の時点で 550 5.7.1 Message refused by the recipient としてメッセージを拒否します。エンベロープのみが対象です。下の注記を参照してください。

reject は、同じルールに envelope_from の条件が少なくとも 1 つない限り書き込み時に拒否されます。reject_needs_envelope、422 です。550 はメッセージを渡してきた相手への応答であり、メーリングリストではそれは「リスト」です。リストはその拒否を購読者のバウンスと解釈し、1 人の投稿を止めたかっただけの読者を、そのリストから退会させてしまいます。条件を書いていても、ヘッダー上の識別子だけで一致した場合はスパムへの振り分けに格下げされます。拒否を正直に向けられる唯一の識別子はエンベロープだからです。

ルールによる forward は送信パスを通るので、メッセージが再構築されます。元の DKIM 署名は残らず、特殊なパート、珍しいヘッダー、送信サイズの上限を超える部分も残りません。添付付きの 25 MB のメッセージはその上限を超えます。これは届いたメッセージそのものではなく、届いたもののコピーです。宛先アドレスはルールを書く時点で検証されるので、未確認の宛先は、10 通に 1 通を静かに落とすルールではなく、呼び出し時の 422 になります。

reply は機械には返信しません。メッセージが Auto-Submittedno 以外)、Precedence: bulk|list|junkList-IdList-UnsubscribeX-AutoreplyX-Autorespond を持つ場合、エンベロープの送信者が空の場合(すべてのバウンスが取る形です)、そしてヘッダーをまったく読めなかった場合には抑制されます。さらに、1 人の送信者が特定のメールボックスから受け取れる自動返信は 24 時間に最大 1 通です。返信ルールを持つ 2 つのメールボックスにガードがなければ、誰かが気付くまで互いにメールを送り続けます。