agentmail-sdk
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAgentMail SDK
AgentMail SDK
AgentMail is an API-first email platform built for AI agents. Unlike transactional email APIs (Resend, SendGrid) that focus on one-way sending, AgentMail provides full two-way email inboxes that agents can create, send from, receive into, and manage programmatically.
Key capabilities:
- Instant inbox creation (milliseconds, no domain setup needed)
- Two-way conversations with native thread management
- Reply extraction () strips quoted history automatically
extracted_text - WebSocket and webhook support for real-time inbound
- Human-in-the-loop drafts for agent oversight
- Multi-tenant isolation with pods
- Allow/block lists for sender filtering
- IMAP and SMTP access for legacy integrations
AgentMail是专为AI Agent打造的API优先邮件平台。与专注于单向发送的事务性邮件API(如Resend、SendGrid)不同,AgentMail提供完整的双向邮箱,支持Agent程序化创建、发送、接收及管理邮件。
核心功能:
- 即时创建邮箱(毫秒级,无需域名配置)
- 支持双向对话及原生线程管理
- 回复提取()自动去除引用历史
extracted_text - 支持WebSocket与Webhook实现实时收件通知
- 支持人工介入审核的草稿功能
- 通过Pods实现多租户隔离
- 允许/阻止列表用于发件人过滤
- 支持IMAP与SMTP接入以兼容遗留系统
Installation and setup
安装与配置
bash
undefinedbash
undefinedPython
Python
pip install agentmail
pip install agentmail
TypeScript / Node.js
TypeScript / Node.js
npm install agentmail
Get your API key from https://console.agentmail.to/ or via the Agent sign-up API (see below).
**Python:**
```python
from agentmail import AgentMail
client = AgentMail(api_key="YOUR_API_KEY")npm install agentmail
从https://console.agentmail.to/ 或通过Agent注册API获取您的API密钥(见下文)。
**Python:**
```python
from agentmail import AgentMail
client = AgentMail(api_key="YOUR_API_KEY")Or set AGENTMAIL_API_KEY env var and omit api_key:
或设置AGENTMAIL_API_KEY环境变量,无需传入api_key参数:
client = AgentMail()
client = AgentMail()
**TypeScript:**
```typescript
import { AgentMailClient } from "agentmail";
const client = new AgentMailClient({ apiKey: "YOUR_API_KEY" });
**TypeScript:**
```typescript
import { AgentMailClient } from "agentmail";
const client = new AgentMailClient({ apiKey: "YOUR_API_KEY" });Agent sign-up (programmatic, no console needed)
Agent注册(程序化,无需控制台)
Create an account and get an API key entirely from code. No browser required.
Requires(Python) /agentmail>=0.4.15(TypeScript). If your installed SDK raisesagentmail>=0.x, upgrade first.AttributeError: 'AgentMail' object has no attribute 'agent'
python
client = AgentMail() # no api_key needed for sign-up
response = client.agent.sign_up(
human_email="you@example.com",
username="my-agent",
)完全通过代码创建账户并获取API密钥,无需浏览器。
要求(Python版)/agentmail>=0.4.15(TypeScript版)。若您安装的SDK提示agentmail>=0.x,请先升级。AttributeError: 'AgentMail' object has no attribute 'agent'
python
client = AgentMail() # 注册无需传入api_key
response = client.agent.sign_up(
human_email="you@example.com",
username="my-agent",
)response.api_key -> store this securely
response.api_key -> 请安全存储
response.inbox_id -> my-agent@agentmail.to
response.inbox_id -> my-agent@agentmail.to
response.organization_id
response.organization_id
Verify with OTP sent to your email
使用发送至您邮箱的OTP验证码完成验证
client = AgentMail(api_key=response.api_key)
client.agent.verify(otp_code="123456")
```typescript
const client = new AgentMailClient();
const response = await client.agent.signUp({
humanEmail: "you@example.com",
username: "my-agent",
});
// response.apiKey, response.inboxId, response.organizationId
const authedClient = new AgentMailClient({ apiKey: response.apiKey });
await authedClient.agent.verify({ otpCode: "123456" });The sign-up endpoint is idempotent: calling again with the same email rotates the API key and resends the OTP.
client = AgentMail(api_key=response.api_key)
client.agent.verify(otp_code="123456")
```typescript
const client = new AgentMailClient();
const response = await client.agent.signUp({
humanEmail: "you@example.com",
username: "my-agent",
});
// response.apiKey, response.inboxId, response.organizationId
const authedClient = new AgentMailClient({ apiKey: response.apiKey });
await authedClient.agent.verify({ otpCode: "123456" });注册接口具有幂等性:使用同一邮箱再次调用会轮换API密钥并重发OTP验证码。
Inboxes
邮箱管理
Create scalable inboxes on-demand. Each inbox has a unique email address. No domain verification needed for .
@agentmail.topython
from agentmail.inboxes.types import CreateInboxRequest按需创建可扩展的邮箱,每个邮箱拥有唯一的邮件地址。使用域名无需验证。
@agentmail.topython
from agentmail.inboxes.types import CreateInboxRequestCreate inbox (auto-generated address)
创建邮箱(自动生成地址)
inbox = client.inboxes.create()
inbox = client.inboxes.create()
inbox.inbox_id, inbox.email
inbox.inbox_id, inbox.email
Create with options. All create kwargs go inside a CreateInboxRequest.
带选项创建,所有创建参数需放入CreateInboxRequest对象中
inbox = client.inboxes.create(
request=CreateInboxRequest(
username="support",
domain="yourdomain.com", # optional, defaults to agentmail.to
display_name="Support Agent",
client_id="support-v1", # idempotency key, safe to retry
),
)
inbox = client.inboxes.create(
request=CreateInboxRequest(
username="support",
domain="yourdomain.com", # 可选,默认值为agentmail.to
display_name="Support Agent",
client_id="support-v1", # 幂等键,可安全重试
),
)
List all inboxes
列出所有邮箱
inboxes = client.inboxes.list()
inboxes = client.inboxes.list()
Paginate: client.inboxes.list(limit=20, page_token=inboxes.next_page_token)
分页查询:client.inboxes.list(limit=20, page_token=inboxes.next_page_token)
Get, update, delete
获取、更新、删除邮箱
inbox = client.inboxes.get(inbox_id="support@agentmail.to")
client.inboxes.update(inbox_id="support@agentmail.to", display_name="New Name")
client.inboxes.delete(inbox_id="support@agentmail.to")
```typescript
const inbox = await client.inboxes.create({
username: "support",
domain: "yourdomain.com",
displayName: "Support Agent",
clientId: "support-v1",
});
const inboxes = await client.inboxes.list();
const fetched = await client.inboxes.get("support@agentmail.to");
await client.inboxes.update("support@agentmail.to", { displayName: "New Name" });
await client.inboxes.delete("support@agentmail.to");Custom domains require a paid plan. Default inboxes are free.
@agentmail.toinbox = client.inboxes.get(inbox_id="support@agentmail.to")
client.inboxes.update(inbox_id="support@agentmail.to", display_name="New Name")
client.inboxes.delete(inbox_id="support@agentmail.to")
```typescript
const inbox = await client.inboxes.create({
username: "support",
domain: "yourdomain.com",
displayName: "Support Agent",
clientId: "support-v1",
});
const inboxes = await client.inboxes.list();
const fetched = await client.inboxes.get("support@agentmail.to");
await client.inboxes.update("support@agentmail.to", { displayName: "New Name" });
await client.inboxes.delete("support@agentmail.to");自定义域名需付费套餐,默认邮箱免费使用。
@agentmail.toMessages
邮件管理
Send
发送邮件
Always provide both and for best deliverability. Maximum 50 recipients across to + cc + bcc combined.
texthtmlpython
sent = client.inboxes.messages.send(
inbox_id="agent@agentmail.to",
to="recipient@example.com", # string or list
subject="Hello from AgentMail",
text="Plain text body",
html="<p>HTML body</p>", # optional but recommended
cc="cc@example.com", # optional, string or list
bcc="bcc@example.com", # optional, string or list
reply_to="replies@example.com", # optional
labels=["outreach"], # optional
attachments=[{ # optional
"filename": "report.pdf",
"content": base64_content, # Base64-encoded
"content_type": "application/pdf",
}],
)为确保最佳投递率,请同时提供和内容。收件人总数(to + cc + bcc)最多50个。
texthtmlpython
sent = client.inboxes.messages.send(
inbox_id="agent@agentmail.to",
to="recipient@example.com", # 字符串或列表
subject="Hello from AgentMail",
text="Plain text body",
html="<p>HTML body</p>", # 可选但推荐提供
cc="cc@example.com", # 可选,字符串或列表
bcc="bcc@example.com", # 可选,字符串或列表
reply_to="replies@example.com", # 可选
labels=["outreach"], # 可选
attachments=[{ # 可选
"filename": "report.pdf",
"content": base64_content, # Base64编码内容
"content_type": "application/pdf",
}],
)sent.message_id, sent.thread_id
sent.message_id, sent.thread_id
```typescript
const sent = await client.inboxes.messages.send("agent@agentmail.to", {
to: "recipient@example.com",
subject: "Hello from AgentMail",
text: "Plain text body",
html: "<p>HTML body</p>",
cc: "cc@example.com",
labels: ["outreach"],
attachments: [{
filename: "report.pdf",
content: base64Content,
contentType: "application/pdf",
}],
});
```typescript
const sent = await client.inboxes.messages.send("agent@agentmail.to", {
to: "recipient@example.com",
subject: "Hello from AgentMail",
text: "Plain text body",
html: "<p>HTML body</p>",
cc: "cc@example.com",
labels: ["outreach"],
attachments: [{
filename: "report.pdf",
content: base64Content,
contentType: "application/pdf",
}],
});List and get
列出与获取邮件
python
undefinedpython
undefinedList messages in an inbox. Note: .list() returns MessageItem objects
列出邮箱中的邮件。注意:.list()返回MessageItem对象
(metadata only — subject, from, labels, timestamps, etc.) with NO body
仅包含元数据——主题、发件人、标签、时间戳等,不包含邮件正文
content. To read .text / .html / .extracted_text you must fetch the full
如需读取.text / .html / .extracted_text内容,需调用.get()获取完整邮件
message with .get().
—
response = client.inboxes.messages.list(
inbox_id="agent@agentmail.to",
limit=10, # optional, default varies
labels=["unread"], # optional, filter by label
)
for item in response.messages:
# item is a MessageItem (metadata only). Fetch the full Message for body:
msg = client.inboxes.messages.get(
inbox_id=item.inbox_id,
message_id=item.message_id,
)
# Use extracted_text for reply content without quoted history
content = msg.extracted_text or msg.text
print(msg.subject, content)
response = client.inboxes.messages.list(
inbox_id="agent@agentmail.to",
limit=10, # 可选,默认值不定
labels=["unread"], # 可选,按标签过滤
)
for item in response.messages:
# item为MessageItem(仅元数据),需获取完整Message对象以读取正文
msg = client.inboxes.messages.get(
inbox_id=item.inbox_id,
message_id=item.message_id,
)
# 使用extracted_text获取去除引用历史的回复内容
content = msg.extracted_text or msg.text
print(msg.subject, content)
Paginate
分页查询
while response.next_page_token:
response = client.inboxes.messages.list(
inbox_id="agent@agentmail.to",
page_token=response.next_page_token,
)
while response.next_page_token:
response = client.inboxes.messages.list(
inbox_id="agent@agentmail.to",
page_token=response.next_page_token,
)
Get a specific message
获取指定邮件
msg = client.inboxes.messages.get(
inbox_id="agent@agentmail.to",
message_id="abc123@agentmail.to",
)
msg = client.inboxes.messages.get(
inbox_id="agent@agentmail.to",
message_id="abc123@agentmail.to",
)
Get raw MIME content
获取原始MIME内容
raw = client.inboxes.messages.get_raw(
inbox_id="agent@agentmail.to",
message_id="abc123@agentmail.to",
)
```typescript
const response = await client.inboxes.messages.list("agent@agentmail.to", {
limit: 10,
labels: ["unread"],
});
const msg = await client.inboxes.messages.get(
"agent@agentmail.to",
"<abc123@agentmail.to>",
);Important: when processing inbound replies, always use / instead of / . These fields strip quoted history and signatures, giving you only the new content. This is powered by Talon reply extraction.
extracted_textextracted_htmltexthtmlAlso note: some email clients (Gmail, Outlook) send forwards as HTML-only. Always treat as the primary content source and as optional.
htmltextraw = client.inboxes.messages.get_raw(
inbox_id="agent@agentmail.to",
message_id="abc123@agentmail.to",
)
```typescript
const response = await client.inboxes.messages.list("agent@agentmail.to", {
limit: 10,
labels: ["unread"],
});
const msg = await client.inboxes.messages.get(
"agent@agentmail.to",
"<abc123@agentmail.to>",
);重要提示:处理收件回复时,请始终使用 / 而非 / 。这些字段会自动去除引用历史和签名,仅保留新增内容,由Talon回复提取技术提供支持。
extracted_textextracted_htmltexthtml此外注意:部分邮件客户端(如Gmail、Outlook)仅以HTML格式发送转发邮件,请始终将视为主要内容源,作为可选内容。
htmltextReply
回复邮件
Replying adds the message to the existing thread.
python
reply = client.inboxes.messages.reply(
inbox_id="agent@agentmail.to",
message_id="<abc123@agentmail.to>",
text="Thanks for your email!",
html="<p>Thanks for your email!</p>", # optional
attachments=[...], # optional
reply_all=False, # optional, defaults to False
)typescript
const reply = await client.inboxes.messages.reply(
"agent@agentmail.to",
"<abc123@agentmail.to>",
{ text: "Thanks for your email!" },
);回复会将邮件添加至现有对话线程。
python
reply = client.inboxes.messages.reply(
inbox_id="agent@agentmail.to",
message_id="<abc123@agentmail.to>",
text="Thanks for your email!",
html="<p>Thanks for your email!</p>", # 可选
attachments=[...], # 可选
reply_all=False, # 可选,默认值为False
)typescript
const reply = await client.inboxes.messages.reply(
"agent@agentmail.to",
"<abc123@agentmail.to>",
{ text: "Thanks for your email!" },
);Forward
转发邮件
python
client.inboxes.messages.forward(
inbox_id="agent@agentmail.to",
message_id="<abc123@agentmail.to>",
to="colleague@example.com",
text="FYI, see below.", # optional prepended text
)typescript
await client.inboxes.messages.forward(
"agent@agentmail.to",
"<abc123@agentmail.to>",
{
to: "colleague@example.com",
text: "FYI, see below.",
},
);python
client.inboxes.messages.forward(
inbox_id="agent@agentmail.to",
message_id="<abc123@agentmail.to>",
to="colleague@example.com",
text="FYI, see below.", # 可选的前置文本
)typescript
await client.inboxes.messages.forward(
"agent@agentmail.to",
"<abc123@agentmail.to>",
{
to: "colleague@example.com",
text: "FYI, see below.",
},
);Update labels
更新标签
Use labels to track message processing state. AgentMail does not have a built-in "read/unread" flag. Use labels instead.
python
client.inboxes.messages.update(
inbox_id="agent@agentmail.to",
message_id="<abc123@agentmail.to>",
add_labels=["processed", "replied"],
remove_labels=["unread"],
)typescript
await client.inboxes.messages.update(
"agent@agentmail.to",
"<abc123@agentmail.to>",
{
addLabels: ["processed", "replied"],
removeLabels: ["unread"],
},
);使用标签追踪邮件处理状态。AgentMail无内置“已读/未读”标记,请使用标签替代。
python
client.inboxes.messages.update(
inbox_id="agent@agentmail.to",
message_id="<abc123@agentmail.to>",
add_labels=["processed", "replied"],
remove_labels=["unread"],
)typescript
await client.inboxes.messages.update(
"agent@agentmail.to",
"<abc123@agentmail.to>",
{
addLabels: ["processed", "replied"],
removeLabels: ["unread"],
},
);Attachments
附件处理
python
import base64python
import base64Send with attachment
发送带附件的邮件
with open("report.pdf", "rb") as f:
content = base64.b64encode(f.read()).decode()
client.inboxes.messages.send(
inbox_id="agent@agentmail.to",
to="user@example.com",
subject="Report attached",
text="See attached.",
attachments=[{
"filename": "report.pdf",
"content": content,
"content_type": "application/pdf",
}],
)
with open("report.pdf", "rb") as f:
content = base64.b64encode(f.read()).decode()
client.inboxes.messages.send(
inbox_id="agent@agentmail.to",
to="user@example.com",
subject="Report attached",
text="See attached.",
attachments=[{
"filename": "report.pdf",
"content": content,
"content_type": "application/pdf",
}],
)
Retrieve attachment from received message
从收到的邮件中获取附件
attachment = client.inboxes.messages.get_attachment(
inbox_id="agent@agentmail.to",
message_id="abc123@agentmail.to",
attachment_id="att_456",
)
```typescript
import { readFileSync } from "node:fs";
const content = readFileSync("report.pdf").toString("base64");
await client.inboxes.messages.send("agent@agentmail.to", {
to: "user@example.com",
subject: "Report attached",
text: "See attached.",
attachments: [{ filename: "report.pdf", content, contentType: "application/pdf" }],
});
const attachment = await client.inboxes.messages.getAttachment(
"agent@agentmail.to",
"<abc123@agentmail.to>",
"att_456",
);attachment = client.inboxes.messages.get_attachment(
inbox_id="agent@agentmail.to",
message_id="abc123@agentmail.to",
attachment_id="att_456",
)
```typescript
import { readFileSync } from "node:fs";
const content = readFileSync("report.pdf").toString("base64");
await client.inboxes.messages.send("agent@agentmail.to", {
to: "user@example.com",
subject: "Report attached",
text: "See attached.",
attachments: [{ filename: "report.pdf", content, contentType: "application/pdf" }],
});
const attachment = await client.inboxes.messages.getAttachment(
"agent@agentmail.to",
"<abc123@agentmail.to>",
"att_456",
);Threads
对话线程管理
Threads group related messages in a conversation. When you send a new message, a thread is created. Replies are added to the same thread automatically.
python
undefined线程将对话中的相关邮件分组。发送新邮件时会创建线程,回复会自动添加至同一线程。
python
undefinedList threads in an inbox
列出邮箱中的线程
threads = client.inboxes.threads.list(
inbox_id="agent@agentmail.to",
labels=["unreplied"], # optional filter
)
threads = client.inboxes.threads.list(
inbox_id="agent@agentmail.to",
labels=["unreplied"], # 可选过滤条件
)
Get a specific thread with all messages
获取包含所有邮件的指定线程
thread = client.inboxes.threads.get(
inbox_id="agent@agentmail.to",
thread_id="thd_123",
)
for msg in thread.messages:
print(msg.subject, msg.extracted_text)
thread = client.inboxes.threads.get(
inbox_id="agent@agentmail.to",
thread_id="thd_123",
)
for msg in thread.messages:
print(msg.subject, msg.extracted_text)
Org-wide thread listing (across all inboxes)
列出组织内所有线程(跨所有邮箱)
all_threads = client.threads.list()
all_threads = client.threads.list()
Delete a thread
删除线程
client.inboxes.threads.delete(
inbox_id="agent@agentmail.to",
thread_id="thd_123",
)
```typescript
const threads = await client.inboxes.threads.list("agent@agentmail.to", {
labels: ["unreplied"],
});
const thread = await client.inboxes.threads.get("agent@agentmail.to", "thd_123");
const allThreads = await client.threads.list();client.inboxes.threads.delete(
inbox_id="agent@agentmail.to",
thread_id="thd_123",
)
```typescript
const threads = await client.inboxes.threads.list("agent@agentmail.to", {
labels: ["unreplied"],
});
const thread = await client.inboxes.threads.get("agent@agentmail.to", "thd_123");
const allThreads = await client.threads.list();Drafts
草稿管理
Create drafts for human-in-the-loop approval. The agent composes a draft, a human reviews, then the draft is sent.
python
undefined创建草稿用于人工介入审核:Agent编写草稿,人工审核后发送。
python
undefinedCreate draft
创建草稿
draft = client.inboxes.drafts.create(
inbox_id="agent@agentmail.to",
to="recipient@example.com",
subject="Pending approval",
text="Draft content for review",
html="<p>Draft content for review</p>",
)
draft = client.inboxes.drafts.create(
inbox_id="agent@agentmail.to",
to="recipient@example.com",
subject="Pending approval",
text="Draft content for review",
html="<p>Draft content for review</p>",
)
List drafts
列出草稿
drafts = client.inboxes.drafts.list(inbox_id="agent@agentmail.to")
drafts = client.inboxes.drafts.list(inbox_id="agent@agentmail.to")
Get, update
获取、更新草稿
draft = client.inboxes.drafts.get(inbox_id="agent@agentmail.to", draft_id=draft.draft_id)
client.inboxes.drafts.update(
inbox_id="agent@agentmail.to",
draft_id=draft.draft_id,
text="Updated draft content",
)
draft = client.inboxes.drafts.get(inbox_id="agent@agentmail.to", draft_id=draft.draft_id)
client.inboxes.drafts.update(
inbox_id="agent@agentmail.to",
draft_id=draft.draft_id,
text="Updated draft content",
)
Send draft (converts to message, removes from drafts)
发送草稿(转换为邮件,从草稿列表移除)
client.inboxes.drafts.send(inbox_id="agent@agentmail.to", draft_id=draft.draft_id)
client.inboxes.drafts.send(inbox_id="agent@agentmail.to", draft_id=draft.draft_id)
Delete draft without sending
删除草稿不发送
client.inboxes.drafts.delete(inbox_id="agent@agentmail.to", draft_id=draft.draft_id)
```typescript
const draft = await client.inboxes.drafts.create("agent@agentmail.to", {
to: "recipient@example.com",
subject: "Pending approval",
text: "Draft content",
});
await client.inboxes.drafts.send("agent@agentmail.to", draft.draftId, {});client.inboxes.drafts.delete(inbox_id="agent@agentmail.to", draft_id=draft.draft_id)
```typescript
const draft = await client.inboxes.drafts.create("agent@agentmail.to", {
to: "recipient@example.com",
subject: "Pending approval",
text: "Draft content",
});
await client.inboxes.drafts.send("agent@agentmail.to", draft.draftId, {});Pods (multi-tenant isolation)
Pods(多租户隔离)
Pods provide isolated environments for SaaS platforms. Each pod has its own set of inboxes.
python
undefinedPods为SaaS平台提供隔离环境,每个Pod拥有独立的邮箱集合。
python
undefinedCreate pod per customer
为每个客户创建Pod
pod = client.pods.create(
name="customer-acme",
client_id="pod-acme-v1", # idempotent
)
pod = client.pods.create(
name="customer-acme",
client_id="pod-acme-v1", # 幂等键
)
Create inbox within pod (pods.inboxes.create accepts flat kwargs)
在Pod内创建邮箱(pods.inboxes.create接受扁平参数)
inbox = client.pods.inboxes.create(
pod_id=pod.pod_id,
username="notifications",
client_id="acme-notifications-v1",
)
inbox = client.pods.inboxes.create(
pod_id=pod.pod_id,
username="notifications",
client_id="acme-notifications-v1",
)
List inboxes scoped to pod
列出Pod范围内的邮箱
inboxes = client.pods.inboxes.list(pod_id=pod.pod_id)
inboxes = client.pods.inboxes.list(pod_id=pod.pod_id)
List threads scoped to pod
列出Pod范围内的线程
threads = client.pods.threads.list(pod_id=pod.pod_id)
threads = client.pods.threads.list(pod_id=pod.pod_id)
List, get, delete pods
列出、获取、删除Pods
pods = client.pods.list()
pod = client.pods.get(pod_id=pod.pod_id)
client.pods.delete(pod_id=pod.pod_id)
```typescript
const pod = await client.pods.create({ name: "customer-acme", clientId: "pod-acme-v1" });
const inbox = await client.pods.inboxes.create(pod.podId, {
username: "notifications",
clientId: "acme-notifications-v1",
});
const inboxes = await client.pods.inboxes.list(pod.podId);pods = client.pods.list()
pod = client.pods.get(pod_id=pod.pod_id)
client.pods.delete(pod_id=pod.pod_id)
```typescript
const pod = await client.pods.create({ name: "customer-acme", clientId: "pod-acme-v1" });
const inbox = await client.pods.inboxes.create(pod.podId, {
username: "notifications",
clientId: "acme-notifications-v1",
});
const inboxes = await client.pods.inboxes.list(pod.podId);Allow/block lists
允许/阻止列表
Control which external senders can deliver to an inbox. Block list takes priority over allow list.
Lists are flat. Each entry is one tuple — there is no batch update, no / sub-namespace. is , , or . is or .
(direction, type, entry).allow.blockdirection"send""receive""reply"type"allow""block"python
undefined控制哪些外部发件人可向邮箱投递邮件。阻止列表优先级高于允许列表。
列表为扁平结构,每个条目是一个元组——无批量更新,无 / 子命名空间。可选、或,可选或。
(direction, type, entry).allow.blockdirection"send""receive""reply"type"allow""block"python
undefinedAllow a sender on incoming mail
允许指定发件人向邮箱投递邮件
client.inboxes.lists.create(
inbox_id="agent@agentmail.to",
direction="receive",
type="allow",
entry="boss@company.com",
)
client.inboxes.lists.create(
inbox_id="agent@agentmail.to",
direction="receive",
type="allow",
entry="boss@company.com",
)
Block a sender on incoming mail
阻止指定发件人向邮箱投递邮件
client.inboxes.lists.create(
inbox_id="agent@agentmail.to",
direction="receive",
type="block",
entry="spammer@example.com",
)
client.inboxes.lists.create(
inbox_id="agent@agentmail.to",
direction="receive",
type="block",
entry="spammer@example.com",
)
List entries for one (direction, type) pair
列出指定(direction, type)组合下的所有条目
allow = client.inboxes.lists.list(
inbox_id="agent@agentmail.to",
direction="receive",
type="allow",
)
allow = client.inboxes.lists.list(
inbox_id="agent@agentmail.to",
direction="receive",
type="allow",
)
Check a single entry
查询单个条目
entry = client.inboxes.lists.get(
inbox_id="agent@agentmail.to",
direction="receive",
type="allow",
entry="boss@company.com",
)
entry = client.inboxes.lists.get(
inbox_id="agent@agentmail.to",
direction="receive",
type="allow",
entry="boss@company.com",
)
Remove an entry
删除条目
client.inboxes.lists.delete(
inbox_id="agent@agentmail.to",
direction="receive",
type="allow",
entry="boss@company.com",
)
```typescript
await client.inboxes.lists.create(
"agent@agentmail.to",
"receive",
"allow",
{ entry: "boss@company.com" },
);
await client.inboxes.lists.create(
"agent@agentmail.to",
"receive",
"block",
{ entry: "spammer@example.com" },
);
const allow = await client.inboxes.lists.list(
"agent@agentmail.to",
"receive",
"allow",
);
await client.inboxes.lists.delete(
"agent@agentmail.to",
"receive",
"allow",
"boss@company.com",
);client.inboxes.lists.delete(
inbox_id="agent@agentmail.to",
direction="receive",
type="allow",
entry="boss@company.com",
)
```typescript
await client.inboxes.lists.create(
"agent@agentmail.to",
"receive",
"allow",
{ entry: "boss@company.com" },
);
await client.inboxes.lists.create(
"agent@agentmail.to",
"receive",
"block",
{ entry: "spammer@example.com" },
);
const allow = await client.inboxes.lists.list(
"agent@agentmail.to",
"receive",
"allow",
);
await client.inboxes.lists.delete(
"agent@agentmail.to",
"receive",
"allow",
"boss@company.com",
);Domains
域名管理
Custom domains let agents send from your own domain (e.g., ). SPF, DKIM, and DMARC records are auto-generated. Requires paid plan.
agent@yourdomain.compython
undefined自定义域名允许Agent使用您的自有域名发送邮件(如)。SPF、DKIM及DMARC记录会自动生成,需付费套餐。
agent@yourdomain.compython
undefinedAdd domain. feedback_enabled is required: set True to route
添加域名。feedback_enabled为必填项:设为True可将退信/投诉通知路由至您的邮箱
bounce/complaint notifications to your inboxes.
—
domain = client.domains.create(domain="yourdomain.com", feedback_enabled=True)
domain = client.domains.create(domain="yourdomain.com", feedback_enabled=True)
domain.records -> list of VerificationRecord objects to add at your registrar
domain.records -> 需添加至域名注册商的VerificationRecord对象列表
Verify after DNS records are set
DNS记录设置完成后验证域名
client.domains.verify(domain_id=domain.domain_id)
client.domains.verify(domain_id=domain.domain_id)
List, get, delete
列出、获取、删除域名
domains = client.domains.list()
domain = client.domains.get(domain_id=domain.domain_id)
client.domains.delete(domain_id=domain.domain_id)
```typescript
const domain = await client.domains.create({
domain: "yourdomain.com",
feedbackEnabled: true,
});
await client.domains.verify(domain.domainId);domains = client.domains.list()
domain = client.domains.get(domain_id=domain.domain_id)
client.domains.delete(domain_id=domain.domain_id)
```typescript
const domain = await client.domains.create({
domain: "yourdomain.com",
feedbackEnabled: true,
});
await client.domains.verify(domain.domainId);Real-time events
实时事件
AgentMail supports both WebSockets and webhooks for real-time notifications. See and for detailed setup and full code examples.
references/webhooks.mdreferences/websockets.mdAgentMail支持WebSocket与Webhook两种实时通知方式。详细设置及完整代码示例请参考和。
references/webhooks.mdreferences/websockets.mdWebSockets (recommended for agents)
WebSocket(推荐Agent使用)
No public URL needed. Persistent connection with instant delivery.
Python (sync):
python
from agentmail import AgentMail, Subscribe, Subscribed, MessageReceivedEvent
client = AgentMail()
with client.websockets.connect() as socket:
socket.send_subscribe(Subscribe(inbox_ids=["agent@agentmail.to"]))
for event in socket:
if isinstance(event, Subscribed):
print(f"Subscribed to: {event.inbox_ids}")
elif isinstance(event, MessageReceivedEvent):
print(f"From: {event.message.from_}")
print(f"Subject: {event.message.subject}")
print(f"Body: {event.message.extracted_text}")Python (async):
python
from agentmail import AsyncAgentMail, Subscribe, MessageReceivedEvent
client = AsyncAgentMail()
async with client.websockets.connect() as socket:
await socket.send_subscribe(Subscribe(inbox_ids=["agent@agentmail.to"]))
async for event in socket:
if isinstance(event, MessageReceivedEvent):
await process_email(event.message)TypeScript:
typescript
const socket = await client.websockets.connect();
socket.on("open", () => {
socket.sendSubscribe({ type: "subscribe", inboxIds: ["agent@agentmail.to"] });
});
socket.on("message", (event) => {
// Use event.eventType (not event.type — event.type is always "event")
if (event.eventType === "message.received") {
// TypeScript uses .from directly; only Python needs .from_ (reserved keyword)
console.log("From:", event.message.from);
console.log("Subject:", event.message.subject);
}
});无需公网URL,持久连接实现即时投递。
Python(同步):
python
from agentmail import AgentMail, Subscribe, Subscribed, MessageReceivedEvent
client = AgentMail()
with client.websockets.connect() as socket:
socket.send_subscribe(Subscribe(inbox_ids=["agent@agentmail.to"]))
for event in socket:
if isinstance(event, Subscribed):
print(f"已订阅: {event.inbox_ids}")
elif isinstance(event, MessageReceivedEvent):
print(f"发件人: {event.message.from_}")
print(f"主题: {event.message.subject}")
print(f"正文: {event.message.extracted_text}")Python(异步):
python
from agentmail import AsyncAgentMail, Subscribe, MessageReceivedEvent
client = AsyncAgentMail()
async with client.websockets.connect() as socket:
await socket.send_subscribe(Subscribe(inbox_ids=["agent@agentmail.to"]))
async for event in socket:
if isinstance(event, MessageReceivedEvent):
await process_email(event.message)TypeScript:
typescript
const socket = await client.websockets.connect();
socket.on("open", () => {
socket.sendSubscribe({ type: "subscribe", inboxIds: ["agent@agentmail.to"] });
});
socket.on("message", (event) => {
// 使用event.eventType(而非event.type —— event.type始终为"event")
if (event.eventType === "message.received") {
// TypeScript直接使用.from;仅Python需使用.from_(因from为保留关键字)
console.log("发件人:", event.message.from);
console.log("主题:", event.message.subject);
}
});Webhooks
Webhook
HTTP POST to your endpoint on email events. Requires a public URL.
event_typespython
webhook = client.webhooks.create(
url="https://your-server.com/webhooks",
event_types=["message.received", "message.bounced"],
)邮件事件触发时向您的端点发送HTTP POST请求,需公网URL。
event_typespython
webhook = client.webhooks.create(
url="https://your-server.com/webhooks",
event_types=["message.received", "message.bounced"],
)webhook.webhook_id, webhook.secret
webhook.webhook_id, webhook.secret
List, get, delete
列出、获取、删除Webhook
webhooks = client.webhooks.list()
client.webhooks.delete(webhook_id=webhook.webhook_id)
Typed webhook event types (listed in the SDK's Literal): `message.received`, `message.sent`, `message.delivered`, `message.bounced`, `message.complained`, `message.rejected`, `domain.verified`.
Runtime-only events — accepted by the API but not in the SDK's typed Literal — include `message.received.spam` and `message.received.blocked`. Pass them as plain strings if you need them. Type checkers will flag them; that's expected.
Always verify webhook signatures before processing. See `references/webhooks.md`.webhooks = client.webhooks.list()
client.webhooks.delete(webhook_id=webhook.webhook_id)
已类型化的Webhook事件类型(SDK的Literal中列出):`message.received`, `message.sent`, `message.delivered`, `message.bounced`, `message.complained`, `message.rejected`, `domain.verified`。
仅运行时支持的事件——API接受但未包含在SDK的类型化Literal中——包括`message.received.spam`和`message.received.blocked`。如需使用请传入纯字符串,类型检查器会标记,此为预期行为。
处理前请始终验证Webhook签名,详见`references/webhooks.md`。Idempotency
幂等性
Pass / on create operations to make them safe to retry:
client_idclientIdpython
from agentmail.inboxes.types import CreateInboxRequest
inbox = client.inboxes.create(
request=CreateInboxRequest(client_id="my-unique-key"),
)在创建操作中传入 / 可确保操作可安全重试:
client_idclientIdpython
from agentmail.inboxes.types import CreateInboxRequest
inbox = client.inboxes.create(
request=CreateInboxRequest(client_id="my-unique-key"),
)Calling again with the same client_id returns the existing inbox, not a duplicate
使用同一client_id再次调用会返回现有邮箱,不会创建重复项
pod = client.pods.create(client_id="pod-unique-key")
pod = client.pods.create(client_id="pod-unique-key")
pods.create takes flat kwargs; same idempotency behavior
pods.create接受扁平参数,幂等行为相同
undefinedundefinedError handling
错误处理
Both SDKs raise/throw on 4xx and 5xx responses. On 429 (rate limit), read the header and use exponential backoff. Both SDKs retry automatically (default: 2 retries).
Retry-Afterpython
try:
client.inboxes.messages.send(inbox_id, to="user@example.com", subject="Hi", text="Hello")
except Exception as e:
print(f"Error: {e}")
# e.body.message contains details if available两个SDK在收到4xx和5xx响应时都会抛出异常。收到429(请求超限)响应时,请读取头并使用指数退避策略。两个SDK均会自动重试(默认:2次)。
Retry-Afterpython
try:
client.inboxes.messages.send(inbox_id, to="user@example.com", subject="Hi", text="Hello")
except Exception as e:
print(f"错误: {e}")
# 若可用,e.body.message包含详细信息Python: override retries per call via request_options
Python:通过request_options覆盖单次调用的重试次数
(the AgentMail constructor has no max_retries argument)
(AgentMail构造函数无max_retries参数)
client.inboxes.messages.send(
inbox_id,
to="user@example.com",
subject="Hi",
text="Hello",
request_options={"max_retries": 5},
)
```typescript
try {
await client.inboxes.messages.send(inboxId, {
to: "user@example.com",
subject: "Hi",
text: "Hello",
});
} catch (err) {
console.error("Error:", err.message);
// err.statusCode, err.body for details
}
// TypeScript: override retries globally on the client, or per-call via requestOptions
const client = new AgentMailClient({ apiKey: "...", maxRetries: 5 });client.inboxes.messages.send(
inbox_id,
to="user@example.com",
subject="Hi",
text="Hello",
request_options={"max_retries": 5},
)
```typescript
try {
await client.inboxes.messages.send(inboxId, {
to: "user@example.com",
subject: "Hi",
text: "Hello",
});
} catch (err) {
console.error("错误:", err.message);
// err.statusCode, err.body包含详细信息
}
// TypeScript:在客户端全局覆盖重试次数,或通过requestOptions覆盖单次调用
const client = new AgentMailClient({ apiKey: "...", maxRetries: 5 });IMAP and SMTP
IMAP与SMTP
AgentMail inboxes are accessible via standard IMAP and SMTP protocols, enabling integration with traditional email clients and legacy systems. See https://docs.agentmail.to/imap-smtp for setup details.
AgentMail邮箱可通过标准IMAP和SMTP协议访问,支持与传统邮件客户端及遗留系统集成。设置详情请参考https://docs.agentmail.to/imap-smtp。
Pagination
分页
All list endpoints use cursor-based pagination:
python
response = client.inboxes.messages.list(inbox_id, limit=20)
while response.next_page_token:
response = client.inboxes.messages.list(
inbox_id, limit=20, page_token=response.next_page_token
)所有列表接口使用基于游标的分页:
python
response = client.inboxes.messages.list(inbox_id, limit=20)
while response.next_page_token:
response = client.inboxes.messages.list(
inbox_id, limit=20, page_token=response.next_page_token
)Reference files
参考文档
For detailed coverage of specific topics:
- -- webhook setup, event types, payload structure, signature verification
references/webhooks.md - -- WebSocket connection, sync/async patterns, event handler pattern, subscribe options
references/websockets.md - -- complete endpoint and SDK method table with all parameters
references/full-api-reference.md
特定主题的详细说明:
- -- Webhook设置、事件类型、负载结构、签名验证
references/webhooks.md - -- WebSocket连接、同步/异步模式、事件处理器模式、订阅选项
references/websockets.md - -- 完整的端点与SDK方法表,包含所有参数
references/full-api-reference.md