AI 参与说明(Agent:Cursor):本文由 Cursor 根据一份 Perplexity 调研导出继续整理。导出稿把 Email Routing 与 Email Sending 收成 Email Service,并给出收发一体、SMTP 与限额表;本稿用 Cloudflare 官方文档、Changelog、Agents SDK 文档与公开仓库逐项回查,纠正过时 SMTP 端点,并补上开发接入、本地调试与完整示例。资料核对于 2026-09-10。Email Sending 仍处于 public beta。运行记录:模型
grok-4.6,提供方xAI,执行入口 Cursor。reasoning effort 与 CLI 版本未取得运行记录。
结论:开发者要在 Cloudflare 上收发事务邮件,用的是 Email Service,不是 Email security。 Email Service 把出站的 Email Sending 和入站的 Email Routing 收成一套产品。三条出站路径(Workers binding、REST API、SMTP)进入同一条投递管道,共享限额、DKIM / ARC 签名和投递日志。Agent 可以直接用 email() handler 和 Agents SDK 的 onEmail。2026 年 4 月随 public beta 开源的 Agentic Inbox 是目前最显眼的参考实现。
Email Sending is Cloudflare’s first-party transactional email product. Email Routing receives inbound mail and either forwards it to a verified destination address or delivers it to a Worker email() handler. Together they form Email Service. Email Service overview Email Sending public beta, 2026-04-16
官方把两件事说得很直白:密码重置、magic link、发票一旦进垃圾箱,产品体验就坏了;同时邮件正在变成 Agent 与外部世界交互的低摩擦通道,用户转发一封邮件就能触发任务,Agent 做完再回信。这不是“多一个发信 API”,而是把邮箱做成 Workers 生态里与 KV、R2、D1 并列的基础设施。Announcing Email Service Email for agents
阅读前先看这几个词
| 英文术语 | 中文名称 | 简要解释 |
|---|---|---|
| Email Service | 保留原名(产品名称) | Cloudflare 开发平台上的收发信产品,由 Email Sending 与 Email Routing 组成 |
| Email Sending | 保留原名(能力名称) | 从 Worker、REST API 或 SMTP 发出事务邮件 |
| Email Routing | 保留原名(能力名称) | 把域名收到的邮件转发到已验证地址,或交给 Worker |
| Email security | 保留原名(产品名称) | Cloudflare One 的入站威胁防护,保护已有邮箱,不是发信 API |
| Area 1 | 保留原名(旧产品名) | Cloudflare 收购的邮件安全产品,文档仍单独保留 |
| Workers binding | Workers 绑定 | 通过 env.EMAIL 发信,不必在 Worker 里放 API Token |
send_email | 配置键名 | Wrangler 里声明发信 binding 的字段 |
| Routing rule | 路由规则 | 把一个邮箱地址模式绑定到一个 Destination address 或一个 Worker |
| Destination address | 目标地址 | 账号里预先验证、可免费转发或试发的收件地址 |
| ForwardableEmailMessage | 入站邮件对象 | email() handler 收到的消息,可 forward / reply / setReject |
| Suppression list | 抑制名单 | 硬退信或投诉后不再投递的收件人列表 |
| SMTPS | 隐式 TLS 的 SMTP | 连接即 TLS;Email Sending 使用端口 465,不提供 587 STARTTLS |
| ARC | Authenticated Received Chain | 转发时保留上游认证结果的签名链,由平台自动写入 |
| Agents SDK | 保留原名(SDK 名称) | Cloudflare 的有状态 Agent 运行时,提供 onEmail 与 sendEmail() |
| Agentic Inbox | 保留原名(项目名称) | Cloudflare 开源的自托管邮箱与 Email Agent 参考应用 |
| postal-mime | 保留原名(库名称) | 解析原始 MIME 的库;读 message.raw 时常用 |
先分清两条产品线
“Cloudflare 的 email 服务”通常被问成一个产品,实际至少是两条线:
| 产品 | 解决什么 | 不解决什么 | 入口 |
|---|---|---|---|
| Email Service | 应用和 Agent 收发事务邮件 | 企业邮箱威胁防护、营销群发 | developers.cloudflare.com/email-service |
| Email security | 分析已有 Outlook / Gmail 入站邮件,拦钓鱼、恶意软件、BEC 和垃圾邮件 | 给自己的应用发欢迎信、验证码 | Cloudflare One Email security |
Email security integrates with an existing mailbox provider via API, BCC/Journaling, or MX/Inline; it is a Cloudflare One security control, not a send API for Workers. Area 1 is the earlier product line, and Cloudflare still keeps separate Area 1 documentation. Email security overview
开发者选题里最近变热的,是 Email Service 这一侧:2026-04-16 起 Email Sending 进入 public beta,并和多年已有的 Email Routing 合并宣传。官方同时放出 Agents SDK 的邮件钩子、Wrangler CLI、Email MCP,以及参考应用 Agentic Inbox。Email for agents
flowchart TB
ask["需要处理邮件?"] --> q1{"是给自己的应用或 Agent 收发,还是保护员工已有邮箱?"}
q1 -->|应用 / Agent| es["Email Service"]
q1 -->|员工邮箱防护| sec["Email security / Area 1"]
es --> send["Email Sending<br/>Workers binding / REST / SMTP"]
es --> route["Email Routing<br/>转发或 email() handler"]
send --> tx["welcome / magic link / 订单通知 / Agent 回复"]
route --> in["support@ / catch-all / Agent 收件"]
Email Service 怎么工作
Email Service requires the zone to use Cloudflare DNS. Onboarding a sending domain adds MX records on the cf-bounce subdomain, plus SPF, DKIM and DMARC records that authorize Cloudflare to send and process bounces. Onboarding Email Routing adds MX on the apex (or chosen domain) so inbound mail arrives at Cloudflare. DNS usually completes in 5–15 minutes, and can take up to 24 hours. Send emails Route emails
入站和出站在同一 Worker 里可以同时出现:HTTP 请求走 fetch,入站邮件走 email(),出站调用 env.EMAIL.send()。站内对 handler 与 binding 的分工,见 Workers:运行时 API、Bindings 与执行模型。
当前官方 Wrangler 配置只需要 send_email 声明出站 binding。入站靠 Dashboard 或 wrangler email routing rules create 把地址指到这个 Worker,不需要再写一个名为 EMAIL_HANDLER 的 email binding。部分二手整理会把后者写进 wrangler.jsonc,与 2026-09-10 的官方文档不一致。
Emails submitted over the Workers binding, the REST API, and SMTP enter the same delivery pipeline: they share limits, receive the same DKIM and ARC signing, and produce the same delivery logs. SMTP
flowchart TB
mx["域名 MX / SPF / DKIM / DMARC"] --> inbound["Email Routing"]
inbound --> rule{"Routing rule"}
rule -->|"转发"| dest["已验证 Destination address"]
rule -->|"Send to Worker"| handler["email() handler"]
handler --> parse["postal-mime 解析 MIME"]
handler --> store["Durable Object / D1 / R2 / Queue"]
handler --> fwd["message.forward()"]
handler --> reply["message.reply() 或 env.EMAIL.send()"]
app["Worker fetch / Queue / Agent"] --> bind["env.EMAIL.send()"]
rest["外部后端"] --> api["REST API"]
legacy["Nodemailer / smtplib / PHPMailer"] --> smtp["SMTP SMTPS :465"]
bind --> sending["Email Sending"]
api --> sending
smtp --> sending
sending --> inbox["收件人收件箱"]
Email Sending:三条出站路径
Email Sending is in public beta and is intended for transactional email only; Cloudflare says marketing and bulk sender tooling are planned, not available now. Email Service FAQ Public beta changelog
| 路径 | 适用场景 | 鉴权 | 成功返回 |
|---|---|---|---|
Workers binding env.EMAIL.send() | 代码已经跑在 Worker / Agents SDK | send_email binding,不必放 API Token | { messageId } |
| REST API | Node、Python、Go 或其它后端 | Bearer API Token | delivered / permanent_bounces / queued |
SMTP smtp.mx.cloudflare.net:465 | 现有 SMTP 客户端(Nodemailer、smtplib、PHPMailer、JavaMail) | 用户名固定为 api_token,密码为 API Token | SMTP 250,正文后返回 Message-ID |
The from address must belong to a domain onboarded for Email Sending. Before that domain is onboarded, you can only send to verified destination addresses in the account; after onboarding, you can send to arbitrary recipients on the Workers Paid plan. Limits
Workers binding
{
"name": "transactional-mail",
"main": "src/index.ts",
"compatibility_date": "2026-09-10",
"send_email": [
{
"name": "EMAIL",
"remote": true
}
]
}
"remote": true lets wrangler dev call the real Email Service. Real mail will be sent, so use addresses you control. Run npx wrangler types after adding the binding; do not hand-write SendEmail. Workers API Agents email channel
interface Env {
EMAIL: SendEmail;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
if (url.pathname !== "/welcome") {
return new Response("Not Found", { status: 404 });
}
try {
const result = await env.EMAIL.send({
to: "user@example.com",
from: { email: "welcome@yourdomain.com", name: "Example App" },
replyTo: "support@yourdomain.com",
subject: "Welcome",
html: "<h1>Welcome</h1><p>Thanks for signing up.</p>",
text: "Welcome. Thanks for signing up.",
});
return Response.json({ messageId: result.messageId });
} catch (error) {
const code = (error as { code?: string }).code;
if (code === "E_SENDER_NOT_VERIFIED" || code === "E_SENDER_DOMAIN_NOT_AVAILABLE") {
return Response.json({ error: code }, { status: 400 });
}
if (code === "E_RATE_LIMIT_EXCEEDED" || code === "E_DAILY_LIMIT_EXCEEDED") {
return Response.json({ error: code }, { status: 429 });
}
throw error;
}
},
} satisfies ExportedHandler<Env>;
官方 Workers API 把 from 写成 string | EmailAddress,其中 EmailAddress.email 是地址字段。结合 to / cc / bcc 的收件人总数不超过 50;单封出站邮件(含附件)默认不超过 5 MiB,只有发往 verified destination addresses 时才放到 25 MiB。附件最多 32 个。新代码优先用结构化的 send(),旧的 EmailMessage + mimetext 仅在已经持有 RFC 5322 原文时保留。Workers API Limits
常见错误码(Workers binding 抛出字符串 code):
| code | 含义 |
|---|---|
E_SENDER_NOT_VERIFIED / E_SENDER_DOMAIN_NOT_AVAILABLE | 发件域名未完成 Email Sending 接入 |
E_RECIPIENT_NOT_ALLOWED | 收件人不在 binding 允许列表 |
E_RECIPIENT_SUPPRESSED | 收件人已在 Suppression list |
E_TOO_MANY_RECIPIENTS | to + cc + bcc 超过 50 |
E_CONTENT_TOO_LARGE | 超过 5 MiB(或 verified destination 的 25 MiB) |
E_RATE_LIMIT_EXCEEDED / E_DAILY_LIMIT_EXCEEDED | 触发速率或日配额 |
E_HEADER_NOT_ALLOWED / E_HEADER_USE_API_FIELD | 自定义 header 不在允许列表,或应走独立 API 字段 |
可以用 destination_address 或 allowed_destination_addresses 收紧某个 binding 能发往哪里,避免一个 Worker 拿到无限制发信能力。Configure send bindings
模板不必绑死在 Cloudflare 上。官方示例直接传 HTML 字符串;也可以先用 @react-email/render 得到 html 和 text,再交给 env.EMAIL.send()。当前一手教程以 User signup flow 为准。
REST API
The current REST endpoint is POST https://api.cloudflare.com/client/v4/accounts/{account_id}/email/sending/send. Authenticate with a token that can send email. A successful body groups recipients into delivered, permanent_bounces, and queued; this is not the Workers binding’s { messageId }. REST 用数字错误码(例如限流 10004),Workers binding 用字符串 code。 REST API
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/email/sending/send" \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{
"to": "recipient@example.com",
"from": "welcome@yourdomain.com",
"subject": "Welcome to our service!",
"html": "<h1>Welcome</h1><p>Thanks for signing up.</p>",
"text": "Welcome! Thanks for signing up."
}'
2026-04-16 的博客示例曾写过 /email-service/send 路径。以 2026-06-09 更新的 REST API 文档为准,当前路径是 /email/sending/send。
SMTP:只提供 465 隐式 TLS
Authenticated SMTP submission became available in beta on 2026-06-08. The current endpoint is smtp.mx.cloudflare.net:465 with implicit TLS (SMTPS). Plaintext SMTP, opportunistic STARTTLS on port 587, and unauthenticated relay on port 25 are not supported for outbound submission. Port 25 is reserved for inbound Email Routing. SMTP SMTP changelog
部分入门页摘要仍出现 smtp.cloudflare.email:587。以 SMTP 参考页(标注 2026-06-09)和 2026-06-08 Changelog 为准。
| 配置项 | 值 |
|---|---|
| Host | smtp.mx.cloudflare.net |
| Port | 465 |
| Security | Implicit TLS / SMTPS |
| AUTH | PLAIN(优先)或 LOGIN |
| Username | 字面量 api_token,不是 Token 本身 |
| Password | 带 Email Sending: Edit 权限的 API Token |
Anyone with that token can send from any onboarded domain on the matching account. Prefer an account-owned token, and treat it as a credential. SMTP
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({
host: "smtp.mx.cloudflare.net",
port: 465,
secure: true,
auth: {
user: "api_token",
pass: process.env.CF_API_TOKEN,
},
});
const info = await transporter.sendMail({
from: '"Acme" <welcome@yourdomain.com>',
to: "user@example.com",
subject: "Welcome to Acme",
text: "Thanks for signing up.",
html: "<h1>Welcome to Acme</h1><p>Thanks for signing up.</p>",
});
最小 curl:
curl --ssl-reqd \
--url "smtps://smtp.mx.cloudflare.net:465" \
--user "api_token:$CF_API_TOKEN" \
--mail-from "welcome@yourdomain.com" \
--mail-rcpt "recipient@example.com" \
--upload-file mail.txt
单次会话 RCPT TO 不超过 50,EHLO 声明的 SIZE 是 5 MiB,AUTH 超时 30 秒,DATA 超时 300 秒。账户级配额与 REST / Workers binding 共享。常见失败:用户名不是 api_token 会 535 5.7.8;MAIL FROM 域名未接入会 550 5.7.1;消息超过 5 MiB 会 552 5.3.4。客户端必须按 465 隐式 TLS 连接,不能改成 587 STARTTLS。SMTP SMTP examples
本地或沙箱里的 coding agent 也可以不写 Worker,直接用 Wrangler:
npx wrangler email sending enable yourdomain.com
npx wrangler email sending dns get yourdomain.com
npx wrangler email send \
--from "agent@yourdomain.com" \
--to "you@example.com" \
--subject "Build completed" \
--text "The staging deploy finished."
Email for agents 把同一套能力接到 Cloudflare MCP,因此不在 Workers 上跑的 Agent 也能发信。
Email Routing:入站邮件怎么进 Worker
Email Routing is available on Workers Free and Workers Paid. Inbound volume is unlimited; a routing rule maps one address pattern to either one destination address or one Worker. Destination addresses are account-scoped and capped at 200. Inbound messages larger than 25 MiB are rejected. Pricing Limits
开通顺序:Dashboard 进入 Compute → Email Service → Email Routing → Onboard Domain → 添加并验证 Destination address → 创建 Routing rule(Email pattern、Action、Destination)。也可以用 wrangler email routing enable / wrangler email routing rules create。
email() handler 不需要单独的收信 binding。message 的类型是 ForwardableEmailMessage:
interface ForwardableEmailMessage {
readonly from: string;
readonly to: string;
readonly headers: Headers;
readonly raw: ReadableStream;
readonly rawSize: number;
readonly canBeForwarded: boolean;
setReject(reason: string): void;
forward(rcptTo: string, headers?: Headers): Promise<EmailSendResult>;
reply(message: EmailMessage): Promise<EmailSendResult>;
}
from/to是 SMTP 信封地址。from比邮件头更可信,因为头可以伪造。raw是一次性ReadableStream。第二次读取会得到空内容,解析前先arrayBuffer()。forward(rcptTo)只能发到已经验证的 Destination address。自定义 header 只保留X-前缀,其它会被去掉。setReject(reason)以永久 SMTP 错误拒绝。reply()走同一条 SMTP 会话并保持 Message-ID 链,但限制很严,见下一小节。延迟回复应改存状态,再用env.EMAIL.send()。
message.reply() throws unless all of these are true: the inbound message has a valid DMARC result; this event has not already replied; the reply recipient matches the original sender; the outgoing sender domain matches the receiving domain; the inbound References header has at most 100 entries. Email handler
因此:需要立刻线程化回信、且满足 DMARC 时用 reply();需要异步、人审或绕过这些限制时用 env.EMAIL.send(),并自己设 In-Reply-To / References。
import PostalMime from "postal-mime";
interface Env {
EMAIL: SendEmail;
TICKETS: Queue;
}
export default {
async email(message, env): Promise<void> {
const raw = await new Response(message.raw).arrayBuffer();
const parsed = await PostalMime.parse(raw);
const subject = parsed.subject ?? message.headers.get("subject") ?? "";
if (!message.to.toLowerCase().includes("support@")) {
message.setReject("Unknown recipient");
return;
}
const extra = new Headers();
extra.set("X-Original-Recipient", message.to);
extra.set("X-Processed-By", "support-worker");
await message.forward("team@example.com", extra);
await env.TICKETS.send({
from: message.from,
subject,
text: parsed.text ?? "",
});
},
} satisfies ExportedHandler<Env>;
This example is a complete handler skeleton; it is not a production inbox. Immediate auto-replies can create mail loops. Production code should skip noreply / auto-submitted mail (Agents SDK 提供 isAutoReplyEmail()),并把必须送达的工作写入 Queues 或 Workflows,不要只挂在 ctx.waitUntil() 上。
一条 routing rule 只能指向一个目标。同一个地址要同时入库和转发给多人时,用 Worker 对每个已验证地址调用一次 forward(),或 Promise.all。
Emails sent with the send_email binding show up as dropped in the Email Routing summary even when delivery succeeded. Track outbound success in Email Sending metrics and logs, not the routing dashboard. Limits
Subaddressing (user+detail@example.com) 已支持:user@example.com 的规则会接住 +detail,细节可留给 Worker 或 Agent 做分类。Subaddressing changelog, 2025-07-21
开发接入:从本地到一条完整用户流
1. 域名与 Wrangler
- 域名必须使用 Cloudflare DNS。
npx wrangler email routing enable yourdomain.com与npx wrangler email sending enable yourdomain.com(或 Dashboard 的 Onboard Domain)。npx wrangler email sending dns get yourdomain.com核验 MX、SPF、DKIM、DMARC。- 先验证至少一个 Destination address,在发送域名生效前用它做免费试发。
- 在
wrangler.jsonc声明send_email,然后npx wrangler types。
2. 本地触发 email() handler
wrangler dev 会暴露 POST /cdn-cgi/local/email。可以用 curl 把一封原始邮件打进本地 Worker,不必先改 MX。Local development for Email Workers
npx wrangler dev
curl -X POST 'http://localhost:8787/cdn-cgi/local/email' \
--url-query 'from=sender@example.com' \
--url-query 'to=support@yourdomain.com' \
--header 'Content-Type: application/json' \
--data-raw 'From: sender@example.com
To: support@yourdomain.com
Subject: Testing Email Workers Local Dev
Hi there'
出站若配置了 "remote": true,本地 EMAIL.send() 会打到真实 Email Service。测试地址必须是你控制的邮箱。
3. 注册信与验证链接
官方 User signup flow 用两个 KV namespace 保存用户和 1 小时过期的验证 token,POST /signup 连发欢迎信和验证信,GET /verify 核销 token。下面是同一条路径的压缩版,完整代码以官方页为准。
interface Env {
EMAIL: SendEmail;
USERS: KVNamespace;
VERIFICATION_TOKENS: KVNamespace;
DOMAIN: string;
COMPANY_NAME: string;
}
async function handleSignup(request: Request, env: Env): Promise<Response> {
const { email, firstName } = (await request.json()) as {
email?: string;
firstName?: string;
};
if (!email || !firstName) {
return Response.json({ error: "Invalid input" }, { status: 400 });
}
if (await env.USERS.get(email)) {
return Response.json({ error: "User already exists" }, { status: 409 });
}
const token = crypto.randomUUID();
await env.USERS.put(email, JSON.stringify({ email, firstName, verified: false }));
await env.VERIFICATION_TOKENS.put(token, email, { expirationTtl: 3600 });
const verificationUrl = `https://${env.DOMAIN}/verify?token=${token}`;
await env.EMAIL.send({
to: email,
from: `noreply@${env.DOMAIN}`,
subject: "Please verify your email address",
html: `<p>Hi ${firstName}, <a href="${verificationUrl}">verify your email</a>. This link expires in 1 hour.</p>`,
text: `Hi ${firstName}, verify: ${verificationUrl}`,
});
return Response.json({ success: true }, { status: 201 });
}
验收:用自己的邮箱走完 signup → 收到两封信(完整示例会再发欢迎信)→ 一小时内打开链接 → KV 中 verified: true;过期 token 返回 400。不要在 fetch 里用 waitUntil 发送验证信,验证信失败应让请求失败。
4. 入站工单闭环
一个可落地的开发顺序:
sequenceDiagram
participant User
participant MX as Email Routing
participant W as Worker email()
participant Q as Queue
participant C as Queue consumer
participant ES as Email Sending
User->>MX: 发到 support@yourdomain.com
MX->>W: ForwardableEmailMessage
W->>W: postal-mime 解析
W->>Q: 投递工单 payload
W-->>User: 可选 message.reply()
Q->>C: 至少一次消费
C->>C: 写 Durable Object / 外部工单
C->>ES: env.EMAIL.send() 带工单号
ES-->>User: 确认信
Worker 热路径只做:校验收件人、缓冲 raw、解析、forward 给值班邮箱、投递 Queue。摘要、Workers AI 分类、创建 Jira/Linear、延迟回信都放到 consumer。这样 CPU 超限时入站邮件不会整封丢失,Free 计划上的 EXCEEDED_CPU 也更容易隔离。
5. 自定义 Header
Email Service 对 header 采用允许列表。Date、Message-ID、DKIM-Signature、ARC-*、Return-Path 等由平台生成,写入 headers 会 E_HEADER_NOT_ALLOWED。From / To / Subject / Reply-To 必须走独立字段。可设置的包括 In-Reply-To、References、List-Unsubscribe、Auto-Submitted,以及任意 X- 前缀。非 X- 的允许 header 最多 20 个,自定义 header 合计不超过 16 KB。整封请求若含非法 header 会被拒绝,不会静默删头后继续发送。Email headers
Agents SDK:把邮箱当成 Agent 的接口
A chatbot answers in the current turn. An email-native agent can receive mail, persist state in a Durable Object, do longer work, then reply later. Email for agents Email agent example
import { Agent, callable, routeAgentEmail } from "agents";
import { createAddressBasedEmailResolver, type AgentEmail } from "agents/email";
import PostalMime from "postal-mime";
export class SupportAgent extends Agent {
@callable()
async sendWelcomeEmail(to: string) {
await this.sendEmail({
binding: this.env.EMAIL,
to,
from: "support@yourdomain.com",
replyTo: "support@yourdomain.com",
subject: "Welcome",
text: "Thanks for signing up. Reply to this email if you need help.",
});
}
async onEmail(email: AgentEmail) {
const raw = await email.getRaw();
const parsed = await PostalMime.parse(raw);
this.setState({
...this.state,
ticket: {
from: email.from,
subject: parsed.subject,
messageId: parsed.messageId,
},
});
await this.replyToEmail(email, {
fromName: "Support Agent",
body: "Thanks for your email. We received it.",
});
}
}
export default {
async email(message, env) {
await routeAgentEmail(message, env, {
resolver: createAddressBasedEmailResolver("SupportAgent"),
});
},
} satisfies ExportedHandler<Env>;
要点:
createAddressBasedEmailResolver("SupportAgent")按收件地址把邮件送到对应 Agent 实例;support@、sales@可以是不同实例,不必先建多个邮箱产品。sendEmail()会写入X-Agent-Name和X-Agent-ID。传入secret时用 HMAC-SHA256 签名,后续回复经createSecureReplyEmailResolver回到同一个实例,避免伪造头把邮件打到任意 Agent。replyToEmail()只能在活的onEmail调用里使用。人审之后再回、Queue 消费后再回,应把from/messageId/subject写入 state,然后用sendEmail()并设置inReplyTo。- Durable Objects 保存会话状态,所以“邮箱”可以同时是 Agent 的记忆,而不必先外接另一套向量库。对象模型见 Durable Objects 使用方式与接口整理。
价格、配额与接入条件
整理日期 2026-09-10,依据官方定价与限额页(定价页标注 2026-06-09 更新):
| 项目 | Workers Free | Workers Paid |
|---|---|---|
| Email Routing 入站 | 不限量 | 不限量 |
| Email Sending 出站到任意收件人 | 不可用 | 每月 3,000 封,超出后每 1,000 封 $0.35 |
| 发到账号内 verified destination addresses | 免费,不计入月配额和日限额 | 同左 |
其它会直接影响实现的边界:
- 新账号有较保守的 daily sending limits,随发送声誉上升;需要提前提高时走官方限额申请表。
- 被 API 边界拒绝的请求(含 Suppression list)不计入月配额;硬退信或已被 Email Service 接受的邮件计入。
- 每个 zone 最多 30 个配置了 Routing 或 Sending 的域名(含 apex)。
- 处理入站邮件的 Worker 仍占用标准 CPU / 内存。Free 计划上复杂 handler 可能
EXCEEDED_CPU。 - You must use Cloudflare DNS. 事务邮件仍须遵守 CAN-SPAM、GDPR、CASL 等适用法规,并提供退订与投诉处理。
近期比较热的项目:Agentic Inbox 以及其它自托管邮箱
The project that matches “最近好像看到什么比较火” is Cloudflare’s own Agentic Inbox. It was published with the Email Sending public beta on 2026-04-16, and on 2026-09-10 GitHub reported 7,362 stars and 947 forks.
Agentic Inbox 把 Email Service 嵌进一个可部署的邮箱客户端:
| 层 | 用到的 Cloudflare 能力 |
|---|---|
| 入站 | Email Routing catch-all → Worker |
| 出站 | send_email binding |
| 每个邮箱的状态 | Durable Object + SQLite |
| 附件 | R2 |
| Email Agent | Agents SDK AIChatAgent + Workers AI |
| 生产鉴权 | Cloudflare Access;README 写明这是唯一信任边界,没有按邮箱授权 |
它会自动给新邮件起草回复,但发送前必须人工确认。仓库也暴露 /mcp,外部 Agent 可以起草、等人审。这是参考应用,不是 Cloudflare 托管的 Gmail 替代品:邮件数据在你自己的账号里,生产环境必须先配 Access。README 仍有部分链接指向旧的 Email Routing 路径,接入时以当前 Email Service 文档为准。Agentic Inbox README Email for agents
同一波自托管邮箱里,社区项目 Mailflare 在 2026-09-10 有 2,877 stars。它同样跑在你的 Cloudflare 账号里,用 Email Routing 收信、Email Sending 发信,数据放在自己的 D1 与 R2,面向个人和团队邮箱,而不是官方 Agent 参考实现。
选型时不要把这些项目和 Email Service 本身并列成“又一个 Cloudflare 官方邮件产品”:
| 需求 | 直接用 Email Service | 再考虑参考应用 |
|---|---|---|
| 注册信、magic link、订单通知 | Workers binding 或 REST | 不需要完整邮箱 UI |
把 support@ 变成 Agent 工单 | email() + Agents SDK | 需要人审界面时再看 Agentic Inbox |
| 给自定义域名做一个自托管收件箱 | Routing + DO/D1/R2 最小实现 | Agentic Inbox / Mailflare |
| 保护公司 Outlook / Gmail | 不走 Email Service | Email security |
适合 / 不适合
现在就可以上:
- 入站自动化:工单转化、附件入库、按域名拒收。
- 发往账号内 verified destination addresses 的内部通知:免费且不占月配额。
- Agent 的邮件入口:
onEmail+ 人审后再sendEmail()。
可以接入但要控制预期:
- 面向真实用户的验证码、密码重置、订单通知。Email Sending 仍是 public beta,配额和限流可能调整,先在低风险链路看送达率。
暂不建议:
- 新闻信、促销、批量营销和复杂订阅者分段。官方明确当前只做 transactional email;这些是 Resend、Postmark、Customer.io 的强项。
- 员工邮箱的钓鱼与 BEC 防护。那是 Email security。
- 把 Cloudflare 当完整的企业邮箱托管(日历、通讯录、IMAP 客户端生态)。
- 尚未把 DNS 迁到 Cloudflare 的域名。
- 把
ctx.waitUntil(env.EMAIL.send())当成可靠投递。
和站内其它专题的关系:Email Routing 只是又一种 Worker handler;发信是一种 binding。对象协调仍用 Durable Objects,可靠异步仍用 Queues / Workflows。不要因为 Agentic Inbox 把这些叠在一起,就把“邮箱”实现成一个巨大的 fetch。
落地检查清单
- 确认需求属于 Email Service 还是 Email security。
- 域名使用 Cloudflare DNS;分别执行
wrangler email routing enable与wrangler email sending enable,或在 Dashboard 的 Compute → Email Service 接入。 - 用
wrangler email sending dns get/wrangler email routing dns get核验 MX、SPF、DKIM、DMARC。 - 先验证至少一个 Destination address,在域名发送能力生效前用它做试发。
- 在
wrangler.jsonc只声明send_email,运行npx wrangler types;不要抄未经官方确认的emailhandler binding。 - 入站规则:需要代码处理时指向 Worker,只想进已有 Gmail/Outlook 时指向 Destination address。
- 解析 MIME 前缓冲
message.raw;同时提供html与text。 message.reply()前确认 DMARC、只回一次、发件域名匹配;否则改用EMAIL.send()。- SMTP 使用
smtp.mx.cloudflare.net:465、用户名api_token,不要配 587 STARTTLS。 - 出站成功看 Email Sending 指标,不要被 Routing 摘要里的 dropped 误导。
- 用
wrangler dev的/cdn-cgi/local/email测入站,用自己的邮箱测出站。 - 生产 Agent 回复必须有人审或明确的自动回复策略,并处理 auto-reply 循环。
- 部署 Agentic Inbox 前先配 Cloudflare Access,并阅读其“所有通过 Access 的人能看到全部邮箱”的信任模型。
关联阅读
- Workers:运行时 API、Bindings 与执行模型:
email()是 handler,send_email是 binding。 - Durable Objects 使用方式与接口整理:按邮箱或按 Agent 实例隔离 SQLite。
- Queues:生产者、消费者、批量处理与重试实战:把发信和解析从请求热路径移走。
- Workflows:实例、步骤、事件与恢复 API 实战:需要跨等待和补偿的邮件流程。
- Convex Agent Component 与 Cloudflare Agents SDK:关页后继续生成并恢复聊天:同一套 Agents SDK 在聊天与邮件通道上的状态模型。
参考资料
- Email Service overview,核验于 2026-09-10
- Send emails,2026-06-25
- Route emails
- Workers API,2026-06-25
- REST API,2026-06-09
- SMTP,2026-06-09
- SMTP examples
- SMTP submission changelog,2026-06-08
- User signup flow,2026-06-09
- Email handler,2026-06-15
- Email headers,2026-08-25
- Local development for Email Workers
- Pricing,2026-06-09
- Limits,2026-06-09
- FAQ
- Email Sending public beta,2026-04-16
- Email for agents,2026-04-16
- Announcing Email Service private beta
- Agents SDK email channel
- Email agent example,2026-08-17
- Email security
- Agentic Inbox,stars 核验于 2026-09-10
- Mailflare,stars 核验于 2026-09-10