当使用 Resend 邮件 API 时使用此技能——发送事务性邮件(单封或批量)、通过 Webhook 接收入站邮件、管理邮件模板、跟踪投递事件、管理域名、联系人、广播、Webhook、API 密钥、自动化、事件、查看 API 请求日志,或设置 Resend SDK。当用户提到 Resend 时始终使用此技能,即使对于像“用 Resend 发送邮件”这样的简单任务也是如此——该技能包含关键陷阱(幂等键、Webhook 验证、模板变量语法),可防止常见的生产问题。
Resend
快速发送 — Node.js
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
const { data, error } = await resend.emails.send(
{
from: 'Acme <onboarding@resend.dev>',
to: ['delivered@resend.dev'],
subject: 'Hello World',
html: '<p>Email body here</p>',
},
{ idempotencyKey: `welcome-email/${userId}` }
);
if (error) {
console.error('Failed:', error.message);
return;
}
console.log('Sent:', data.id);
关键陷阱: Resend Node.js SDK 不会抛出异常——它返回 { data, error }。务必显式检查 error,而不是对 API 错误使用 try/catch。
快速发送 — Python
import resend
import os
resend.api_key = os.environ["RESEND_API_KEY"]
email = resend.Emails.send({
"from": "Acme <onboarding@resend.dev>",
"to": ["delivered@resend.dev"],
"subject": "Hello World",
"html": "<p>Email body here</p>",
}, idempotency_key=f"welcome-email/{user_id}")
单封 vs 批量决策
| 选择 | 何时使用 |
|---|---|
单封 (POST /emails) |
1 封邮件,需要附件,需要定时发送 |
批量 (POST /emails/batch) |
2-100 封不同的邮件,无附件,无定时发送 |
批量是原子性的——如果一封邮件验证失败,整个批量都会失败。发送前务必验证。批量不支持附件或 scheduled_at。
幂等键(重试时至关重要)
防止重试失败请求时发送重复邮件:
| 关键事实 | |
|---|---|
| 格式(单封) | <event-type>/<entity-id>(例如 welcome-email/user-123) |
| 格式(批量) | batch-<event-type>/<batch-id>(例如 batch-orders/batch-456) |
| 过期时间 | 24 小时 |
| 最大长度 | 256 个字符 |
| 相同键 + 相同负载 | 返回原始响应,不重新发送 |
| 相同键 + 不同负载 | 返回 409 错误 |
快速接收(Node.js)
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST(req: Request) {
const payload = await req.text(); // 必须使用原始文本,而不是 req.json()
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 仅包含元数据——调用 API 获取正文
const { data: email } = await resend.emails.receiving.get(
event.data.email_id
);
console.log(email.text);
}
return new Response('OK', { status: 200 });
}
关键陷阱: Webhook 负载不包含邮件正文。必须单独调用 resend.emails.receiving.get()。
你需要什么?
| 任务 | 参考 |
|---|---|
| 发送单封邮件 | sending/overview.md — 参数、可投递性、测试 |
| 发送批量邮件 | sending/overview.md → sending/batch-email-examples.md |
| 完整 SDK 示例(Node.js、Python、Go、cURL) | sending/single-email-examples.md |
| 幂等性、重试、错误处理 | sending/best-practices.md |
| 获取、列出、重新安排、取消邮件 | sending/email-management.md |
| 接收入站邮件 | receiving.md — 域名设置、Webhook、附件 |
| 管理模板(CRUD、变量) | templates.md — 生命周期、别名、分页 |
| 设置 Webhook(事件、验证) | webhooks.md — 验证、CRUD、重试计划、IP 白名单 |
| 管理域名(创建、验证、声明、DNS) | domains.md — 区域、TLS、跟踪、声明、功能 |
| 管理联系人(CRUD、属性) | contacts.md — 细分、主题、自定义属性、批量 CSV 导入 |
| 发送广播(营销活动) | broadcasts.md — 生命周期、定时、模板变量 |
| 管理 API 密钥 | api-keys.md — 权限范围、域名限制 |
| 查看 API 请求日志 | logs.md — 列出和检索 API 调用历史、调试 |
| 定义联系人属性 | contact-properties.md — 联系人的自定义字段 |
| 管理细分(联系人分组) | segments.md — 广播定位、联系人分组 |
| 管理主题(订阅) | topics.md — 选择加入/退出偏好、广播过滤 |
| 创建自动化(事件驱动工作流) | automations.md — 步骤、连接、运行、条件 |
| 定义和发送事件(自动化触发器) | events.md — 模式、负载、联系人关联 |
| 安装 SDK(8 种以上语言) | installation.md |
| 设置 AI 代理收件箱 | 安装 agent-email-inbox 技能——涵盖不可信输入的安全级别 |
SDK 版本要求
始终安装最新版本的 SDK。以下是完整功能(发送、接收、Webhook 验证)的最低版本:
| 语言 | 包 | 最低版本 | 安装命令 |
|---|---|---|---|
| Node.js | resend |
>= 6.14.0 | npm install resend |
| Python | resend |
>= 2.21.0 | pip install resend |
| Go | resend-go/v3 |
>= 3.1.0 | go get github.com/resend/resend-go/v3 |
| Ruby | resend |
>= 1.0.0 | gem install resend |
| PHP | resend/resend-php |
>= 1.1.0 | composer require resend/resend-php |
| Rust | resend-rs |
>= 0.20.0 | cargo add resend-rs |
| Java | resend-java |
>= 4.11.0 | 参见 installation.md |
| .NET | Resend |
>= 0.2.1 | dotnet add package Resend |
如果项目已安装 Resend SDK,请检查版本,如果低于最低版本则升级。旧版 SDK 可能缺少
webhooks.verify()、emails.receiving.get()或domains.claims.*。
完整安装命令、语言检测和 cURL 回退请参见 installation.md。
常见设置
API 密钥
存储在环境变量中——切勿硬编码:
export RESEND_API_KEY=re_xxxxxxxxx
在 resend.com/api-keys 获取你的密钥。
检测项目语言
检查这些文件:package.json(Node.js)、requirements.txt/pyproject.toml(Python)、go.mod(Go)、Gemfile(Ruby)、composer.json(PHP)、Cargo.toml(Rust)、pom.xml/build.gradle(Java)、*.csproj(.NET)。
常见错误
| # | 错误 | 修复 |
|---|---|---|
| 1 | 重试时未使用幂等键 | 始终包含幂等键——防止重试时重复发送。格式:<event-type>/<entity-id> |
| 2 | 未验证 Webhook 签名 | 始终使用 resend.webhooks.verify() 验证——未验证的事件不可信 |
| 3 | 模板变量名称不匹配 | 变量名称区分大小写——必须与模板定义完全一致。使用三重大括号 {{{VAR}}} 语法 |
| 4 | 期望 Webhook 负载中包含邮件正文 | Webhook 仅包含元数据——调用 resend.emails.receiving.get() 获取正文内容 |
| 5 | 对 Node.js SDK 错误使用 try/catch | SDK 返回 { data, error }——显式检查 error,不要用 try/catch 包裹 |
| 6 | 对带附件的邮件使用批量发送 | 批量不支持附件——改用单封发送 |
| 7 | 使用虚假邮件测试(test@gmail.com) | 使用 delivered@resend.dev——虚假地址会退信并损害信誉 |
| 8 | 使用草稿模板发送 | 模板必须先发布才能发送——先调用 .publish() |
| 9 | 在同一发送调用中同时使用 html 和 template |
互斥——使用模板时移除 html/text/react |
| 10 | 入站 MX 记录优先级不是最低 | 确保 Resend 的 MX 记录数值最小(优先级最高),否则邮件无法路由 |
| 11 | 从 resend.dev 发送时出现 403 |
默认的 onboarding@resend.dev 是沙箱——只能投递到你的 Resend 账户邮箱。先验证你自己的域名 |
| 12 | 403 域名不匹配 | from 地址的域名必须与已验证的域名完全一致。已验证 send.acme.com 但从 user@acme.com 发送会失败 |
| 13 | 从浏览器调用 Resend API(CORS) | API 不支持 CORS——这是为了保护你的 API 密钥。始终从服务端调用(API 路由、无服务器函数) |
| 14 | 401 restricted_api_key |
在非发送端点(域名、联系人等)上使用了仅发送的 API 密钥。请创建全访问密钥 |
横切关注点
同时发送和接收
自动回复、邮件转发或任何先接收后发送的工作流需要两种能力:
- 首先设置入站域名(参见 receiving.md)
- 设置发送(参见 sending/overview.md)
- 注意:批量发送不支持附件或定时——转发带附件时使用单封发送
AI 代理收件箱
如果你的系统处理不可信的邮件内容并执行操作(退款、数据库更改、转发),请安装 agent-email-inbox 技能。无论是否涉及 AI,任何解释来自外部发件人的自由格式邮件内容的系统都需要安全措施。
营销邮件
此技能中的发送能力适用于事务性邮件(收据、确认、通知)。对于面向大型订阅者列表、包含退订链接和参与度跟踪的营销活动,请使用 Resend Broadcasts——API 请参见 broadcasts.md。
域名预热
新域名必须逐步增加发送量。第 1 天限制:约 150 封邮件(新域名)或约 1,000 封(现有域名)。预热计划请参见 sending/overview.md。
测试
切勿使用真实邮件提供商的虚假地址测试(test@gmail.com、fake@outlook.com)——它们会退信并破坏发件人信誉。
| 地址 | 结果 |
|---|---|
delivered@resend.dev |
模拟成功投递 |
bounced@resend.dev |
模拟硬退信 |
complained@resend.dev |
模拟垃圾邮件投诉 |
抑制列表
Resend 会自动抑制硬退信和垃圾邮件投诉的地址。向被抑制地址发送会触发 email.suppressed Webhook 事件,而不是尝试投递。在控制台 → 抑制中管理。
Webhook 事件类型
| 事件 | 触发条件 |
|---|---|
email.sent |
API 请求成功 |
email.delivered |
到达收件人的邮件服务器 |
email.bounced |
永久拒绝(硬退信) |
email.complained |
收件人标记为垃圾邮件 |
email.opened / email.clicked |
收件人参与 |
email.delivery_delayed |
软退信,Resend 重试 |
email.received |
入站邮件到达 |
domain.* / contact.* |
域名/联系人变更 |
完整详情、签名验证和重试计划请参见 webhooks.md。
错误处理快速参考
| 状态码 | 操作 |
|---|---|
| 400, 422 | 修复请求参数,不要重试 |
| 401 | 检查 API 密钥——restricted_api_key 表示在非发送端点上使用了仅发送密钥 |
| 403 | 验证域名所有权——常见原因:resend.dev 沙箱、from 域名不匹配、域名未验证 |
| 409 | 幂等冲突——使用新密钥或修复负载 |
| 429 | 速率限制——使用指数退避重试(默认速率限制:2 请求/秒) |
| 500 | 服务器错误——使用指数退避重试 |






