SendGrid の統計・Email Activity を取得する、読み取り専用 CLI です。
sendgridctl result はアカウント単位の日次イベント統計を取得します。
--sender を指定した場合だけ、送信元で絞った Email Activity のレコード状態スナップショットへ切り替わります。
--sender を省略したときの API・schema・出力バイト列は従来と同じです。
sendgridctl describe は、その送信元モードの件数のもとになった個々のメッセージレコードを一覧します
(メッセージ詳細)。
Go 1.27 以上が必要です。SDK は sendgrid-go/v4 v4.0.0-rc.10(RC)を使用します。
上流 SDK の helpers/mail 参照により sendgrid-go v3.16.1+incompatible も間接依存に含まれます。
CLI の直接 import は v4 のままで、SDK の置換・replace・vendoring はしていません。
go build -o sendgridctl .
./sendgridctl --help
./sendgridctl result --help
./sendgridctl describe --helpSENDGRID_API_KEY に、通常モードでは Stats の読み取り権限、
--sender モードでは email_activity.read を持つキーを設定してください。
認証情報はこの環境変数からのみ読み込みます。キー指定フラグ・設定ファイルはありません。
キーをソースやシェル履歴に保存せず、シークレット管理ツールなどから環境へ渡してください。
ルート単体、help、completion はキー不要で、通信しません。
以下の日付は使用例のリテラルです。実際に調査する開始日・終了日を明示してください。
./sendgridctl result --start-date 2026-01-01 --end-date 2026-01-07
./sendgridctl result --start-date 2026-01-01 --end-date 2026-01-07 --format json --total
./sendgridctl result --start-date 2026-01-01 --end-date 2026-01-07 --format csv --region eu --timeout 60s
./sendgridctl result --start-date 2026-01-01 --end-date 2026-01-07 --sender sender@example.com --format json --total
./sendgridctl result --start-date 2026-01-01 --end-date 2026-01-07 --language ja --total
# インストールせずに実行する場合:
go run . result --start-date 2026-01-01 --end-date 2026-01-07| フラグ | 既定値 | 制約 |
|---|---|---|
--start-date |
なし・必須 | 厳密な YYYY-MM-DD の暦日 |
--end-date |
なし・必須 | 開始日以降の暦日 |
--format |
table |
table / json / csv のみ |
--language |
en |
en / ja のみ。table の文言と stderr の注意書きだけが変わる(表示言語) |
--sender |
なし | bare address 1 件のみ。指定時は Email Activity へ切替、重複指定不可 |
--total |
false |
通常は取得バケット合計、--sender では取得レコード合計を追加 |
--region |
global |
global / eu のみ。--sender と eu の併用不可 |
--timeout |
30s |
正の Go duration。再試行・待機を含む取得全体の期限 |
result は位置引数を取りません。開始・終了ラベルを含め最大 366 暦日です。
この上限は CLI の出力量制限で、SendGrid の保持期間や API 上限を示すものではありません。
global は api.sendgrid.com、eu は EU regional subuser 用の api.eu.sendgrid.com を選びます。
stats エイリアスはありません。
- 日付は API-native です。指定した日付を
start_date/end_dateとして無変換で渡します。 日付境界の包含・排他、date-only バケットのタイムゾーンは保証しません。UTC と推定しません。 - 自アカウントのイベント発生日ベース統計です。親と全 subuser、category 別の数値を合算しません。
On-Behalf-Ofも使用しません。 requestsはメール配信要求数で、HTTP リクエスト数ではありません。processed/delivered/deferredなどは互いに排他的な最終状態ではありません。deliveredは受信箱への到達保証ではありません。- unique 指標、成功率・失敗率、pending、
requests - deliveredなどの派生状態は生成しません。 個別メールの調査が必要なら Email Activity、継続的な履歴収集が必要なら Event Webhook を別途検討してください。 - API の応答に含まれた日だけを出します。取得されなかった日をゼロ行で補完しません。 指標の欠損と観測された整数ゼロも区別します。
--totalは 取得バケットだけ の合計です。要求期間全体の完全な合計ではありません。 取得バケットのどれかで指標が欠けていれば、その指標の合計も欠損です。 空結果には合計行を作りません。- 完全性は常に
unknownです。全ページ取得・全日付取得でも、保持期間、更新遅延、取得中の変化は確定できません。 数値は後日変わる可能性があります。
出力指標の順序:
requests, processed, delivered, bounces, blocks, deferred,
invalid_emails, bounce_drops, spam_report_drops, unsubscribe_drops, spam_reports
- Stats API は送信元の絞り込みをサポートしないため、global の
GET /v3/messagesを使います。 エラー時にアカウント統計へフォールバックしません。--region euとの併用はキー読み取り前に失敗します。 - 有料の Additional Email Activity History の購入と
email_activity.read権限が必要です。 保持期間は最大 30 日、API は毎分 6 リクエストです。366 日のローカル上限は履歴保持の保証ではありません。 --sender sender@example.comのように bare address を 1 件だけ指定します。 大文字・小文字を変更せず、通常の plus address や apostrophe を含むアドレスも扱います。 明示的な空値、複数アドレス、フラグの重複、表示名、制御文字、引用符、バックスラッシュは拒否します。 クエリのエスケープ仕様を確認できるまでは quoted mailbox はサポートしません。- 日付は
last_event_timeの UTC 暦日です。開始日の00:00:00Z以上、 終了日の翌日00:00:00Z未満という半開区間で選びます。翌日を表現できない終了日も拒否します。sent_atの送信日による絞り込みではありません。 - 数値は取得したメールレコードの 状態スナップショットです。元の account event counter と比較・合算できません。
日次行は UTC の最新イベント日ごとに
processed/delivered/not_deliveredを数えます。 API 応答仕様 のprocessedと query reference のprocessingは表記が一致しないため、status filter は付けず、応答の既知状態だけを検証します。 未知の状態を別の状態へ読み替えません。result --senderは件名・受信者・メッセージ ID を出力しません (個々のレコードはdescribeが出力します)。 - 1 回の query limit は 1000 です。取得件数が 1000 件以上なら不完全の可能性があるため失敗し、
stdout は出しません。独自のページング・期間分割はしません。期間を狭めて再実行してください。
ただし、1 日だけの指定でも件数が多ければ上限に達するため、取得できるとは限りません。
1000 件未満でも保持期間や反映遅延があるため完全性は
unknownです。 --totalは 取得レコードだけの合計です。過去の総送信数ではありません。 取得されなかった日をゼロで補完せず、空結果には合計行を作りません。 空結果は過去の送信数がゼロだった証拠にはなりません。
result --sender が数えるのは processed / delivered / not_delivered の件数だけです。
describe は、その件数のもとになった 個々のメッセージレコードを一覧し、
どのメッセージが配信失敗(not_delivered)なのかを確認できるようにします。
./sendgridctl describe --sender sender@example.com --start-date 2026-01-01 --end-date 2026-01-07 --status not_delivered
./sendgridctl describe --sender sender@example.com --start-date 2026-01-01 --end-date 2026-01-07 --status processed --status not_delivered --format json
./sendgridctl describe --sender sender@example.com --start-date 2026-01-01 --end-date 2026-01-07 --format csv --language ja| フラグ | 既定値 | 制約 |
|---|---|---|
--sender |
なし・必須 | bare address 1 件のみ。検証は result --sender と同じで、重複指定不可 |
--start-date |
なし・必須 | last_event_time の UTC 暦日(両端を含む)。厳密な YYYY-MM-DD |
--end-date |
なし・必須 | 開始日以降の暦日。開始日から終了日まで最大 366 日 |
--status |
全状態 | processed / delivered / not_delivered のいずれか。繰り返し指定で複数選択 |
--format |
table |
table / json / csv のみ |
--language |
en |
en / ja のみ。table の文言と stderr の注意書きだけが変わる |
--timeout |
30s |
正の Go duration。再試行・待機を含む取得全体の期限 |
--region と --total はありません。Email Activity は global のみで EU は未対応です。
--status は小文字で正確に指定します。大文字小文字の変換、カンマ区切り(processed,delivered)、
同じ値の重複、空値は終了コード 2 で拒否します。複数の状態は --status を繰り返してください。
検証は日付範囲、--format、--language、--timeout、--sender、--status の順に行い、
すべて SENDGRID_API_KEY の読み取りより前に終わります。
- 件名(
subject)・宛先(to_email)・メッセージ ID(msg_id)を出力します。 これらを出力しないresult --senderとは異なります。出力は個人情報を含み得るため、保存先や共有先に注意してください。 - 日付は
result --senderと同じくlast_event_timeの UTC 暦日(半開区間)で、sent_atの送信日ではありません。 各行はメッセージレコードの状態スナップショットで、イベント履歴ではありません。 --statusは取得後にローカルで絞り込みます。processedとprocessingのように API 応答仕様と query reference の 状態表記が一致しないため、result --senderと同じく API には status filter を付けません。 その結果、1000 件の上限は絞り込み前の送信元の全結果に適用されます。not_deliveredが数件しかなくても、全状態の取得件数が 1000 件以上なら失敗し、stdout は出しません。 期間を狭めて再実行してください。ただし 1 日だけの指定でも件数が多ければ上限に達します。- 応答の検証は
result --senderと同じです。空のmsg_id/to_email、(msg_id, to_email)の重複、 送信元の不一致、期間外のlast_event_time、未知の状態は、部分的な出力をせず終了コード 1 で失敗します。 - 並び順は
last_event_timeの昇順、同時刻ならmsg_id、さらに同じならto_emailの昇順です。 - 有料の Additional Email Activity History の購入と
email_activity.read権限が必要です。 保持期間は最大 30 日、API は毎分 6 リクエストです。 - 完全性は常に不明(
unknown)です。空の出力は過去の送信がなかった証拠にはなりません。 stderr の注意書きは 2 種類あります。応答にレコードがなかった場合と、 レコードはあったが--statusに一致するものがなかった場合(取得件数つき)です。 - 配信失敗の理由(バウンス理由など)はこのエンドポイントの応答に含まれません。
describeの対象外です。
- table: 先頭に取得元・送信元・状態フィルター・最新イベント時刻(UTC)・完全性不明を示す行を出し、
列は
LAST_EVENT_TIME STATUS TO_EMAIL SUBJECT OPENS CLICKS MSG_IDです。 件名が空なら-と表示します。 1 メッセージを必ず 1 行に収めるため、table に限り、subject/to_email/msg_idの制御文字 (タブ・改行・ESC など、unicode.IsControlに該当する文字)を 1 文字ずつ空白に置き換えます。 メールの送信者が決める文字列で、表のレイアウトが崩れたり端末が操作されたりするのを防ぐためです。enの table はtext/tabwriterによる空白整列のため、全角文字を含む件名では桁がずれます。jaの table は桁揃えをしないパイプ区切りで、上の置換に加えて縦線|を全角の|に置き換えます。jaの列は最新イベント時刻(UTC) | 状態 | 宛先(to_email) | 件名(subject) | 開封数(opens_count) | クリック数(clicks_count) | メッセージ ID(msg_id)です。 状態は処理済み(processed)/配信済み(delivered)/配信失敗(not_delivered)と表示します。 - JSON:
schema_version: 3。metadata はsource: email_activity、scope: sender、sender、region: global、start_date/end_date、interval_start/interval_end_exclusive、time_field: last_event_time、timezone: UTC、query_limit: 1000、completeness: unknown、status_filter、retention: up_to_30_days、returned_messages、listed_messagesを含みます。status_filterは選択した状態をprocessed,delivered,not_deliveredの順で並べた配列で、指定がなければ 3 つすべてです。returned_messagesは検証後・絞り込み前の取得件数、listed_messagesは絞り込み後の件数です。messagesの各要素はmsg_id,from_email,to_email,subject,status,last_event_time(UTC・time.RFC3339Nano形式の文字列),opens_count,clicks_countで、空なら[]です。 - CSV:
source,sender,time_field,timezone,completeness,msg_id,from_email,to_email,subject,status,last_event_time,opens_count,clicks_count。 1 メッセージ 1 行で、空ならヘッダーのみです。stderr には sender・latest-event UTC・状態スナップショット・ 完全性不明・状態フィルターに一致した取得レコード限定の警告を出します。
JSON と CSV は文字列を加工せず、en と ja で同一のバイト列です。
JSON は制御文字をエスケープしますが、CSV は制御文字を生のバイトとして出力します(引用が必要なフィールドだけを引用します)。
件名や宛先はメールの送信者が決めるため、CSV は端末に表示せずファイルに保存してください。
CSV は値を変更しないため、表計算ソフトで開く場合は、= + - @ で始まる件名や宛先が数式として解釈され得ます。
{
"schema_version": 3,
"metadata": {
"source": "email_activity",
"scope": "sender",
"sender": "sender@example.com",
"region": "global",
"start_date": "2026-01-01",
"end_date": "2026-01-07",
"interval_start": "2026-01-01T00:00:00Z",
"interval_end_exclusive": "2026-01-08T00:00:00Z",
"time_field": "last_event_time",
"timezone": "UTC",
"query_limit": 1000,
"completeness": "unknown",
"status_filter": [
"not_delivered"
],
"retention": "up_to_30_days",
"returned_messages": 42,
"listed_messages": 1
},
"messages": [
{
"msg_id": "example-message-id",
"from_email": "sender@example.com",
"to_email": "recipient@example.net",
"subject": "Example subject",
"status": "not_delivered",
"last_event_time": "2026-01-03T04:05:06Z",
"opens_count": 0,
"clicks_count": 0
}
]
}終了コードは result と同じです(出力と終了コード)。
入力・設定エラーは 2、API・応答検証・整形・出力エラーと取得期限切れは 1、Ctrl-C は 130 です。
出力先自体の書込失敗を除き、すべての取得・検証・整形が成功してから stdout を開始します。
stdout には指定形式の出力だけを、stderr には説明・警告・エラーを出します。 すべての取得・検証・集計・整形が成功してから stdout を開始します。 出力先自体の書込失敗は終了コード 1 ですが、書込済みの接頭部分は取り消せません。
--sender なしの出力:
- table:
KIND DATE METRIC VALUEの長形式。欠損はN/A、合計の日付は-。 冒頭に API-native 日付と完全性不明の metadata を表示します。 - JSON:
schema_version: 1、metadata とrows。 metadata はtimezone: null、timezone_basis: api_native_unspecified、total_basis: returned_buckets、completeness: unknownを含みます。 欠損値・合計行の日付はnullです。 - CSV:
kind,date,metric,value。欠損値・合計日付は空フィールド。 API-native 日付と完全性不明の警告を stderr に出します。
日付昇順、指標は上記の固定順です。通常行の kind は day、合計は returned_total。
空結果も正常終了し、JSON は rows: []、table / CSV はデータ行なしです。
metadata やヘッダーは残し、stderr に空結果の説明を出します。
--sender ありの出力は別 schema です:
- table: source・sender・latest-event UTC・完全性不明を表示し、
列は
KIND DATE RETURNED_MESSAGES PROCESSED DELIVERED NOT_DELIVEREDです。 - JSON:
schema_version: 2。metadata はsource: email_activity、scope: sender、sender、region: global、start_date/end_date、interval_start/interval_end_exclusive、time_field: last_event_time、timezone: UTC、query_limit: 1000、completeness: unknown、count_basis: returned_message_records、total_basis: returned_messages、retention: up_to_30_daysを含みます。 rows はkind,date,returned_messages,processed,delivered,not_delivered。 日付昇順で、合計の kind はreturned_total、date はnull、空結果はrows: []です。 - CSV:
source,sender,time_field,timezone,completeness,kind,date,returned_messages,processed,delivered,not_delivered。 account CSV と異なり、各行に取得元の文脈を含みます。空結果はヘッダーのみです。 stderr には sender・latest-event UTC・状態スナップショット・完全性不明・取得レコード限定の警告を出します。
describe の出力は、さらに別の schema(schema_version: 3)で、メッセージ単位の行を持ちます。
列・JSON の形・CSV ヘッダー・table の扱いは メッセージ詳細 を参照してください。
終了コードは次の表のとおり result と同じで、空結果も 0 の正常終了です。
| 終了コード | 意味 |
|---|---|
0 |
正常終了、または空結果 |
2 |
引数・設定エラー、キー未設定・空白のみ(describe では --sender 未指定と不正な --status を含む) |
1 |
API・応答検証・整形・出力エラー、取得期限切れ |
130 |
Ctrl-C による中断 |
通常モードは直列ページ取得、送信元モード(describe を含む)は単一 query です。
一時的な対象エラーだけをリクエストごとに最大 3 試行し、
リダイレクトには追従しません。応答本文はリクエストごとに 16 MiB までです。
API 応答と rate limit が主な待ち時間となるため、並列取得や常駐サービスは設けていません。
--language en|ja で、人間が読む文言の言語を選びます。既定は en で、
指定しなければ(--language en を明示しても)従来と同じ出力です。--sender の有無にかかわらず使えます。
- 値は小文字の
enとjaだけです。空値、EN、ja-JP、ja_JP.UTF-8などは 終了コード 2 で拒否し、SENDGRID_API_KEYの読み取りやクライアント生成より前に失敗します。 LANG/LC_*などのロケール環境変数からは言語を推測しません。- 変わるもの:
--format tableの見出し・ラベル・説明行(stdout)と、 空結果および CSV 用の注意書き(stderr)。 - 変わらないもの: JSON と CSV の値・キー・ヘッダー・schema は、
enとjaで同一のバイト列です。 終了コード、取得するデータ、集計結果も変わりません。エラーメッセージと--helpは常に英語です。 jaの table は、桁揃えをしないパイプ区切り(Markdown 表の形式)です。text/tabwriterは全角文字の表示幅を扱えないため、英語の table のような空白による整列はしません。- 日本語の「取得」は英語の returned に対応します。バウンスや返送されたメールを指しません。
取得メッセージ数はRETURNED_MESSAGES(取得したメッセージレコードの数)、合計(取得分のみ)はreturned_total(取得したバケットまたはレコードだけの合計)です。 - 数値の意味は変わりません。日付は
--senderなしでは API-native(タイムゾーン未指定)、--senderではlast_event_timeの UTC 暦日でありsent_atの送信日ではありません。 完全性は常に不明(unknown)です。API が返さなかった指標は欠損と表示し、観測された0とは区別します。 空結果は過去の送信ゼロの証拠になりません。
--sender なしの table の列は 種別 | 日付 | 指標 | 値 です。欠損値は 欠損、合計行の日付は - です。
日付: API-native(タイムゾーン未指定)、完全性: 不明(unknown)
| 種別 | 日付 | 指標 | 値 |
| --- | --- | --- | --- |
| 日別 | 2026-01-01 | 配信要求数(requests) | 5 |
| 日別 | 2026-01-01 | 処理済み(processed) | 欠損 |
| 日別 | 2026-01-01 | 配信済み(delivered) | 0 |
| 合計(取得分のみ) | - | 配信済み(delivered) | 0 |
上は出力の一部です。実際には指標ごとに行があります。指標の表示名は「日本語名(JSON / CSV の指標名)」の形式で、次のとおりです。
| JSON / CSV の指標 | ja の表示 |
JSON / CSV の指標 | ja の表示 |
|---|---|---|---|
requests |
配信要求数(requests) | invalid_emails |
無効なメールアドレス(invalid_emails) |
processed |
処理済み(processed) | bounce_drops |
バウンスによる破棄(bounce_drops) |
delivered |
配信済み(delivered) | spam_report_drops |
スパム報告による破棄(spam_report_drops) |
bounces |
バウンス(bounces) | unsubscribe_drops |
配信停止による破棄(unsubscribe_drops) |
blocks |
ブロック(blocks) | spam_reports |
スパム報告(spam_reports) |
deferred |
遅延(deferred) |
--sender ありの table は、取得元・送信元・集計基準を示す 2 行の説明に続けて、
列 種別 | 最新イベント日(UTC) | 取得メッセージ数 | 処理済み(processed) | 配信済み(delivered) | 配信失敗(not_delivered) を出します。
行の種別は 日別(day)と 合計(取得分のみ)(returned_total)です。
取得元: email_activity、送信元: sender@example.com、完全性: 不明(unknown)
日付は last_event_time(最新イベント時刻)の UTC 暦日です。sent_at(送信日時)ではありません。件数は取得したメッセージレコードの状態スナップショットです。
| 種別 | 最新イベント日(UTC) | 取得メッセージ数 | 処理済み(processed) | 配信済み(delivered) | 配信失敗(not_delivered) |
| --- | --- | --- | --- | --- | --- |
| 日別 | 2026-01-01 | 2 | 1 | 0 | 1 |
| 合計(取得分のみ) | - | 2 | 1 | 0 | 1 |
describe も --language に対応します。table の列と状態の表示名は
メッセージ詳細 に記載しています。
stderr の注意書き(空結果、CSV)も同じ言語で出力します。内容は英語版と対応しており、
完全性が unknown であること、合計が取得分だけであること、
--sender では last_event_time の UTC 暦日・状態スナップショット・空結果が過去の送信ゼロを意味しないことを保ちます。
Cobra 標準の生成コマンドを使用します。各シェルの詳しい導入先は
sendgridctl completion <shell> --help で確認できます。
以下は sendgridctl を PATH に置いた場合の例です。
--sender の補完はアドレス候補を API から取得せず、キーも読みません。
--language の補完は固定の候補 en / ja だけを返し、同様にキーを読まず通信しません。
describe でも同じで、--status の補完は固定の候補 processed / delivered / not_delivered だけを返します。
describe に --region はないため、補完にも現れません。
# Bash(bash-completion が必要): 現在のセッション
source <(sendgridctl completion bash)# Zsh: compsys 有効化後、現在のセッションに読み込む
autoload -U compinit; compinit
source <(sendgridctl completion zsh)
# 永続化する場合は書込可能な fpath のディレクトリに生成
sendgridctl completion zsh >| "${fpath[1]}/_sendgridctl"# fish: 現在のセッション
sendgridctl completion fish | source
# 永続化
mkdir -p ~/.config/fish/completions
sendgridctl completion fish > ~/.config/fish/completions/sendgridctl.fish# PowerShell: 現在のセッション
sendgridctl completion powershell | Out-String | Invoke-Expression
# 永続化するには生成した内容を PowerShell profile から読み込むSENDGRIDCTL_INTEGRATION=0 SENDGRIDCTL_ACTIVITY_INTEGRATION=0 go test -count=1 ./...
SENDGRIDCTL_INTEGRATION=0 SENDGRIDCTL_ACTIVITY_INTEGRATION=0 go test -race -count=1 ./...
go vet ./...通常テストは fixture・注入した取得境界・RoundTripper を使い、HTTP mock service を起動しません。
実バイナリをビルドしたオフライン help / completion / 入力検証も含みます。
実 API 検証は別途明示的に opt-in した場合だけ実行し、未実施を通常テストの成功と混同しません。
SENDGRIDCTL_INTEGRATION=1 と非空の SENDGRID_API_KEY が必要です。
対象日は SENDGRIDCTL_TEST_START_DATE / SENDGRIDCTL_TEST_END_DATE で明示し、
SENDGRIDCTL_TEST_REGION は省略時 global です。opt-in がなければ理由付きで skip します。
opt-in 後にキー・必須日付が未設定、または設定が不正ならテストは失敗します。
キーを安全に環境へ設定した上で、読み取り API の実行を許可する場合だけ実行してください。 このテストは固定イベント数を期待せず、取得データの構造・期間・非負値の整合性を検証します。
SENDGRIDCTL_INTEGRATION=1 \
SENDGRIDCTL_TEST_START_DATE=2026-01-01 \
SENDGRIDCTL_TEST_END_DATE=2026-01-02 \
SENDGRIDCTL_TEST_REGION=global \
go test -count=1 -v -run '^TestIntegrationFetch$' ./internal/sendgrid上記は Stats の検証であり、送信元モードの検証にはなりません。
Email Activity の実 API 検証は別の SENDGRIDCTL_ACTIVITY_INTEGRATION=1 で opt-in します。
SENDGRID_API_KEY、明示的な開始日・終了日、SENDGRIDCTL_TEST_SENDER が必須です。
region は global のみで、SENDGRIDCTL_TEST_REGION=eu は拒否します。
opt-in がなければキーを読む前に skip し、opt-in 後の設定不備は失敗します。
購入済み履歴と権限がある場合だけ実行してください。空結果でも過去の送信がゼロとは断定しません。
SENDGRIDCTL_INTEGRATION=0 \
SENDGRIDCTL_ACTIVITY_INTEGRATION=1 \
SENDGRIDCTL_TEST_START_DATE=2026-01-01 \
SENDGRIDCTL_TEST_END_DATE=2026-01-02 \
SENDGRIDCTL_TEST_SENDER=sender@example.com \
SENDGRIDCTL_TEST_REGION=global \
go test -count=1 -v -run '^TestIntegrationActivityFetch$' ./internal/sendgrid