跳转到内容

群发

群发会向受众中每一位已订阅的联系人发送同一封邮件。SpacePost 会将其拆分为每位联系人一封个性化邮件,添加退订链接和 List-Unsubscribe 标头,跳过被抑制的地址,并像对待其他邮件一样追踪所有内容。

状态 含义
draft 已创建,可编辑,尚未发送。
queued 已调用 send;正在等待开始时间(立即,或 scheduled_at)。
sending 正在分发给各位联系人。
sent 所有邮件均已被接受投递。已设置 sent_at。
failed 分发已停止,例如因为达到了配额或团队被暂停。
canceled 发送前已取消。
broadcast.ts
import { SpacePost } from "@spacepost/node";
const spacepost = new SpacePost(process.env.SPACEPOST_API_KEY);
const audienceId = "0192e1c4-0000-7000-8000-0000000000a1";
// 1. Create a draft
const { 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 it
const { error: sendError } = await spacepost.broadcasts.send(draft.id, { scheduledAt: "in 1 hour" });
if (sendError) throw new Error(sendError.message);
// 3. Check progress
const { 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} 可用于草稿,以及已安排在未来发送的群发。

终端窗口
# now
curl -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" }'

只有带有 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 将投诉归因到某次群发。事务邮件则不带这些标头。

  • 个性化会应用于 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,也可能退信或被打开。