群发
群发会向受众中每一位已订阅的联系人发送同一封邮件。SpacePost 会将其拆分为每位联系人一封个性化邮件,添加退订链接和 List-Unsubscribe 标头,跳过被抑制的地址,并像对待其他邮件一样追踪所有内容。
| 状态 | 含义 |
|---|---|
draft |
已创建,可编辑,尚未发送。 |
queued |
已调用 send;正在等待开始时间(立即,或 scheduled_at)。 |
sending |
正在分发给各位联系人。 |
sent |
所有邮件均已被接受投递。已设置 sent_at。 |
failed |
分发已停止,例如因为达到了配额或团队被暂停。 |
canceled |
发送前已取消。 |
import { SpacePost } from "@spacepost/node";
const spacepost = new SpacePost(process.env.SPACEPOST_API_KEY);const audienceId = "0192e1c4-0000-7000-8000-0000000000a1";
// 1. Create a draftconst { data: draft, error } = await spacepost.broadcasts.create({ audienceId, name: "October newsletter", from: "Acme <news@acme.com>", replyTo: "support@acme.com", subject: "What's new at Acme, {{{FIRST_NAME|friend}}}", previewText: "Three things we shipped this month", html: ` <h1>Hi {{{FIRST_NAME|there}}},</h1> <p>Here is what is new.</p> <p><a href="{{{SPACEPOST_UNSUBSCRIBE_URL}}}">Unsubscribe</a></p> `,});if (error) throw new Error(error.message);
// 2. Send it now, or schedule itconst { error: sendError } = await spacepost.broadcasts.send(draft.id, { scheduledAt: "in 1 hour" });if (sendError) throw new Error(sendError.message);
// 3. Check progressconst { data: broadcast } = await spacepost.broadcasts.get(draft.id);console.log(broadcast?.status); // "queued" | "sending" | "sent" | "failed"POST /broadcasts 会创建一份草稿,并返回 { "id": "..." }。
audience_idstring (uuid)必填要发送的目标受众。
fromstring必填已验证域名上的发件人。
subjectstring必填1 到 998 个字符。支持占位符。
htmlstring可选HTML 正文。发送前需要提供 html、text 或两者。
textstring可选纯文本正文。
reply_tostring | string[]可选最多 50 个地址。
preview_textstring可选最多 200 个字符。显示在收件箱中主题的后面;会作为隐藏的预览文本(preheader)插入。
namestring可选最多 100 个字符。仅供内部使用的标签。
PATCH /broadcasts/{id} 接受相同的字段(均为可选),并且只能用于草稿。DELETE /broadcasts/{id} 可用于草稿,以及已安排在未来发送的群发。
# nowcurl -X POST https://api.spacepost.dev/broadcasts/$ID/send -H "Authorization: Bearer $SPACEPOST_API_KEY"
# scheduled (ISO or natural language, up to 30 days ahead)curl -X POST https://api.spacepost.dev/broadcasts/$ID/send \ -H "Authorization: Bearer $SPACEPOST_API_KEY" -H "Content-Type: application/json" \ -d '{ "scheduled_at": "2026-11-01T09:00:00Z" }'await spacepost.broadcasts.send(id); // nowawait spacepost.broadcasts.send(id, { scheduledAt: "in 1 hour" }); // later只有带有 html 或 text 正文的草稿才能发送,且必须使用已验证的域名。响应为 { "id": "..." }。
发送之前,GET /broadcasts/{id}/readiness 会返回一份送达率检查清单(控制台的编辑器中也会显示同样的清单)。这是 SpacePost 的扩展功能,并不属于 Resend 的 API。
{ "ready": true, "checks": [{ "id": "html_size", "level": "warn", "title": "Gmail will clip this message", "detail": "..." }] }| 检查项 | 级别 | 触发条件 |
|---|---|---|
sender_domain |
error | 缺少 from 域名,或该域名尚未验证。 |
dmarc |
warn | _dmarc.<domain> 下没有 v=DMARC1 记录,或查询失败。p=none 视为通过。 |
subject |
error / warn | 为空时为 error。全大写、含 !!! 或 $$$,或超过 90 个字符时为 warn。 |
html_size |
warn | HTML 超过 102 KB,Gmail 会将其截断。 |
images |
warn | 仅有图片,或有四张及以上图片而文字很少。 |
shorteners |
warn | 链接经过 bit.ly、tinyurl.com、t.co 等短链接服务。 |
spam_phrases |
warn | 主题或正文中含有常见的垃圾邮件措辞。 |
unsubscribe |
ok | 当正文中没有占位符时,会自动添加退订页脚,因此该项不会阻止发送。 |
audience |
error | 没有已订阅的联系人。 |
role_addresses |
warn | 超过 20% 的联系人是 info@ 或 admin@ 之类的地址。 |
只要有任何检查项的级别为 error,ready 就是 false。此时发送会以 validation_error(422)失败,并列出需要修复的内容。警告不会阻止发送。
群发邮件还会带有 List-Id 和 Feedback-ID 标头(<broadcast id>:<team id>:broadcast:spacepost),以便 Gmail Postmaster Tools 将投诉归因到某次群发。事务邮件则不带这些标头。
收件人会收到什么
Section titled “收件人会收到什么”- 个性化会应用于
subject、html和text(个性化)。 - 退订: 如果正文中没有
{{{SPACEPOST_UNSUBSCRIBE_URL}}}/{{{RESEND_UNSUBSCRIBE_URL}}}占位符,系统会自动追加退订页脚。List-Unsubscribe和List-Unsubscribe-Post: List-Unsubscribe=One-Click标头则始终会添加。 - 预览文本会成为 HTML 顶部的隐藏预览文本(preheader)。
- 已退订的联系人,以及在你抑制列表中的地址,都会被跳过。
每个收件人都会按一封邮件计入你的套餐配额,新账户还受每天 100 封的沙盒限制。如果发送过程中配额耗尽,群发会以 failed 结束;已经创建的邮件仍会被投递。如果 Worker 重启,分发可以继续进行。
每封群发邮件都是普通邮件:它会出现在 GET /emails 中,在 Webhook 载荷里带有 broadcast_id,也可能退信或被打开。