新規のお客様新規アカウントで DNS と CDN の無料プランをご利用いただけます。アカウント作成

イベントと Webhook

送信ログでメッセージのステータスを追跡し、署名付きの配信、バウンス、苦情、開封、クリックの各イベントをお客様のエンドポイントで受信します。

7 分で読めます 更新日 2026年10月20日

送信したメッセージにはそれぞれメッセージ ID が付与され、キューへの登録、配信、再試行、バウンスに応じて一連のステータスを経て処理されます。この状況は、コンソールの送信ログで確認したり、API で照会したり、Webhook で各イベントをお客様自身のサーバーに送信させたりできます。

メッセージのステータス

受信者ごとのコピーにはそれぞれ 1 つのステータスがあります。ステータスは先に進むだけです。たとえば、配信済みのメッセージが後からバウンスや苦情になることはありますが、キュー済みに戻ることはありません。

ステータスコンソールの表示意味
queued待機中受け付けられ、配信を待っています
deferred遅延・再試行受信側サーバーが一時エラーを返しました。配信は最大 72 時間再試行されます。
delivered配信済み受信側サーバーがメッセージを受け付けました
bouncedバウンス配信中、または後から受け取ったバウンスレポートにより、配信が恒久的に失敗しました。バウンスの種類は下記をご覧ください。
complained苦情受信者がメッセージをスパムとして報告しました
rejected拒否済み送信前に拒否されました。たとえば受信者が抑制されている、サンドボックスで許可されていない、コンテンツが拒否された、などの場合です
failed失敗72 時間再試行しても配信できなかった、またはキューに入れられませんでした

開封、クリック、配信停止はステータスではありません。これらはメッセージに記録され(opened_at、clicked_at、unsubscribed_at)、Webhook イベントとして送信されます。送信ログでは、開封されたメッセージに 開封済みタグが追加で表示されます。

バウンスの種類

種類発生条件影響
ハード不明なユーザーなどによる恒久的な 5xx 拒否アドレスがグローバル抑制リストに追加されます
ソフトメールボックスの容量超過(x.2.2)、またはシステム、ネットワーク、ポリシーによる拒否(x.3.x〜x.7.x。IP レピュテーションによるブロックなど)アドレスは抑制されません

送信ログ

ストリームの 送信ログタブには、過去 30 日間のメッセージが、日時、受信者、件名、カテゴリ、送信元(API または SMTP)、ステータスとともに一覧表示されます。受信者、ステータス、取得元、カテゴリ、日付範囲で絞り込むことができます。

メッセージをクリックすると メッセージの詳細が開き、ステータス、送信者、件名、カテゴリ、タグ、受信側サーバーの最後の応答、そして各配信試行の SMTP コード、応答、バウンスの種類、MX ホスト、IP を含むイベント一覧が表示されます。

概要タブでは、同じデータを 7 日間または 30 日間で集計して表示します:送信数、配信率、バウンス率、苦情率、開封数、クリック数。

Webhook

Webhook は、各イベントが発生した時点でお客様の HTTPS エンドポイントに送信します。これにより、たとえばハードバウンスの後にユーザーのアドレスを無効としてマークする、といった処理をアプリケーションで行えます。

Webhook を設定する

  1. ストリームを開き、Webhook タブに移動します。
  2. 受信 URLに、インターネットからアクセスできる https:// URL を入力します。プライベートアドレスやローカルアドレスは使用できません。
  3. イベントで、受信するイベントを選択します。既定ではすべてのイベントが選択されています。
  4. 保存をクリックします。初めて URL を保存したときに、署名シークレットが一度だけ表示されます。whsec_ で始まります。サーバー上に保管してください。
  5. テスト送信をクリックして test イベントを送信し、エンドポイントが応答することを確認します。

新しいシークレットを取得するには、署名シークレットをリセットをクリックします。古いシークレットは直ちに無効になります。イベントの受信を停止するには、URL を消去して保存します。

イベント

イベントコンソールの表示送信されるタイミング
delivered配信済み受信側サーバーがメッセージを受け付けたとき
deferred遅延(tarpit)配信試行が一時的に失敗したとき。試行ごとに 1 回送信されます。
bouncedバウンス恒久的な失敗。data.bounce_type は hard または soft です。
complained苦情受信者がメッセージをスパムとして報告したとき
failed失敗72 時間後に配信が断念されたとき
rejected拒否送信サーバーが受信者を拒否したとき
opened開くメッセージが初めて開封されたとき(開封トラッキングが必要)
clickedクリックトラッキング対象のリンクがクリックされるたび(クリックトラッキングが必要)
unsubscribed配信停止受信者が配信を停止したとき

HTTP API 自体が拒否した受信者は API レスポンスの rejected フィールドで返され、Webhook は発生しません。

リクエストの形式

各イベントは、JSON 本文を持つ POST として送信されます。

http
POST /your/webhook HTTP/1.1
Content-Type: application/json
User-Agent: Yeap-TM-Webhook/1
X-Yeap-Signature: t=1760955304,v1=5f2b9c...e81a

{
  "id": "evt_01JAQ40B2C3D4E5F6G7H8J9K0M",
  "type": "bounced",
  "stream_id": 12,
  "message_id": "01JAQ3Z9V8K4M2N6P7R5S1T0XW",
  "created_at": "2026-10-20T10:15:04+00:00",
  "data": {
    "rcpt": "alice@example.org",
    "smtp_code": 550,
    "smtp_response": "5.1.1 The email account that you tried to reach does not exist",
    "bounce_type": "hard",
    "mx": "mx.example.org"
  }
}

id はイベントごとに一意です。重複を無視するために使用してください。data の内容はイベントによって異なります。

イベントdata のフィールド
delivered, deferred, bounced, complained, failed, rejectedrcpt、および利用可能な場合は smtp_code、smtp_response、bounce_type、mx、at
openedrcpt、ip、user_agent
clickedrcpt、url、ip、user_agent
unsubscribedrcpt、category、via
testmessage

署名を検証する

X-Yeap-Signature ヘッダーは t=<timestamp>,v1=<signature> の形式です。署名は、署名シークレット全体(whsec_ を含む)をキーとして <timestamp>.<raw request body> から計算した HMAC-SHA256 の 16 進文字列です。リクエストを確認するには、次の手順に従います。

  1. JSON を解析する前に、受信した生の本文をそのまま読み取ります。
  2. t + "." + body に対して HMAC を計算し、定数時間比較で v1 と比較します。
  3. リプレイ攻撃を防ぐため、タイムスタンプが 5 分より古いリクエストは拒否します。

Python:

python
import hashlib, hmac, time

def verify(secret: str, header: str, body: bytes, tolerance: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    ts, sig = parts.get("t", ""), parts.get("v1", "")
    if not ts.isdigit() or abs(time.time() - int(ts)) > tolerance:
        return False
    expected = hmac.new(secret.encode(), ts.encode() + b"." + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)

Node.js:

javascript
const crypto = require('crypto');

function verify(secret, header, rawBody, tolerance = 300) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const ts = Number(parts.t);
  if (!ts || Math.abs(Date.now() / 1000 - ts) > tolerance) return false;
  const expected = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1 || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

応答と再試行

  • 10 秒以内に任意の 2xx ステータスで応答してください。それ以外はすべて失敗とみなされます。
  • 失敗した送信は、間隔を広げながら再試行されます。間隔は 1 分から始まり、試行間で最大 4 時間まで延びます。再試行はイベント発生から 24 時間後に停止します。
  • イベントは複数回届いたり、順序が前後したりすることがあります。重複のスキップにはイベントの id を、現在の状態の判断にはメッセージのステータスを使用してください。

Webhook タブの 最近の配信表には、直近 100 件の送信が、イベント、ステータス(配信待ち 保留中、成功 成功、再試行中 再試行中、中止 断念)、試行回数、最後のエラー、次回の試行日時とともに表示されます。

関連項目

このページは役に立ちましたか?