Sign inGet started

从其他服务商迁移

使用本指南将生产邮件从其他服务商迁移过来。映射发送请求、发布 DNS 记录、导入屏蔽列表、转换 Webhook 事件,并在将生产流量导向 Bird 之前测试集成。
迁移清单:
  1. 映射你的发送调用POST /v1/email/messages
  2. 重新指向发送域名和 DNS
  3. 导入屏蔽列表
  4. 将 Webhook 切换到我们的事件词汇
  5. 在正式切换前在邮件沙箱中验证
步骤 1、3 和 4 取决于你正在离开的服务商。你的服务商指南包含逐字段的载荷映射、屏蔽列表的导出位置以及 Webhook 事件名称对照表。

1. 映射发送调用

我们有一个单次发送端点 POST /v1/email/messages。你构建一个扁平的 JSON 载荷(无 personalizations 包装,无 MIME 组装),包含 fromto/cc/bcc 数组、subjecthtml 和/或 text、可选的 reply_to 列表,以及用于自定义邮件请求头的 headers。成功发送返回 202 Accepted,附带以 em_ 为前缀的消息 ID。投递结果通过 Webhook 和读取端点异步到达。完整载荷(包含每个字段的上限和默认值)见发送邮件。从你当前载荷的逐字段映射见你的服务商指南。如果你的应用当前通过 SMTP 提交,可能完全不需要迁移调用:我们接受 SMTP 提交到同一管道,这一步只需更换凭证即可。
使用 tags 作为消息列表、分析和仪表盘汇总中的筛选维度。使用 metadata 存储结构化上下文,Bird 会将其保存在消息上、在 API 读取时返回,并在 Webhook 事件中回传。限制详情见 Tags vs metadata
在迁移代码之前,注意以下差异:
  • 定时发送、存储模板和附件均可迁移。 使用 scheduled_at 进行定时发送。使用 template 代替内联内容来引用存储模板。将文件映射到 attachments 数组。
  • 被屏蔽的收件人会被显式拒绝。 被屏蔽的地址仍会获得一个 recipient_id,并出现在消息的收件人列表中,状态为 rejected,附带一个 email.rejected 事件(rejection_reason: recipient_suppressed),不会被静默丢弃。即使所有收件人都被屏蔽,请求仍会以 202 被接受,每个收件人都会返回拒绝状态。详见屏蔽列表
  • 为事务性邮件设置 category: "transactional" 发送默认使用 marketing,类别控制屏蔽策略:marketing 会因投诉和退订而阻止发送,transactional 则会绕过它们继续投递。新闻通讯和营销活动使用默认值即可正确处理。将收据、密码重置和类似的事务性邮件标记为 transactional,以免被退订所拦截。

2. 重新指向域名和 DNS

使用 POST /v1/email/domains 或在 Email > Domains 中注册每个发送域名,然后发布 dns_records 中的记录。DKIM、return-path CNAME 和 DMARC 策略是发送的前置条件。已有的 DMARC 记录(包括父域上的)也满足要求。跟踪 CNAME 仅用于品牌化的打开和点击跟踪。发送域名涵盖了记录、验证生命周期和区域模型。如果你的 DNS 提供商要求拆分 DKIM 值,使用 DNS 记录拆分工具;如果需要策略,使用 DMARC 策略生成器
大多数服务商要求你首先添加的一条记录在这里被有意省略了:你不需要在域名顶点发布 SPF 记录。SPF 针对 envelope-from 域名进行验证,而 return-path CNAME 已将其指向我们,因此 SPF 无需修改你的顶点即可通过并对齐。如果你的旧服务商曾让你在顶点 SPF 记录中添加 include:,请在过渡期间保留它,切换完成后再移除。它既不会帮助也不会影响通过我们发送的邮件,移除后可释放顶点 SPF 允许的 10 次 DNS 查找中的一次。完整说明见 DKIM、SPF 和 DMARC
你可以在旧服务商的记录仍然生效时发布我们的记录。DKIM 记录使用我们的选择器。return-path 和跟踪 CNAME 是你选择的新主机名,你现有的 DMARC 记录无需修改即可满足要求。两个服务商可以同时进行身份验证,直到你准备好切换流量。域名状态是按区域的,因此需要在你发送邮件的每个区域注册域名。

3. 导入屏蔽列表

在通过我们发送生产流量之前迁移你的屏蔽列表。否则,你的首批发送会到达那些在旧服务商已经产生退信或投诉的地址,从而损害你正试图保护的信誉。
从当前服务商导出列表(你的服务商指南中有具体的端点),然后使用 POST /v1/email/suppressions 将每个地址添加到这里:
代码示例
while read -r address; do
  curl -s -X POST https://us1.platform.bird.com/v1/email/suppressions \
    -H "Authorization: Bearer $BIRD_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"email\": \"$address\"}"
done < suppressions.txt
关于此导入方式需要了解两点:
  • 每次请求只能导入一个地址。 屏蔽列表 API 是单条目 CRUD,因此大量列表需要循环遍历导出的地址。调用是幂等的(新记录返回 201,地址已被手动屏蔽时返回 200 及现有记录),因此重新执行未完成的导入是安全的。
  • 导入的地址会获得 reason: manualapplies_to: all,这会阻止所有类别的发送,包括事务性邮件。这比原生投诉记录更严格,后者仅阻止非事务性发送。如果你需要针对特定地址使用按类别区分的行为,请参阅屏蔽列表中的原因分类。
今后你无需自行管理退信:我们会自动屏蔽硬退信和投诉,并触发 email_suppression.created 以便你的系统同步屏蔽列表。退订会被记录为声明的偏好设置,通过 email.unsubscribedemail.list_unsubscribed 同步,而非通过屏蔽事件。

4. 切换 Webhook

使用 POST /v1/webhooks 注册一个端点,并为其订阅明确的事件类型列表。我们的事件名称遵循 resource.action:正常路径为 email.acceptedemail.processedemail.delivered,其余由 email.deferredemail.bouncedemail.complainedemail.rejectedemail.openedemail.clicked 及退订事件对覆盖。从你当前服务商词汇的事件名称对照见你的服务商指南。每个事件的载荷结构见事件参考
关联映射可以直接复用。每个事件都包含 email_idrecipient_idworkspace_id 标识符,还会回传发送请求中的 tagsmetadata。这与旧服务商通过载荷回传返回的上下文相同,无需额外查询。在发送时将你的内部 ID 放入 metadata,即可直接从每个事件中读取。
我们按照 Standard Webhooks 规范对投递进行签名,使用三个请求头:webhook-idwebhook-timestampwebhook-signature,通过对 {id}.{timestamp}.{raw body} 做 HMAC-SHA256 计算。如果你已经在其他平台验证过 Standard Webhooks 投递,完全相同的验证代码在这里同样适用。否则,验证方法、重试计划和重放工具见 Webhooks 与事件。投递是至少一次且无序的,因此需要基于 webhook-id 去重,并按载荷中的 timestamp 排序,这与你当前处理程序应有的做法一致。

5. 切换前在沙箱中验证

在迁移生产流量之前,将你的完整集成(迁移后的发送调用、Webhook 处理程序、屏蔽列表同步)在邮件沙箱中运行一遍。沙箱发送使用 messagebird.dev 的魔法地址,并通过真实生产管道处理:相同的 202、相同的事件序列、相同的签名 Webhook 投递,但不会到达任何收件箱或影响你的信誉。
最小化的切换前冒烟测试:
  1. 发送到 delivered@messagebird.dev,断言你的处理程序处理了 email.acceptedemail.processedemail.delivered
  2. 发送到 bounce@messagebird.dev,断言你的退信处理在 email.bounced 上触发(模拟退信不会写入你的屏蔽列表,因此该地址可以继续使用)。
  3. 发送到 suppressed@messagebird.dev,断言你处理了 email.accepted 后跟 email.rejected,之后没有 email.processed 或投递事件。这就是生产环境中每个被屏蔽收件人产生的事件形态;rejection_reason: recipient_suppressed 详情在收件人记录和事件的 API 中。
  4. 发送一条 category: "marketing" 消息,确认类别在消息读取中按预期显示。
使用 +label 子地址(bounce+cutover-test@messagebird.dev)来关联测试用例。完整地址会出现在你的事件中。冒烟测试通过后,切换流量。将你的应用指向我们,并保留旧服务商的 DNS,直到你的域名在这里显示为 capabilities.sending 已验证。在仪表盘和 Webhook 流中监控正式投递的最初几个小时。

从特定服务商迁移

  • SendGridpersonalizations → 扁平载荷,categories/custom_argstags/metadatadroppedemail.rejected 的等价关系
  • Mailguno:*/v:*/h:* 参数 → 一级字段,bounces/complaints/unsubscribes 导出
  • Amazon SES:SendEmail v2 → 单一端点,configuration sets → 按消息的跟踪标志,SNS → 签名 Webhook
  • Resend:几乎相同的载荷结构,Svix 签名 Webhook → Standard Webhooks
  • Postmark:逗号分隔的收件人 → 数组,按流的屏蔽列表导出,无签名 Webhook → 签名 Webhook
  • Brevo:地址对象 → 纯地址,两个独立的阻止列表需导出,paramstemplate.parameters
  • MailerSend:五个屏蔽列表(其中临时列表无需迁移),personalization → 按发送参数
  • MailjetMessages 数组 → 单一扁平载荷,EventPayloadmetadata,阻止列表导出
  • Mandrillmessage 包装和 body 认证 → 扁平载荷和 bearer 认证,rejection blacklist 导出

后续步骤