メールの送信とトラッキング
`emails` コマンドでメールを送信、一括送信、翻訳、予約、取り消しし、`tracking` で配信、開封、クリックを追跡します。
概要
emails 名前空間は送信 API をコマンドにしたもので、SDK の openemail.emails の各メソッドに 1 つずつ対応します。それぞれが 1 つのエンドポイントを呼び出し、返された内容を表示します。tracking 名前空間は、送信したメールの開封とクリックを読み取ります。openemail emails の代わりに openemail email も使えます。
ここにあるすべてのコマンドには、ブラウザまたは API キーによるサインインと、2 つのスコープのどちらかが必要です。送信、翻訳、取り消し、再スケジュールには emails:send、読み取るだけのものにはすべて emails:read です。
どちらの送信コマンドを使うか
openemail send は「メール」のページで説明している手書きのコマンドで、emails send を通して送信します。ターミナルの前にいる人向けに作られており、--from を省略すると送信元アドレスを選び、本文をファイル、stdin、またはエディタから読み取り、パスを指定してファイルを添付し、何かを送る前に確認用の概要を表示します。openemail emails send はリクエストの本文をフィールドごとに 1 つのフラグとして受け取り、何も尋ねないので、何を送るかを正確に把握しているスクリプトに向いています。
| send | emails send |
|---|---|
| --from <address> | --to と同様に、--data に含まれていない限り必須です。send では省略でき、アドレスを選んでくれます |
| -f, --body-file <path> | 本文用のファイルフラグはありません。--html "$(cat body.html)" を渡すか、リクエスト全体を --data @email.json で渡します |
| -a, --attach <path> | --attachments。ファイルの JSON 配列で、それぞれに filename と base64 の content、または「ファイル」にすでにあるファイルの fileId を指定します |
| --at <when> | --scheduled-at <when>。ISO 8601 の日時、または PT1H や P2D のような期間です。send は 10m、2h、1d のような短い遅延も受け付けます |
| --undo <seconds> | --cancellable-for-seconds <n>。0 から 900 まで |
| --translate <language> | --translate '{"to":"de"}'。from、includeOriginal、subject も指定できます |
| --template <id> --props <json> | --template '{"id":"welcome","props":{"name":"Ada"}}'。version を固定することもできます |
| --draft <id> | --draft-id <id> |
| --thread <id> | --thread-id <id> |
| --tag <key=value> | --tags <key=value> を繰り返し指定するか、JSON オブジェクトで指定 |
emails send だけにあるフラグは次のとおりです。1 回の送信で開封やクリックの追跡をオフにする --tracking、--signature、カスタムヘッダー用の --headers、ファイルを添付するかリンクにするかを選ぶ --attachment-delivery、そして本文全体を JSON で渡す --data です。JSON はインラインでも、@path でファイルからでも、- で stdin からでも渡せます。
2 つは終わり方が異なります。send はメールが failed で返ると終了コード 1 で終了します。emails send は API が応答すれば常に終了コード 0 で終了するので、出力の status を確認してください。
emails のすべてのコマンド
send、send-batch、translate、cancel、reschedule には emails:send が、list、get、list-events、get-tracking には emails:read が必要です。メールの ID は、送信が返すとおり、msg_ の後に 16 進数 24 文字が続く形式です。
| コマンド | 機能 |
|---|---|
| openemail emails send --from <value> --to <a,b> | 1 通のメールを今すぐ送るか、--cancellable-for-seconds で取り消し猶予の間保留するか、--scheduled-at で予約します。本文は --html、--text またはその両方、保存済みの --template、または保存済みの --draft-id です |
| openemail emails send-batch <emails> | 互いに独立した最大 100 通のメールを 1 回のリクエストで送ります。JSON 配列をファイル、インライン、または - で stdin から渡します。各項目は emails send の本文と同じ形で、それぞれ個別に成功または失敗します |
| openemail emails translate --to <value> | 翻訳付きの送信で何が届くかを、--subject、--html、--text についてプレビューします。何も保存も送信もされず、AI アクションを 1 回消費します |
| openemail emails list | 送信済みメールの 1 ページを新しい順に。--status、--from、--broadcast-id で絞り込めます |
| openemail emails get <id> | 送信済みメール 1 通を、受信者ごとのステータス、エラー、配信時刻とともに表示し、追跡されていた場合は完全なトラッキングレポートも含めます |
| openemail emails list-events <id> | 1 回の送信のイベント履歴を古い順に。受付、予約、送信、配信、バウンス、苦情、開封、クリックなど |
| openemail emails get-tracking <id> | 1 回の送信のエンゲージメントレポート。合計、追跡された各コピーにつき 1 件のエントリ、書き換えられたすべてのリンクとそのクリック数 |
| openemail emails cancel <id> | キューにある、または予約されたメールを送られる前に止めます。確認を求めます |
| openemail emails reschedule <id> <scheduled-at> | キューにある、または予約されたメールを、ISO 8601 の日時、または PT30M のような期間に移します。1 秒後から 365 日後まで指定できます |
tracking のすべてのコマンド
5 つすべてに emails:read が必要です。tracking get、list-opens、list-clicks は、メッセージが持つどちらの ID でも受け付けます。送信が返した msg_ の ID か、tracking list と Webhook のペイロードに含まれる tmsg_ のトラッキング ID です。
| コマンド | 機能 |
|---|---|
| openemail tracking list | ある期間内に送信された追跡対象メッセージの 1 ページを新しい順に、それぞれ完全なレポート付きで。--opened と --clicked で絞り込み、--no-opened では誰も開封しなかったものだけを残します。期間は --days か --minutes で指定しない限り 30 日です |
| openemail tracking get-stats | エンゲージメントパネルの元になる数値。追跡、開封、クリックされたメッセージ数、開封率とクリック率、--grain 単位の時系列、上位のリンク、メールクライアント、国 |
| openemail tracking get <id> | 1 通のメッセージのエンゲージメントレポート。emails get-tracking が返すものと同じドキュメントです |
| openemail tracking list-opens <id> | メッセージの開封数の内訳となる個々の開封を新しい順に。それぞれに human、proxy、machine の印が付きます。--include-machine を付けると、カウントされなかったヒットも加わります |
| openemail tracking list-clicks <id> | メッセージのリンクに対する個々のクリックを新しい順に、それぞれ元の url とともに。--include-machine を付けると、リンクスキャナーとまとめられた繰り返しも加わります |
tracking list と get-stats は、Web アプリで書いたメールや MCP ツールやアシスタントが送ったメールを含め、メールボックスが送信したすべての追跡対象メッセージを対象にします。一方、emails list には API が作成した送信記録が入っています。送信記録のないレポートでは sendId が null になります。
例
独自の冪等キーを付けてスクリプトから送信します。同じ --idempotency-key でもう一度実行すると、2 通目を送る代わりに、最初のメールを replayed: true 付きで表示します。
openemail emails send \ --from 'Acme Billing <[email protected]>' \ --to [email protected] \ --subject 'Your September invoice' \ --html '<p>The invoice is attached. Tell me if anything on it looks wrong.</p>' \ --attachments '[{"fileId":"file_6bb640f5b99e47deb758f1f5"}]' \ --tracking '{"opens":false}' \ --idempotency-key invoice:inv_2026_09_4192 \ --json | jq -r '.id + " " + .status'送る前に翻訳を人に読んでもらいます。承認された文面は --translate を付けずに、そのまま --subject と --html として送ってください。付けると 2 回翻訳されます。--no-include-original を渡さない限り、翻訳された html にはその下に元の文面がすでに含まれています。
openemail emails translate --to de \ --subject 'Your September invoice' \ --html "$(cat invoice.html)" \ --json > preview.jsonjq -r .html preview.jsonopenemail emails send --from [email protected] --to [email protected] \ --subject "$(jq -r .subject preview.json)" \ --html "$(jq -r .html preview.json)"ファイルから一括送信します。一部の項目が失敗しても、一括送信が処理されればコマンドは終了コード 0 で終了するので、failed と各項目の status を読んでください。同じキーでもう一度実行すると、送信済みの項目は再生され、残りだけが送られます。ただし配列の順序が変わっていない場合に限ります。
[ { "from": "[email protected]", "to": "[email protected]", "subject": "Receipt 4192", "text": "Thanks for your order." }, { "from": "[email protected]", "to": "[email protected]", "subject": "Receipt 4193", "text": "Thanks for your order." }]openemail emails send-batch receipts.json --idempotency-key receipts:2026-09-27 --json > result.jsonjq '{ sent, failed }' result.jsonjq -r '.items[] | select(.status == "error") | "\(.index) \(.error.code)"' result.jsonメールを予約し、日時を移し、取り消します。--yes は cancel が求める確認に代わりに答えます。スクリプトは確認に答えられないためです。
ID=$(openemail send --from [email protected] --to [email protected] --subject "Standup notes" \ --body-file notes.md --at 2026-10-01T09:00:00Z --json | jq -r .id)openemail emails reschedule "$ID" 2026-10-01T13:00:00Zopenemail emails get "$ID" --json | jq -r '.status + " " + .scheduledAt'openemail emails cancel "$ID" --yes失敗した送信を見つけ、そのうち 1 つに何が起きたかを読みます。--json なしでパイプすると、--all は 1 行に 1 つの JSON オブジェクトを出力します。
openemail emails list --status failed,partial --from [email protected] --all | jq -r .idopenemail emails get msg_3f9a1c07d2b84e6a9c5b1f20openemail emails list-events msg_3f9a1c07d2b84e6a9c5b1f20 --all --json | jq -r '.items[] | .createdAt + " " + .type'UTC+2 の午前 0 時で区切った日単位で 1 週間分のエンゲージメントを読み、誰も開封しなかったものを一覧にし、1 通のメッセージの各リンクのクリック数を数えます。
openemail tracking get-stats --days 7 --offset-minutes 120 --json | jq '{ tracked, openRate, clickRate }'openemail tracking list --no-opened --days 7 --all | jq -r .subjectopenemail tracking list-clicks msg_3f9a1c07d2b84e6a9c5b1f20 --all | jq -r .url | sort | uniq -cスコープ、コード、確認
- ブラウザでのサインインでは承認ページでスコープを求め、
openemail login --scopes emails:send,emails:readで両方をあらかじめ選択できます。スコープが足りないコマンドは終了コード4とinsufficient_scopeで停止し、そのスコープ名を示します。 - 5 MB を超えるファイルを付けた
send --attachは、まずそれらを「ファイル」にアップロードするため、files:writeも必要です。 - これらのコマンドはどれも確認コードを求めないので、ブラウザでのサインインでも API キーと同じように実行されます。
emails cancelは取り消す前に確認し、--yesを付けると代わりに答えます。--yesなしの無人実行では、Refusing to run unattended. Pass --yes to confirm.と終了コード2で停止します。emails send、send-batch、rescheduleは何も尋ねません。sendは概要を表示し、ターミナルでのみ確認を求めます。--yesを付けるとそれも省略されます。--dry-runはコマンドが送るはずのリクエストを表示し、何も送らずに終了コード0で終了します。emails translateでは AI アクションを消費せず、emails cancelでは何も尋ねません。
結果のページ
emails list、emails list-events、tracking list、list-opens、list-clicks は 1 ページを読みます。--limit でそのサイズを指定します。2 つの emails のリストでは 1 から 100 で既定は 25、3 つの tracking のリストでは 1 から 200 で既定は 50 です。--cursor は、ページが表示したカーソルから続けます。
--allはすべてのページを読んで項目をストリームします。ターミナルでは表として、パイプしたときや--ndjsonを付けたときは 1 行に 1 つの JSON オブジェクトとして出力します。--max <n>はその件数で停止し、--allを含意します。--jsonは、--allの場合も含めて 1 つの{ items, hasMore, nextCursor }ドキュメントを出力します。- ページングはオフセットではなくカーソルで行うので、ページをめくっている間に送信されたメールによって行がずれたり重複したりすることはありません。
知っておくと役立つこと
- 実行のたびに独自の冪等キーが作られ、その実行内の再試行をカバーします。送信を 2 回実行すると、両方の実行で同じ
--idempotency-keyを渡さない限り 2 回送信されます。同じキーで異なる本文を送ると、idempotency_key_reuseと終了コード7で拒否されます。 - 取り消しや日時の移動ができるのは
queuedとscheduledのメールだけです。取り消し猶予のない即時送信はリクエストの中で送られるため、ID を手にした時点では通常もう手遅れで、呼び出しはemail_not_cancellableと終了コード6で終わります。 - 取り消したメールは取り消されたままです。再スケジュールで変わるのは時刻だけで、期間で指定した場合はサーバーがリクエストを受け取った時点から数えます。本文を変えるには、取り消してから送り直してください。
- 翻訳を生成できない場合は送信全体が拒否され、未翻訳のまま送られるものはありません。翻訳付きの一括送信に含められる
translate付きのメッセージは最大 10 通です。 - 送信枠を使い切ると、月の初日まで送信が
send_quota_exceededで止まり、AI の枠を使い切ると、UTC の午前 0 時まで翻訳がai_quota_exceededで止まります。どちらも終了コード8です。 oe_test_キーで送ったメールは配信されません。ステータスはsentと表示され、transportはtestになり、追跡されることもありません。- ピクセルも書き換えられたリンクも含まないメッセージに対して、
emails get-trackingとtracking getは 404(終了コード5)を返します。追跡されていないことは、開封されていないことと同じではないからです。トラッキングはメッセージ送信時の設定に従うため、後でオンにしても以前のメールには及びません。 - どの数値も下限値です。メールクライアントが画像をブロックしている読者は開封として数えられず、クリックは開封よりも強い既読の証拠です。
list-opensとlist-clicksは、何も追跡されていないmsg_の ID には 404 を返しますが、tmsg_の ID は与えられたまま受け取るため、不明な ID では空のリストが返ります。- 一部のアドレスに限定されたキーは、それらのアドレスから送られたメールしか見えず、ドメイン全体を持つキーはそのドメインのすべてのアドレスを対象にします。
すべてのフラグ
このページでは特に重要なフラグを紹介しています。openemail <command> --help は、コマンドが受け取るすべての引数とフラグを、その型、必要なスコープ、メソッドとパス、返す内容、API リファレンスの注記とともに一覧表示します。--json を付けると、同じヘルプを 1 つの JSON ドキュメントとして出力します。
openemail emails --helpopenemail emails send --helpopenemail tracking list-opens --help --json