0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

blastengine MCPを1通で検証。送信ツール・配信ログ・Gmailを照合した

0
Posted at

1通送れた。配信ログもSENT。それなのに、MCPで取得した利用通数は0でした。

blastengineの公式MCPサーバーから自分宛てに1通送り、配信ログとGmailまで照合しました。利用状況のupdated_timeを読むと、23:52の送信より古い23:47:30の値だったと分かりました。「利用0だから未送信」とAIが判断したら、余計な再送をしかねません。

この記事では、送信ツールの返り値から配信IDを追い、送信の結果と利用量の集計を分けて確認する手順を残します。記録は2026年11月4日の1通分です。Gmailでは届いた本文を迷惑メール内に確認しました。

配信ID・配信ログ・受信結果を対応させる

確認先 今回確認した結果 そこから言えること
MCPの送信ツール delivery_id: 1 追跡する配信IDを取得した
blastengineの配信ログ 配信成功、応答コード250 配信ログ上で成功と記録された
Gmail 迷惑メール内に本文を確認 今回の1通は届いたが、受信トレイには入らなかった

blastengine管理画面の配信成功・応答コード250

2026年11月4日23:52 JSTの検証。件名・ステータス・応答コードの部分を切り出しています。

Gmailで迷惑メールに振り分けられた検証メール

同じ件名のメールをGmailで開いた結果。「以前迷惑メールと判断されたメールに類似」と表示され、指定した本文を確認できました。個人アドレスの部分は撮影範囲から外しています。

これは1通の動作確認です。到達率の比較や、迷惑メール判定の原因特定をした実験ではありません。今回は自分のGmailアドレスを送信元にも使っており、独自ドメインの認証を整えた運用環境とは条件が違います。

まず「送らずに読む」接続を作った

公式マニュアルで紹介されている公開リポジトリを使いました。検証したのはblastengine-mcp-server 0.2.2、コミットは46961dc304824b60311484c6b84bde9f5967796dです。公式リポジトリ

今回はClaude Desktopへ常設する代わりに、小さなNode.jsのMCPクライアントからローカルのstdioサーバーへ接続しました。AIエージェントによる検証作業ですが、Claude Desktopのチャット画面で試した例ではありません。

最初は次の設定で起動しています。

{
  "BLASTENGINE_ENABLE_SEND": "false",
  "BLASTENGINE_ENABLE_BULK": "false",
  "BLASTENGINE_ENABLE_CSV_IMPORT": "false"
}

ログインIDとAPIキーは別途環境変数で渡します。キーを記事、ソースコード、スクリーンショットへ入れないようにします。

この状態でtools/listから15個のツールを取得し、次の二つを呼びました。

ツール 確認する内容 送信前の結果
blastengine_usage_latest_get 利用通数・残量・更新時刻 利用0、残り10,000
blastengine_mail_results_list 対象期間の配信ログ data: []

「無効」と「ツール一覧に出ない」は同じではなかった

送信を無効にした起動でも、tools/listにはblastengine_send_transactionが載っていました。ツールが見えるだけで、送信可能と判断してはいけません。

この版のソースでは、送信操作時にBLASTENGINE_ENABLE_SENDを確認する実装になっています。11月4日の実送信検証では、送信無効時の送信ツール自体は呼び出していません。そこで11月7日、次の隔離試験を追加しました。

追試:一覧に載る送信ツールを呼ぶと、上流へ届く前に拒否された

公式MCPサーバー0.2.2をstdioで起動し、送信・一斉配信・CSV取込をすべてfalseにしました。接続先のBLASTENGINE_BASE_URLは自分のPCのHTTPサーバー、認証情報はダミーです。blastengineの実APIへ送信要求を出した試験ではありません。

操作 実際の結果 ローカルHTTPサーバーが受けた要求
tools/list 送信ツールが一覧に含まれる 0
blastengine_send_transaction isError: true、code: send_disabled 0
blastengine_usage_latest_get モックの利用状況を取得 GET /usages/latest が1件

送信ツールには構文上正しい例示用アドレス・件名・本文を渡しました。返答は次のとおりです。

{"code":"send_disabled","message":"BLASTENGINE_ENABLE_SEND=true is required to send transaction mail","retryable":false}

SDKクライアント側でisErrorとコードを検査し、送信呼び出し直後のHTTP要求数が0であることもassertしました。その後に参照系のGETが1件届いたため、単に接続不能だったという結果とも区別できます。参照系の返答値は自作モックの固定値なので、実アカウントの利用状況としては扱いません。

この試験で分かったのは、当該版の送信無効設定が、ツールを隠す方式ではなく実行時に拒否することです。人間の承認済みかをMCPサーバーが自動判断したわけではありません。送信を有効にしたプロセスでは、宛先や本文の承認は別途必要です。

AIと人間がそれぞれ決めたこと

実送信では、人間が宛先・件名・本文・1通という上限を承認しました。AIエージェントは接続設定の準備、ローカルMCPクライアントの実行、配信IDを使ったログの照合を担当しました。迷惑メール内の受信結果と利用状況の基準時刻も確認しています。今回の追試では、AIがダミーの上流を用意し、拒否の返答と要求数を照合しました。

実送信をもう一度行わずに、未確認だった拒否動作を補えました。実サービスへの配送確認と、ローカルでの安全策の検査は、異なる証拠として残しています。

トライアルでは、先に送信先を登録する

管理画面のスタートアップガイドには、トライアルの配信可能アドレスを登録する案内がありました。今回の画面では5件までの登録と説明されていました。

そこで自分が管理する宛先だけを登録し、今回の送信条件を固定しました。

宛先:自分が管理する検証用メールアドレス1件
件名:【アドカレ検証】blastengine受信確認
本文:Qiita記事の動作確認用メールです。返信は不要です。
件数:1通
一斉配信・CSV取込:使わない

宛先が許可リストに入っていることと、今回の本文を送ってよいことも別の確認です。今回は宛先・件名・本文・件数について、人間の承認を得てから実行しています。

MCPを通して送信し、配信IDを受け取る

1通の送信時だけ、別のローカルプロセスでBLASTENGINE_ENABLE_SEND=trueにしました。一斉配信・CSV取込はfalseのままです。実行したツールと引数の形は次です。アドレスは例示に置き換えています。

{
  "name": "blastengine_send_transaction",
  "arguments": {
    "from_email": "sender@example.com",
    "to": "recipient@example.com",
    "subject": "【アドカレ検証】blastengine受信確認",
    "text_part": "Qiita記事の動作確認用メールです。返信は不要です。"
  }
}

返った値は次でした。

{
  "delivery_id": 1
}

ここで「受信者が読める」とまでは言いません。次はこのIDの結果を調べます。送信用プロセスは終了し、確認は再び送信無効のプロセスで行いました。

管理画面とMCPのログを照合する

blastengine_mail_results_listには、相対的な「今日」ではなく、時差を含む開始・終了時刻を渡しました。

{
  "name": "blastengine_mail_results_list",
  "arguments": {
    "count": 100,
    "delivery_start": "2026-11-04T00:00:00+09:00",
    "delivery_end": "2026-11-05T00:00:00+09:00"
  }
}

結果のうち、今回照合した項目は以下です。宛先等を省いた抜粋です。

{
  "delivery_id": 1,
  "maillog_id": 1,
  "delivery_type": "TRANSACTION",
  "status": "SENT",
  "last_response_code": "250",
  "last_response_message": "配信に成功しました"
}

管理画面の「配信成功」「250」と対応しました。一方、Gmailでは同じ件名と本文を迷惑メール内に確認しています。配信ログの成功を、受信トレイへの配置保証へ読み替えないことが、画面を並べるとよく分かります。

なお、Gmailの表示だけからSPF、DKIM、DMARCのどれが判定原因だったかは特定していません。認証結果のヘッダ照合や、認証済み独自ドメインでの比較は次の検証です。

利用状況には、値と一緒に更新時刻が必要だった

もう一つ気になった点があります。送信後に取得した利用状況には、まだ次の値が返りました。

{
  "month": 202611,
  "current": 0,
  "remaining": 10000,
  "updated_time": "2026-11-04T23:47:30+09:00"
}

今回の送信は23:52です。利用状況の更新時刻はそれより前でした。配信ログに1件あるのに利用状況が0だからといって、「送れていないので再送」と判断すると危険です。

この観測から更新間隔の仕様までは断定できません。ただ、AIに残量を要約させるなら「残り10,000通」だけでなく、何時時点の情報かも返してほしいと思いました。

AIの完了報告を「送れました」で終わらせない

残すもの 必要な理由
承認した宛先・件名・本文・件数 送信した内容が依頼と一致するか確かめる
delivery_idとmaillog_id ツールの返り値と配信結果を対応させる
確認した期間・時差 別の日や別の配信を調べない
状態・SMTP応答・観測時刻 API受理、配信結果、古い利用状況を混ぜない
受信側で確認した場所 配信ログだけでは分からない配置を記録する

今回の結果を人が判断できる報告にするなら、次のように書けます。これはMCPの生レスポンスではなく、上記の観測をまとめ直した例です。

対象:今回承認した1通、delivery_id=1
配信ログ:SENT / SMTP応答250、maillog_id=1
受信確認:Gmailの迷惑メール内で同じ件名・本文を確認
利用状況:current=0、remaining=10000
利用状況の基準時刻:2026-11-04 23:47:30 +09:00(23:52の送信より前)
判断:利用0を根拠に再送しない。既存の配信IDを追跡する
未確認:迷惑メール判定の原因、利用状況が反映されるまでの時間

実装するなら、「送信要求」「配信ログの取得」「人による受信確認」を別の状態として保持します。利用量の値だけを見て送信処理へ戻す分岐は作りません。タイムアウトなどで送信結果が不明になった場合も、今回の記録だけでは再送の安全性を保証できないため、結果不明として確認へ回します。

今回の収穫は、MCPでメールを送れたことに加え、配信結果と利用状況の鮮度が別だったことです。AIに運用を手伝わせるときは、値と一緒に「何を、いつ確認したか」を返す必要がありました。

blastengine MCP設定マニュアル/検証した公式リポジトリ

執筆・検証補助にAIを使用しています。実行経路はローカルのMCPクライアントで、Claude Desktopの操作記録ではありません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?