关于 cloudflare-email-routing
面向 Cloudflare Workers 开发者的 Email Routing 技能,说明如何接收、解析、转发和发送邮件。内容涵盖设置、过滤模式、模板及常见错误处理。
主要功能
- 01Email Workers 收件处理
- 02解析邮件正文与附件
- 03邮件转发与过滤
- 04从 Worker 发送邮件
- 05设置指南与配置模板
- 06常见错误处理
适用场景
- 01将来信整理为支持工单
- 02向用户发送通知邮件
- 03按规则过滤并转发邮件
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill cloudflare-email-routing安装后在 Claude Code 中输入/cloudflare-email-routing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/common-errors.mddns-setup.mdlocal-development.mdsetup-guide.mdtemplates/receive-allowlist.tsreceive-basic.tsreceive-blocklist.tsreceive-reply.tssend-basic.tssend-notification.tswrangler-email.jsonc详细介绍
Cloudflare Email Routing
状态:已可用于生产环境 ✅ | 上次验证:2025-11-18
什么是 Email Routing?
两项功能:
- Email Workers - 接收并处理收到的邮件(允许列表、转发、解析)
- Send Email - 从 Workers 向已验证的地址发送邮件
两项功能均免费,并且可以协同工作,提供完整的电子邮件功能。
快速开始(10 分钟)
第 1 部分:启用 Email Routing
控制面板设置:
- 控制面板 → 域名 → Email → Email Routing
- Enable Email Routing → Add records and enable
- 创建目标地址:
- 自定义:
[email protected] - 目标:你的电子邮件地址
- 通过电子邮件验证
- 自定义:
- ✅ 基本转发已启用
第 2 部分:接收电子邮件(Email Workers)
安装依赖项:
bun add [email protected] [email protected]
创建电子邮件 Worker:
// src/email.ts
import { EmailMessage } from 'cloudflare:email';
import PostalMime from 'postal-mime';
export default {
async email(message, env, ctx) {
const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
console.log('From:', message.from);
console.log('Subject:', email.subject);
// Forward to destination
await message.forward('[email protected]');
}
};
配置 wrangler.jsonc:
{
"name": "email-worker",
"main": "src/email.ts",
"compatibility_date": "2025-10-11", // must be >= 2024-09-23 for nodejs_compat
"compatibility_flags": ["nodejs_compat"] // Required! postal-mime needs Node.js compat
}
部署并连接:
bunx wrangler deploy
控制面板 → Email Workers → Create address → 选择 Worker
第 3 部分:发送电子邮件
添加发送电子邮件绑定:
{
"name": "my-worker",
"main": "src/index.ts",
"compatibility_date": "2025-10-11",
"send_email": [
{
"name": "SES",
"destination_address": "[email protected]"
}
]
}
从 Worker 发送:
import { EmailMessage } from 'cloudflare:email';
import { createMimeMessage } from 'mimetext';
const msg = createMimeMessage();
msg.setSender({ name: 'App', addr: '[email protected]' });
msg.setRecipient('[email protected]');
msg.setSubject('Hello!');
msg.addMessage({
contentType: 'text/plain',
data: 'Email body here'
});
const message = new EmailMessage(
'[email protected]',
'[email protected]',
msg.asRaw()
);
await env.SES.send(message);
加载 references/setup-guide.md 查看完整操作指南。
重要规则
始终执行 ✅
- 启用
compatibility_flags: ["nodejs_compat"]以使用 postal-mime(要求compatibility_date >= 2024-09-23) - 发送前验证目标地址
- 使用 postal-mime 解析电子邮件内容
- 使用 mimetext 创建电子邮件
- 检查 message.from 以应用允许列表
- 使用 message.forward() 转发(不要手动转发)
- 处理错误(电子邮件投递可能失败)
- 使用真实电子邮件测试(不只在控制面板中测试)
- 添加 MX 记录(通过控制面板自动完成)
- 记录电子邮件活动以便调试
绝不执行 ❌
- 绝不跳过
nodejs_compat(postal-mime 需要 Node.js 兼容性标志) - 未经验证绝不发送(投递会失败)
- 绝不在公开代码中硬编码电子邮件地址
- 绝不跳过解析(原始电子邮件很难处理)
- 绝不忽略垃圾邮件(请实现允许列表和阻止列表)
- 绝不超过 Gmail 限制(每天向 Gmail 发送 500 封邮件)
- 绝不跳过错误处理(电子邮件可能发送失败)
- 绝不手动修改 DNS(请使用控制面板)
- 绝不在日志中暴露电子邮件内容(个人身份信息)
- 绝不假定邮件会立即送达(电子邮件是异步的)
常见模式
允许列表
const allowlist = ['[email protected]'];
if (!allowlist.includes(message.from)) {
message.setReject('Not on allowlist');
return;
}
await message.forward('[email protected]');
阻止列表
const blocklist = ['[email protected]'];
if (blocklist.includes(message.from)) {
message.setReject('Blocked');
return;
}
await message.forward('[email protected]');
回复电子邮件
const msg = createMimeMessage();
msg.setSender({ addr: '[email protected]' });
msg.setRecipient(message.from);
msg.setSubject(`Re: ${email.subject}`);
msg.addMessage({
contentType: 'text/plain',
data: 'Thanks for your email!'
});
const reply = new EmailMessage(
'[email protected]',
message.from,
msg.asRaw()
);
await env.SES.send(reply);
解析附件
const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
for (const attachment of email.attachments) {
console.log('Filename:', attachment.filename);
console.log('Type:', attachment.mimeType);
console.log('Size:', attachment.content.byteLength);
}
自定义路由逻辑
async email(message, env, ctx) {
const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
// Route based on subject
if (email.subject.includes('[Support]')) {
await message.forward('[email protected]');
} else if (email.subject.includes('[Sales]')) {
await message.forward('[email protected]');
} else {
await message.forward('[email protected]');
}
}
电子邮件消息属性
收到的消息(ForwardableEmailMessage)
message.from // Sender email
message.to // Recipient email
message.headers // Email headers
message.raw // Raw email stream
message.rawSize // Size in bytes
// Methods
message.forward(address) // Forward to address
message.setReject(reason) // Reject email
已解析的电子邮件(PostalMime)
email.from // { name, address }
email.to // [{ name, address }]
email.subject // Subject line
email.text // Plain text body
email.html // HTML body
email.attachments // Array of attachments
email.headers // All headers
可避免的 5 个常见错误
- “Email Trigger not available”:启用
compatibility_flags: ["nodejs_compat"](且compatibility_date >= 2024-09-23) - 目标地址未验证:验证所有发送目标
- Gmail 速率限制:每天最多向 Gmail 发送 500 封邮件
- SPF permerror:使用控制面板配置 DNS
- Worker 调用失败:检查日志中的解析错误
使用场景
使用场景 1:支持工单系统
async email(message, env, ctx) {
const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
// Create ticket in database
await env.DB.prepare(
'INSERT INTO tickets (email, subject, body, created_at) VALUES (?, ?, ?, ?)'
).bind(message.from, email.subject, email.text, Date.now()).run();
// Send confirmation
const msg = createMimeMessage();
msg.setSender({ addr: '[email protected]' });
msg.setRecipient(message.from);
msg.setSubject('Ticket Created');
msg.addMessage({
contentType: 'text/plain',
data: 'Your support ticket has been created.'
});
const confirmation = new EmailMessage(
'[email protected]',
message.from,
msg.asRaw()
);
await env.SES.send(confirmation);
}
使用场景 2:电子邮件通知
export default {
async fetch(request, env, ctx) {
// User signup
const { email, name } = await request.json();
const msg = createMimeMessage();
msg.setSender({ name: 'App', addr: '[email protected]' });
msg.setRecipient(email);
msg.setSubject('Welcome!');
msg.addMessage({
contentType: 'text/html',
data: `<h1>Welcome, ${name}!</h1>`
});
const message = new EmailMessage(
'[email protected]',
email,
msg.asRaw()
);
await env.SES.send(message);
return new Response('Welcome email sent!');
}
};
使用场景 3:带过滤功能的电子邮件转发
async email(message, env, ctx) {
const parser = new PostalMime.default();
const email = await parser.parse(await new Response(message.raw).arrayBuffer());
// Filter spam keywords
const spamKeywords = ['viagra', 'lottery', 'prince'];
const isSpam = spamKeywords.some(keyword =>
email.subject.toLowerCase().includes(keyword) ||
email.text.toLowerCase().includes(keyword)
);
if (isSpam) {
message.setReject('Spam detected');
return;
}
await message.forward('[email protected]');
}
何时加载参考资料
在以下情况下加载 references/setup-guide.md:
- 首次设置 Email Routing
- 配置 MX 记录
- 设置电子邮件 Worker
- 配置发送电子邮件绑定
- 需要完整操作指南
使用捆绑的资源
参考资料(references/):
setup-guide.md- 完整的设置指南(启用路由、电子邮件 Worker、发送电子邮件)common-errors.md- 已记录的全部 8 个错误及其解决方案和预防措施dns-setup.md- MX 记录、SPF、DKIM 配置指南local-development.md- 本地测试和开发模式
模板(templates/):
receive-basic.ts- 基础电子邮件接收 Workerreceive-allowlist.ts- 电子邮件允许列表实现receive-blocklist.ts- 电子邮件阻止列表实现receive-reply.ts- 自动回复电子邮件 Workersend-basic.ts- 基础发送电子邮件示例send-notification.ts- 通知电子邮件模式wrangler-email.jsonc- 用于电子邮件路由的 Wrangler 配置
官方文档
- 电子邮件路由:https://developers.cloudflare.com/email-routing/
- 电子邮件 Worker:https://developers.cloudflare.com/email-routing/email-workers/
- 发送电子邮件:https://developers.cloudflare.com/email-routing/email-workers/send-email-workers/
有疑问?遇到问题?
- 查看
references/setup-guide.md了解完整设置流程 - 确认 wrangler.jsonc 中的
compatibility_flags: ["nodejs_compat"] - 确认目标地址已通过验证
- 检查日志中的错误
评论
支持 Markdown