postmark-webhooks について
Postmark の Webhook ハンドラーを実装する開発者向けスキルです。メールイベント処理、URL ベースの認証、セキュリティ確認、ローカルテストを扱います。
主な機能
- 01配信、バウンス、開封、クリックイベントの処理
- 02迷惑メール報告と購読変更の処理
- 03URL 資格情報による認証
- 04ペイロード検証とエンドポイント保護
- 05Hookdeck CLI によるローカルテスト
活用シーン
- 01メールの反応と配信状況の追跡
- 02バウンスや苦情後の連絡先更新
- 03配信停止と再登録の処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ hookdeck/ webhook-skills --skill postmark-webhooksインストール後、Claude Code で/postmark-webhooksを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
TODO.mdexamples/express/.env.examplepackage.jsonREADME.mdexamples/express/src/index.jsexamples/express/test/webhook.test.jsexamples/fastapi/.env.examplemain.pyREADME.mdrequirements.txttest_webhook.pyexamples/nextjs/.env.examplepackage.jsonREADME.mdvitest.config.tsexamples/nextjs/app/webhooks/postmark/route.tsexamples/nextjs/test/webhook.test.tsreferences/overview.mdsetup.mdverification.md詳細
Postmark Webhook
このスキルを使用する場面
- メールイベントの追跡に Postmark の Webhook ハンドラーを設定する
- メール配信イベント(バウンス、配信完了、開封、クリック)を処理する
- スパム報告やサブスクリプションの変更に対応する
- メールエンゲージメント分析を実装する
- Webhook 認証の問題をトラブルシューティングする
重要なコード
認証
Postmark は署名検証を使用しません。代わりに、Webhook URL 自体に認証情報を含めて認証します。
// Express - Basic Auth in URL
// Configure webhook URL in Postmark as:
// https://username:[email protected]/webhooks/postmark
app.post('/webhooks/postmark', express.json(), (req, res) => {
// Basic auth is handled by your web server or proxy
// Additional validation can check expected payload structure
const event = req.body;
// Validate expected fields exist
if (!event.RecordType || !event.MessageID) {
return res.status(400).send('Invalid payload structure');
}
// Process event
console.log(`Received ${event.RecordType} event for ${event.Email}`);
res.sendStatus(200);
});
// Alternative: Token in URL
// Configure webhook URL as:
// https://yourdomain.com/webhooks/postmark?token=your-secret-token
app.post('/webhooks/postmark', express.json(), (req, res) => {
const token = req.query.token;
if (token !== process.env.POSTMARK_WEBHOOK_TOKEN) {
return res.status(401).send('Unauthorized');
}
const event = req.body;
console.log(`Received ${event.RecordType} event`);
res.sendStatus(200);
});
複数のイベントの処理
// Postmark sends one event per request (not batched)
app.post('/webhooks/postmark', express.json(), (req, res) => {
const event = req.body;
switch (event.RecordType) {
case 'Bounce':
console.log(`Bounce: ${event.Email} - ${event.Type} - ${event.Description}`);
// Update contact as undeliverable
break;
case 'SpamComplaint':
console.log(`Spam complaint: ${event.Email}`);
// Remove from mailing list
break;
case 'Open':
console.log(`Email opened: ${event.Email} at ${event.ReceivedAt}`);
// Track engagement
break;
case 'Click':
console.log(`Link clicked: ${event.Email} - ${event.OriginalLink}`);
// Track click-through rate
break;
case 'Delivery':
console.log(`Delivered: ${event.Email} at ${event.DeliveredAt}`);
// Confirm delivery
break;
case 'SubscriptionChange':
console.log(`Subscription change: ${event.Email} - ${event.ChangedAt}`);
// Update subscription preferences
break;
case 'Inbound':
console.log(`Inbound email from: ${event.Email} - Subject: ${event.Subject}`);
// Process incoming email
break;
case 'SMTP API Error':
console.log(`SMTP API error: ${event.Email} - ${event.Error}`);
// Handle API error, maybe retry
break;
default:
console.log(`Unknown event type: ${event.RecordType}`);
}
res.sendStatus(200);
});
一般的なイベントタイプ
| イベント | RecordType | 説明 | 主なフィールド |
|---|---|---|---|
| バウンス | Bounce | ハードバウンス/ソフトバウンス、またはメールのブロック | Email、Type、TypeCode、Description |
| スパム報告 | SpamComplaint | 受信者がスパムとして報告 | Email、BouncedAt |
| 開封 | Open | メールが開封された(開封追跡が必要) | Email、ReceivedAt、Platform、UserAgent |
| クリック | Click | リンクがクリックされた(クリック追跡が必要) | Email、ClickedAt、OriginalLink |
| 配信 | Delivery | 配信に成功 | Email、DeliveredAt、Details |
| サブスクリプションの変更 | SubscriptionChange | 配信停止/再登録 | Email、ChangedAt、SuppressionReason |
| 受信 | Inbound | メールを受信 | Email、FromFull、Subject、TextBody、HtmlBody |
| SMTP API エラー | SMTP API Error | SMTP API の呼び出しに失敗 | Email、Error、ErrorCode、MessageID |
環境変数
# For token-based authentication
POSTMARK_WEBHOOK_TOKEN="your-secret-token-here"
# For basic auth (if not using URL-embedded credentials)
WEBHOOK_USERNAME="your-username"
WEBHOOK_PASSWORD="your-password"
セキュリティのベストプラクティス
- 必ず HTTPS を使用する - HTTP URL で Webhook を設定しないでください
- 強力な認証情報を使用する - 長くランダムなトークンまたはパスワードを生成してください
- ペイロードの構造を検証する - 処理の前に想定されるフィールドがあることを確認してください
- IP 許可リストを実装する - Postmark は IP 範囲を公開しています
- Webhook ゲートウェイの利用を検討する - 追加のセキュリティレイヤーを提供する Hookdeck など
ローカル開発
ローカルで Webhook をテストするには、Hookdeck CLI を使用してください。
npx hookdeck-cli listen 3000 postmark --path /webhooks/postmark
アカウントは不要です。ローカルトンネルと、リクエストを検査するための Web UI を利用できます。
リソース
- overview.md - Postmark Webhook の概要と一般的なイベントタイプ
- setup.md - Postmark ダッシュボードでの Webhook 設定
- verification.md - 認証方法とセキュリティのベストプラクティス
- examples/ - Express、Next.js、FastAPI 向けの完全な実装
推奨:webhook-handler-patterns
本番環境に対応した Webhook 処理を実現するには、webhook-handler-patterns スキルもインストールしてください。
関連スキル
- sendgrid-webhooks - ECDSA 検証を使用した SendGrid Webhook の処理
- resend-webhooks - Svix 署名を使用した Resend Webhook の処理
- stripe-webhooks - HMAC-SHA256 を使用した Stripe Webhook の処理
- webhook-handler-patterns - 冪等性、エラー処理、再試行ロジック
- hookdeck-event-gateway - 本番環境向け Webhook インフラストラクチャ
コメント
Markdown 対応