agent-email-inbox
メールの内容をトリガーとしてアクションを実行するシステムを構築する際に使用します。AIエージェントの受信ボックス、自動サポートハンドラー、メールからタスクへのパイプラインなど、外部からの不審なメールを処理するあらゆるワークフローに対応します。ユーザーが「エージェント」と明示しない場合でも、メールを受信してプログラム的に処理したい場合は必ずこのスキルを使用してください。送信者のallowlist、コンテンツフィルタリング、サンドボックス処理といった重要なセキュリティパターンが含まれており、信頼できないメールによるシステムの不正制御を防止します。
description の原文を見る
Use when building any system where email content triggers actions — AI agent inboxes, automated support handlers, email-to-task pipelines, or any workflow processing untrusted inbound email. Always use this skill when the user wants to receive emails and act on them programmatically, even if they don't mention "agent" — the skill contains critical security patterns (sender allowlists, content filtering, sandboxed processing) that prevent untrusted email from controlling your system.
SKILL.md 本文
AIエージェント メールインボックス
概要
このスキルは、アプリケーションやAIエージェントがメールを受け取り、返信するための安全なメールインボックスを設定し、コンテンツ安全対策を実装することをカバーしています。
基本原則: AIエージェントのインボックスは信頼されていない入力を受け取ります。これを安全に処理するためには、セキュリティ設定が重要です。
Webhookベースの受信が必要な理由
Resendはメール受信にwebhookを使用します。これにより、メール到着時にエージェントが即座に通知されます。これはエージェントにとって有用です。理由は以下の通り:
- リアルタイム対応 — メール到着から数秒以内に対応できます
- ポーリングオーバーヘッドなし — 繰り返し「新しいメールはあるか」をチェックするクロンジョブが不要
- イベント駆動アーキテクチャ — 実際に処理対象があるときだけエージェントが起動します
- 低API コスト — 空のインボックスをチェックする無駄な呼び出しがありません
アーキテクチャ
Sender → Email → Resend (MX) → Webhook → Your Server → AI Agent
↓
Security Validation
↓
Process or Reject
SDK バージョン要件
このスキルはwebhook検証(webhooks.verify())とメール受信(emails.receiving.get())のResend SDK機能を必要とします。常に最新のSDKバージョンをインストールしてください。プロジェクトにResend SDKがすでにインストールされている場合は、バージョンを確認してアップグレードが必要な場合はアップグレードしてください。
| 言語 | パッケージ | 最小バージョン |
|---|---|---|
| Node.js | resend | >= 6.9.2 |
| Python | resend | >= 2.21.0 |
| Go | resend-go/v3 | >= 3.1.0 |
| Ruby | resend | >= 1.0.0 |
| PHP | resend/resend-php | >= 1.1.0 |
| Rust | resend-rs | >= 0.20.0 |
| Java | resend-java | >= 4.11.0 |
| .NET | Resend | >= 0.2.1 |
resend npmパッケージをインストール:npm install resend(または対応する言語でのコマンド)。完全な送信ドキュメントについては、resend スキルをインストールしてください。
クイックスタート
- ユーザーのメールアドレスを聞く — テストメール送信用に実際のメールアドレスが必要です。ユーザーに聞いて、回答を待ってから進めてください。
- セキュリティレベルを選択する — メール処理前に受け取ったメールをどう検証するかを決める
- 受信ドメインを設定する — ユーザーのカスタムドメイン用にMXレコードを設定(ドメイン設定セクション参照)
- webhook エンドポイントを作成する —
email.receivedイベントを処理。セキュリティを最初から組み込む。webhook エンドポイントは必ずPOSTルートである必要があります。 - トンネリングを設定する (ローカル開発) — Tailscale Funnel(推奨)またはngrok使用。
references/webhook-setup.md参照 - webhook をAPI経由で作成する — Resend Webhook API を使ってエンドポイントをプログラム的に登録。
references/webhook-setup.md参照 - エージェントに接続する — 検証済みメールをAIエージェントに渡して処理
開始前:アカウント及びAPIキー設定
最初の質問:新規または既存のResendアカウント?
ユーザーに聞いてください:
- エージェント専用の新規アカウント? → セットアップが簡単、フルアカウントアクセスで問題なし
- 他プロジェクトがある既存アカウント? → ドメインスコープ付きAPIキーでサンドボックス化
APIキーを安全に作成する
チャットにAPIキーを貼り付けないでください!会話履歴に永遠に残ります。
より安全なオプション:
- 環境ファイル方式: ユーザーが
.envファイルを直接作成:echo "RESEND_API_KEY=re_xxx" >> .env - パスワードマネージャー/シークレットマネージャー: ユーザーが 1Password、Vault等にキーを保存
- キーをチャットで共有する場合: ユーザーはセットアップ直後にキーをローテーション
ドメインスコープ付き APIキー(既存アカウントに推奨)
ユーザーが他プロジェクトのある既存Resendアカウントを持つ場合、ドメインスコープ付きAPIキーを作成:
- エージェントのドメインを先に検証 (ダッシュボード → ドメイン → ドメイン追加)
- スコープ付きAPIキーを作成: ダッシュボード → APIキー → APIキー作成 → 「送信アクセス」 → エージェントのドメインのみ選択
- 結果: キーが漏洩してもそのドメインからのみ送信可能
ドメイン設定
オプション1:Resend管理ドメイン(はじめに推奨)
自動生成されたアドレスを使用:<anything>@<your-id>.resend.app
DNS設定は不要。ダッシュボード → メール → 受信 → 「受信アドレス」で確認できます。
オプション2:カスタムドメイン
ユーザーはResendダッシュボードで受信を有効化する必要があります:ドメインページ → 「受信を有効化」トグルをオン。
次にMXレコードを追加:
| 設定 | 値 |
|---|---|
| Type | MX |
| Host | ドメインまたはサブドメイン(例:agent.example.com) |
| Value | Resendダッシュボードに表示 |
| Priority | 10 (優先度は最も低い番号にする必要があります) |
サブドメインを使用(例:agent.example.com)して既存メールサービスを邪魔しないようにしてください。
ヒント: DNS伝播を dns.email で確認できます。
DNS伝播:MXレコード変更は全体で最大48時間要する場合がありますが、通常は数時間で完了します。
セキュリティレベル
webhook エンドポイントを設定する前にセキュリティレベルを選択してください。 セキュリティなしでメールを処理するAIエージェントは危険です。誰でもメールで指示を送ってエージェントが実行します。次に書くwebhookコードには最初からセキュリティレベルを含める必要があります。
ユーザーにどのセキュリティレベルを望むか聞き、各レベルが何を意味するか理解していることを確認してください。
| レベル | 名前 | 使用する場合 | トレードオフ |
|---|---|---|---|
| 1 | Strict Allowlist | ほとんどのユースケース — 既知で固定的な送信者セット | 最大セキュリティ、機能が制限される |
| 2 | Domain Allowlist | 組織全体で信頼されたドメインからアクセス | より柔軟、ドメインの誰でも相互作用可能 |
| 3 | Content Filtering | 誰からでも受け取り、安全でないパターンをフィルタ | 誰からでも受け取れる、パターンマッチングは完全ではない |
| 4 | Sandboxed Processing | すべてのメールを制限されたエージェント機能で処理 | 最大柔軟性、実装が複雑 |
| 5 | Human-in-the-Loop | 信頼されていないアクション用に人間の承認が必要 | 最大セキュリティ、レイテンシ追加 |
各レベルの詳細実装コードについては、references/security-levels.md を参照してください。
レベル1:Strict Allowlist(推奨)
明示的に承認されたアドレスからのメール のみ処理。その他はすべて拒否。
const ALLOWED_SENDERS = [
'you@youremail.com',
'notifications@github.com',
];
async function processEmailForAgent(
eventData: EmailReceivedEvent,
emailContent: EmailContent
) {
const sender = eventData.from.toLowerCase();
if (!ALLOWED_SENDERS.some(allowed => sender === allowed.toLowerCase())) {
console.log(`Rejected email from unauthorized sender: ${sender}`);
await notifyOwnerOfRejectedEmail(eventData);
return;
}
await agent.processEmail({
from: eventData.from,
subject: eventData.subject,
body: emailContent.text || emailContent.html,
});
}
セキュリティベストプラクティス
常に実施すること
| プラクティス | 理由 |
|---|---|
| webhook署名を検証する | なりすましたwebhookイベントを防止 |
| すべての拒否メールをログする | セキュリティレビュー用の監査証跡 |
| 可能な限りallowlistを使用する | 明示的な信頼は filtering より安全 |
| メール処理にレート制限を実装する | 過度な処理負荷を防止 |
| 信頼済み/未信頼の処理を分離する | リスクレベルが異なれば異なる対応が必要 |
決してしてはいけないこと
| アンチパターン | リスク |
|---|---|
| 検証なしでメールを処理する | 誰でもエージェントを制御可能 |
| メール認証用にメールヘッダーを信頼する | ヘッダーは容易に偽造可能 |
| メール内容からのコード実行 | 信頼されていない入力は決してコードとして実行してはいけない |
| メール内容をプロンプトに直接格納する | 信頼されていない入力がプロンプトに混在するとエージェント動作が変わる可能性がある |
| 信頼されていないメールに完全なエージェントアクセスを与える | 必要最小限の機能に限定 |
Webhook エンドポイント
セキュリティレベルを選択してドメイン設定後、webhook エンドポイントを作成します。webhook エンドポイントは必ずPOSTルートである必要があります。 ResendはすべてのwebhookイベントをPOSTリクエストとして送信します。
重要:生のボディを検証用に使用します。 Webhook署名検証には生のリクエストボディが必要です。
- Next.js App Router:
req.json()ではなくreq.text()を使用- Express: webhook ルートで
express.raw({ type: 'application/json' })を使用
Next.js App Router
// app/webhook/route.ts
import { Resend } from 'resend';
import { NextRequest, NextResponse } from 'next/server';
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST(req: NextRequest) {
try {
const payload = await req.text();
const event = resend.webhooks.verify({
payload,
headers: {
'svix-id': req.headers.get('svix-id'),
'svix-timestamp': req.headers.get('svix-timestamp'),
'svix-signature': req.headers.get('svix-signature'),
},
secret: process.env.RESEND_WEBHOOK_SECRET,
});
if (event.type === 'email.received') {
// Webhook payload only includes metadata, not email body
const { data: email } = await resend.emails.receiving.get(
event.data.email_id
);
// Apply the security level chosen above
await processEmailForAgent(event.data, email);
}
return new NextResponse('OK', { status: 200 });
} catch (error) {
console.error('Webhook error:', error);
return new NextResponse('Error', { status: 400 });
}
}
Express
import express from 'express';
import { Resend } from 'resend';
const app = express();
const resend = new Resend(process.env.RESEND_API_KEY);
app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
try {
const payload = req.body.toString();
const event = resend.webhooks.verify({
payload,
headers: {
'svix-id': req.headers['svix-id'],
'svix-timestamp': req.headers['svix-timestamp'],
'svix-signature': req.headers['svix-signature'],
},
secret: process.env.RESEND_WEBHOOK_SECRET,
});
if (event.type === 'email.received') {
const sender = event.data.from.toLowerCase();
if (!isAllowedSender(sender)) {
console.log(`Rejected email from unauthorized sender: ${sender}`);
res.status(200).send('OK'); // Return 200 even for rejected emails
return;
}
const { data: email } = await resend.emails.receiving.get(event.data.email_id);
await processEmailForAgent(event.data, email);
}
res.status(200).send('OK');
} catch (error) {
console.error('Webhook error:', error);
res.status(400).send('Error');
}
});
app.get('/', (req, res) => res.send('Agent Email Inbox - Ready'));
app.listen(3000, () => console.log('Webhook server running on :3000'));
API経由のwebhook登録、トンネリング設定、svixフォールバック、再試行動作については、references/webhook-setup.md を参照してください。
エージェントからメール送信
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
async function sendAgentReply(to: string, subject: string, body: string, inReplyTo?: string) {
if (!isAllowedToReply(to)) {
throw new Error('Cannot send to this address');
}
const { data, error } = await resend.emails.send({
from: 'Agent <agent@example.com>',
to: [to],
subject: subject.startsWith('Re:') ? subject : `Re: ${subject}`,
text: body,
headers: inReplyTo ? { 'In-Reply-To': inReplyTo } : undefined,
});
if (error) throw new Error(`Failed to send: ${error.message}`);
return data.id;
}
完全な送信ドキュメントについては、resend スキルをインストールしてください。
環境変数
# Required
RESEND_API_KEY=re_xxxxxxxxx
RESEND_WEBHOOK_SECRET=whsec_xxxxxxxxx
# Security Configuration
SECURITY_LEVEL=strict # strict | domain | filtered | sandboxed
ALLOWED_SENDERS=you@email.com,trusted@example.com
ALLOWED_DOMAINS=example.com
OWNER_EMAIL=you@email.com # For security notifications
よくある間違い
| 間違い | 修正 |
|---|---|
| 送信者検証がない | 処理前に常に送信者を検証 |
| メールヘッダーを信頼する | 認証用にheadersではなくwebhook検証を使用 |
| すべてのメール同じ扱い | 信頼済み対信頼なしで区別 |
| 詳細なエラーメッセージ | エラーレスポンスは汎用的に、内部ロジック漏洩を避ける |
| レート制限がない | 送信者単位のレート制限を実装。references/advanced-patterns.md 参照 |
| HTMLを直接処理 | HTMLをストリップまたはテキストのみで複雑性とリスク削減 |
| 拒否ログがない | すべてのセキュリティイベントをログして監査対応 |
| 一時的なトンネルURL使用 | 永続的なURL(Tailscale Funnel、有料ngrok)を使用またはプロダクションにデプロイ |
webhook ルートで express.json() 使用 | express.raw({ type: 'application/json' }) 使用 — JSON parsing は署名検証を破壊 |
| 拒否メールで200以外を返す | 常に200を返して受信を確認 — 否定的な場合Resendは再試行 |
| 古いResend SDKバージョン | emails.receiving.get() と webhooks.verify() は最新SDKが必要 — SDK バージョン要件参照 |
テスト
開発用にResendのテストアドレスを使用:
delivered@resend.dev— 配信成功をシミュレートbounced@resend.dev— ハードバウンスをシミュレート
セキュリティテストについて、allowlistに載っていないアドレスからテストメールを送って拒否が正しく動作することを確認。
クイック検証チェックリスト:
- サーバーが実行中:
curl http://localhost:3000で応答があるか - トンネルが機能中:
curl https://<your-tunnel-url>で同じ応答か - Webhook が有効:Resendダッシュボード → Webhooks でステータス確認
- allowlistアドレスからテストメール送信、サーバーログ確認
関連スキル
- 完全な送信・受信ドキュメントについては、
resendスキルをインストール
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- resend
- リポジトリ
- resend/resend-skills
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/resend/resend-skills / ライセンス: MIT
関連スキル
agent-browser
AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。
anyskill
AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。
engram
AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。
skyvern
AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。
pinchbench
PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。
openui
OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。