AgentMail — AIエージェント向けメール
AgentMailはAIエージェントにリアルなメールアドレス(@theagentmail.net)を提供し、REST APIで操作できます。エージェントはメールの送受信、サービス(GitHub、AWS、Slackなど)へのサインアップ、確認コードの取得が可能です。カルマシステムによりスパムを防止し、共有ドメインの評判を高く保ちます。
ベースURL: https://api.theagentmail.net
使用すべき場合
- AIエージェントがサインアップ、確認フロー、トランザクションコミュニケーションのために実際の受信箱/送信箱を必要とする場合。
- AgentMailアカウントのプロビジョニング、メッセージ送信、受信箱内容の読み取り、インバウンドWebhookの登録が必要な場合。
- カルマ使用量の監視やメールイベントをエージェント自動化に組み込む必要がある場合。
クイックスタート
全てのリクエストにはAuthorization: Bearer am_...ヘッダー(ダッシュボードから取得したAPIキー)が必要です。
メールアカウントを作成する(-10カルマ)
curl -X POST https://api.theagentmail.net/v1/accounts \
-H "Authorization: Bearer am_..." \
-H "Content-Type: application/json" \
-d '{"address": "[email protected]"}'
レスポンス: {"data": {"id": "...", "address": "[email protected]", "displayName": null, "createdAt": 123}}
メールを送信する(-1カルマ)
curl -X POST https://api.theagentmail.net/v1/accounts/{accountId}/messages \
-H "Authorization: Bearer am_..." \
-H "Content-Type: application/json" \
-d '{
"to": ["[email protected]"],
"subject": "こんにちは、エージェントからです",
"text": "プレーンテキスト本文",
"html": "<p>オプションのHTML本文</p>"
}'
オプションフィールド: cc, bcc(文字列配列)、inReplyTo, references(スレッド化用の文字列)、attachments({filename, contentType, content}の配列、contentはbase64)。
受信箱を読む
# メッセージ一覧
curl https://api.theagentmail.net/v1/accounts/{accountId}/messages \
-H "Authorization: Bearer am_..."
# フルメッセージ(本文と添付ファイル付き)を取得
curl https://api.theagentmail.net/v1/accounts/{accountId}/messages/{messageId} \
-H "Authorization: Bearer am_..."
カルマを確認する
curl https://api.theagentmail.net/v1/karma \
-H "Authorization: Bearer am_..."
レスポンス: {"data": {"balance": 90, "events": [...]}}
Webhookを登録する(リアルタイムインバウンド)
curl -X POST https://api.theagentmail.net/v1/accounts/{accountId}/webhooks \
-H "Authorization: Bearer am_..." \
-H "Content-Type: application/json" \
-d '{"url": "https://my-agent.example.com/inbox"}'
Webhook配信には2つのセキュリティヘッダーが含まれます:
X-AgentMail-Signature-- リクエストボディのHMAC-SHA256 hexダイジェスト。Webhookシークレットで署名されています。X-AgentMail-Timestamp-- 配信が送信された時刻のミリ秒タイムスタンプ。
署名を検証し、5分以上経過したタイムスタンプのリクエストを拒否してリプレイ攻撃を防ぎます:
import { createHmac } from "crypto";
const verifyWebhook = (body: string, signature: string, timestamp: string, secret: string) => {
if (Date.now() - Number(timestamp) > 5 * 60 * 1000) return false;
return createHmac("sha256", secret).update(body).digest("hex") === signature;
};
添付ファイルをダウンロードする
curl https://api.theagentmail.net/v1/accounts/{accountId}/messages/{messageId}/attachments/{attachmentId} \
-H "Authorization: Bearer am_..."
レスポンス: {"data": {"url": "https://signed-download-url..."}}
完全なAPIリファレンス
| メソッド | パス | 説明 | カルマ |
|---|---|---|---|
| POST | /v1/accounts | メールアカウントを作成 | -10 |
| GET | /v1/accounts | 全てのアカウントを一覧表示 | |
| GET | /v1/accounts/:id | アカウントの詳細を取得 | |
| DELETE | /v1/accounts/:id | アカウントを削除 | +10 |
| POST | /v1/accounts/:id/messages | メールを送信 | -1 |
| GET | /v1/accounts/:id/messages | メッセージを一覧表示 | |
| GET | /v1/accounts/:id/messages/:msgId | フルメッセージを取得 | |
| GET | /v1/accounts/:id/messages/:msgId/attachments/:attId | 添付ファイルURLを取得 | |
| POST | /v1/accounts/:id/webhooks | Webhookを登録 | |
| GET | /v1/accounts/:id/webhooks | Webhookを一覧表示 | |
| DELETE | /v1/accounts/:id/webhooks/:whId | Webhookを削除 | |
| GET | /v1/karma | 残高とイベントを取得 |
カルマシステム
全てのアクションにはカルマのコストまたは報酬があります:
| イベント | カルマ | 理由 |
|---|---|---|
money_paid | +100 | クレジットを購入 |
email_received | +2 | 信頼できるドメインから返信があった |
account_deleted | +10 | アドレス削除時にカルマ返金 |
email_sent | -1 | 送信にカルマ消費 |
account_created | -10 | アドレス作成にカルマ消費 |
重要なルール:
- カルマは信頼できるプロバイダー(Gmail、Outlook、Yahoo、iCloud、ProtonMail、Fastmail、Heyなど)からのインバウンドメールに対してのみ付与されます。不明または使い捨てドメインからのメールではカルマは得られません。
- エージェントが返信するまで、送信者1人につき1回のみカルマが獲得できます。送信者Xが返信なしで5回メールを送ってきても、最初の1回のみカルマが付与されます。Xに返信すると、次のXからのメールで再びカルマが獲得できます。
- アカウントを削除すると、作成時に消費した10カルマが返金されます。
カルマが0になると、送信とアカウント作成はHTTP 402を返します。カルマを消費する操作の前には必ず残高を確認してください。
TypeScript SDK
import { createClient } from "@agentmail/sdk";
const mail = createClient({ apiKey: "am_..." });
// アカウントを作成
const account = await mail.accounts.create({
address: "[email protected]",
});
// メールを送信
await mail.messages.send(account.id, {
to: ["[email protected]"],
subject: "こんにちは",
text: "AIエージェントから送信されました。",
});
// 受信箱を読む
const messages = await mail.messages.list(account.id);
const detail = await mail.messages.get(account.id, messages[0].id);
// 添付ファイル
const att = await mail.attachments.getUrl(accountId, messageId, attachmentId);
// att.url は署名付きダウンロードURL
// Webhook
await mail.webhooks.create(account.id, {
url: "https://my-agent.example.com/inbox",
});
// カルマ
const karma = await mail.karma.getBalance();
console.log(karma.balance);
エラーハンドリング
import { AgentMailError } from "@agentmail/sdk";
try {
await mail.messages.send(accountId, { to: ["[email protected]"], subject: "Hi", text: "Hey" });
} catch (e) {
if (e instanceof AgentMailError) {
console.log(e.status); // 402, 404, 401 など
console.log(e.code); // "INSUFFICIENT_KARMA", "NOT_FOUND" など
console.log(e.message);
}
}
一般的なパターン
サービスにサインアップし、確認メールを読む
const account = await mail.accounts.create({
address: "[email protected]",
});
// このアドレスを使ってサインアップ(ブラウザ自動化、APIなど)
// 確認メールをポーリング
for (let i = 0; i < 30; i++) {
const messages = await mail.messages.list(account.id);
const verification = messages.find(m =>
m.subject.toLowerCase().includes("verify") ||
m.subject.toLowerCase().includes("confirm")
);
if (verification) {
const detail = await mail.messages.get(account.id, verification.id);
// detail.bodyText または detail.bodyHtml から確認リンク/コードを解析
break;
}
await new Promise(r => setTimeout(r, 2000));
}
メールを送信し、返信を待つ
const sent = await mail.messages.send(account.id, {
to: ["[email protected]"],
subject: "注文#12345に関する質問",
text: "ステータスを確認していただけますか?",
});
for (let i = 0; i < 60; i++) {
const messages = await mail.messages.list(account.id);
const reply = messages.find(m =>
m.direction === "inbound" && m.timestamp > sent.timestamp
);
if (reply) {
const detail = await mail.messages.get(account.id, reply.id);
// 返信を処理
break;
}
await new Promise(r => setTimeout(r, 5000));
}
型定義
type Account = { id: string; address: string; displayName: string | null; createdAt: number };
type Message = { id: string; from: string; to: string[]; subject: string; direction: "inbound" | "outbound"; status: string; timestamp: number };
type MessageDetail = Message & { cc: string[] | null; bcc: string[] | null; bodyText: string | null; bodyHtml: string | null; inReplyTo: string | null; references: string | null; attachments: AttachmentMeta[] };
type AttachmentMeta = { id: string; filename: string; contentType: string; size: number };
type KarmaBalance = { balance: number; events: KarmaEvent[] };
type KarmaEvent = { id: string; type: string; amount: number; timestamp: number; metadata?: Record<string, unknown> };
制限事項
- このスキルは、タスクが上記の範囲に明確に合致する場合にのみ使用してください。
- 出力を環境固有の検証、テスト、専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全境界、成功基準が不足している場合は、停止して明確化を求めてください。