海外邮件送达率基础:域名、DNS 与冷启动
邮件是产品基础设施,不是上线后补的配件
我做过的几个出海产品里,邮件送达率这个问题每次都会在某个阶段冒出来。最早一次是做 SaaS 工具,上线两周后陆续有用户反馈收不到重置密码邮件。去 Resend 后台看,邮件状态显示「delivered」,但用户邮箱里就是没有。后来查才发现,邮件安静地躺进了 Gmail 的垃圾文件夹——SPF 记录没配,DKIM 签名缺失,DMARC 策略是空的。
这类问题不挑产品规模。独立开发者的第一个 MVP 会碰到,公司级产品换域名一样会碰到。根源在于邮件送达率不是一个「配置完就不管」的设置,而是一个需要从头规划、持续维护的基础设施。Google 从 2024 年 2 月起对日发送量超过 5000 封的批量发件人强制执行 SPF、DKIM、DMARC 验证和一键退订要求;Yahoo 同期跟进;Microsoft 在 2025 年 5 月也加严了发件人验证标准。这不是最佳实践建议,而是准入门槛。
根据 Validity 发布的 2025 年基准报告,全球邮件的平均收件箱放置率约 75.6%,Gmail 的收件箱放置率从 2024 年 Q1 到 2026 年 Q1 从 58.72% 降到 53.70%,过滤越来越严格。电商类邮件的主收件箱放置率只有 2.7%–4.4%,绝大多数被归入 Promotions 标签页。这意味着,如果邮件认证和发信习惯没做好,产品发出的邮件很可能连被用户看到的機會都没有。
这篇文章把海外邮件送达率拆成三个层面来聊:DNS 认证配置、冷启动策略和日常维护。每个层面都会给出具体的操作和代码。
邮件认证的三根支柱:SPF、DKIM、DMARC
邮件认证的本质是解决一个问题:收件方怎么确认这封邮件确实是你发的,没有被中间人篡改?
这个机制由三个协议协作完成,各自解决不同层面的问题。
SPF:声明谁有资格代我发信
SPF(Sender Policy Framework,RFC 7208)通过在 DNS 里发布一条 TXT 记录,列出被授权代表该域名发信的 IP 地址或服务。收件方收到邮件后,会查询发件人域名的 SPF 记录,比对接件 IP 是否在授权列表里。
SPF 的记录格式像这样:
v=spf1 include:_spf.google.com include:sendgrid.net ~allinclude 指令把第三方服务的 SPF 记录引入进来。~all 表示「不在列表里的 IP,软拒绝」;-all 表示「硬拒绝」。
SPF 有一个硬性限制:一次 SPF 验证最多只做 10 次 DNS 查询。如果你的 include 链条太深或者太多,超出 10 次查询的部分会被直接忽略,导致合法邮件被判定为 SPF 失败。这个限制在 RFC 7208 Section 4.6.4 里明确定义了。
DKIM:给邮件加上不可篡改的签名
DKIM(DomainKeys Identified Mail,RFC 6376)的思路不同。它在每封邮件的 Header 里加一个加密签名,收件方通过 DNS 里发布的公钥来验证这个签名。签名覆盖了邮件的正文和指定的 Header 字段,任何中间篡改都会导致验证失败。
DKIM 的好处是没有 SPF 那样的 10 次查询限制,也不受邮件转发影响——转发过程中 IP 可能变,但签名不会失效。
现在主流邮件服务商推荐使用 Ed25519 算法(RFC 8463)替代传统的 RSA-1024。Ed25519 签名更短、验证更快、安全性更高。
DMARC:告诉收件方怎么处理验证失败的邮件
DMARC(Domain-based Message Authentication, Reporting, and Conformance,RFC 7489)是 SPF 和 DKIM 的上层策略。它做两件事:
- 声明策略:告诉收件方,如果一封邮件 SPF 和 DKIM 都验证失败,该怎么处理——放行(
none)、进垃圾箱(quarantine)还是直接拒收(reject)。 - 接收报告:收件方会按 DMARC 记录里配置的地址发送聚合报告(Aggregate Report)和取证报告(Forensic Report),告诉你哪些邮件通过了验证、哪些失败了、来自哪些 IP。
DMARC 还有一个关键机制叫「对齐」(Alignment)。即使 SPF 或 DKIM 单独验证通过了,如果验证使用的域名和邮件 From 头里的域名不一致,DMARC 仍然会判定为失败。这防止了攻击者用子域名通过 SPF 但伪造主域名 From 头的绕过方式。
三个协议的协作关系:
| 协议 | 解决什么问题 | 验证依据 | 主要限制 |
|---|---|---|---|
| SPF | 授权发信 IP | DNS TXT 记录中的 IP 列表 | 10 次 DNS 查询上限;转发后 IP 变化会导致失败 |
| DKIM | 邮件完整性 | Header 中的加密签名 + DNS 公钥 | 签名可能被中间件修改 Header 破坏;RSA-1024 已不推荐 |
| DMARC | 策略执行 + 可见性 | 依赖 SPF 和/或 DKIM 的对齐结果 | 策略强度需要逐步提升,直接上 reject 有误杀风险 |
三者不是三选一,而是必须全部配置。Google 的发件人指南明确要求:批量发件人必须同时具备 SPF、DKIM 和 DMARC,且 DMARC 验证必须通过(即 SPF 或 DKIM 至少一个通过并与 From 域名对齐)。
发信域名的选择:别用服务商的默认域名
Resend、SendGrid、Postmark 这类邮件服务商都会提供一个默认发信域名,比如 resend.dev 或 u2317842.wl.sendgrid.net。用这些域名发信在开发阶段没问题,但生产环境必须换自己的域名。原因有三个:
第一,默认域名是共享的。同一个域名下可能有成百上千个发件人,其中任何一个人的发信行为出了问题(高退信率、高投诉率),整个域名的信誉都会受影响,你的邮件送达率跟着遭殃。
第二,默认域名随时可能变。服务商调整基础设施、更换 IP 池,你的 DNS 记录要跟着改,如果忘了改,邮件就发不出去了。
第三,用户在收件箱里看到的发件人地址直接影响打开率。[email protected] 比 [email protected] 看起来可信得多。
我的做法是注册一个专门的发信子域名,比如 mail.yourproduct.com,和主域名 yourproduct.com 分开。这样做的好处是:即使发信域名因为某些原因被标记,不会影响主站 SEO 和品牌形象;同时主域名的 DNS 记录保持干净,不会被大量 include 指令拖累。
| 方案 | 适合场景 | 送达率风险 | 品牌感知 |
|---|---|---|---|
| 服务商默认域名 | 开发测试、极低量发送 | 高(共享信誉) | 差 |
| 主域名直接发信 | 小规模、初期验证 | 中(影响主域名) | 好 |
发信子域名(mail.) | 生产环境推荐 | 低(隔离风险) | 好 |
| 完全独立域名 | 大规模、多产品线 | 最低 | 中性 |
案例一:SPF 的 include 链条爆了
我之前接手一个项目,用的是 SendGrid 发信。DNS 里已经有 Google Workspace 的 SPF(用于客服邮箱),加上 SendGrid 的 include,又加了一个内部系统的 include。看起来没问题,但 SendGrid 自己的 SPF 记录里又 include 了多个子服务。算上 Google Workspace 的嵌套查询,总 DNS 查询次数超过了 10 次上限。
结果是 SPF 验证在超过 10 次查询后直接返回 permerror,Gmail 把 SPF 视为失败。
排查过程:用 dig 命令逐步展开 SPF 链条,数清楚每一条 include 和 redirect 引入的查询数。
# 错误的 SPF 记录——include 嵌套超过 10 次 DNS 查询
# v=spf1 include:_spf.google.com include:sendgrid.net include:mail.zendesk.com include:support.freshdesk.com ~all
# _spf.google.com 内部有 4 次查询
# sendgrid.net 内部有 3 次查询
# zendesk.com 内部有 2 次查询
# freshdesk.com 内部有 3 次查询
# 总计 12 次,超出 10 次上限修复方式是 flattening——把不再直接使用的第三方服务从 SPF 记录里移除,只保留实际在用的:
# 修复后:只保留实际使用的服务
# 移除了 freshdesk(已不用),把 zendesk 的 IP 直接写进来减少嵌套
v=spf1 include:_spf.google.com include:sendgrid.net ip4:192.0.78.0/24 ip4:192.0.80.0/24 ~all也可以考虑用 SPF flatten 工具定期把嵌套的 include 展平为直接的 ip4/ip6 记录,把 DNS 查询次数控制在 10 以内。这个操作需要定期做,因为第三方服务的 IP 池会变化。
案例二:新域名第一天发了两万封营销邮件
这件事发生在一个电商产品上线的时候。用户注册后积累了大概两万封待发的欢迎邮件和促销通知,运营团队希望上线第一天全部发出去。我当时提醒过风险,但业务侧觉得「都是真实注册用户,没关系」。
结果是:Gmail 和 Outlook 在第一天就把这个域名的邮件大量拦截。后续三天里,即使用户主动在后台点了「重发确认邮件」,邮件也进不了 Gmail 收件箱。域名信誉在头 72 小时内就被打上了负面标签,花了将近六周才恢复到正常水平。
这个问题的根源是没有做域名预热(warm-up)。新域名、新 IP 在邮件服务商眼里是一张白纸,收件方没有任何历史数据来判断你是不是合法发件人。如果突然从 0 跳到高发送量,收件方的过滤系统会把这当作垃圾邮件或钓鱼邮件的典型特征。
预热的基本原则是:从极少量开始,每天递增,持续 4–8 周。
AWS 在 Amazon SES 迁移指南 中建议的预热节奏是:第一周每天发送量控制在目标量的 5%–10%,每周翻倍,直到第四周达到正常水平。
更具体的做法:
// 预热期间的发送控制逻辑(伪代码)
// 错误做法:一次性全量发送
// await sendBatch(allUsers) // ❌ 新域名直接炸
// 正确做法:按阶段递增
const warmupSchedule = [
{ week: 1, dailyLimit: 50, priority: 'highly_engaged' },
{ week: 2, dailyLimit: 200, priority: 'recently_active' },
{ week: 3, dailyLimit: 1000, priority: 'active' },
{ week: 4, dailyLimit: 5000, priority: 'all' },
]
async function warmupSend(users: User[], week: number) {
const schedule = warmupSchedule[week - 1]
const eligible = users
.filter(u => u.segment === schedule.priority)
.slice(0, schedule.dailyLimit)
// 按邮箱服务商分组,均匀分配发送时间
const grouped = groupByProvider(eligible)
for (const [provider, group] of Object.entries(grouped)) {
// 每个邮箱服务商(Gmail、Outlook、Yahoo)独立限速
await sendWithRateLimit(group, {
perHour: Math.ceil(schedule.dailyLimit / 8),
perProvider: true,
})
}
}预热阶段还有一个关键点:只发给最活跃的用户。这些用户打开率高、不太可能标记为垃圾邮件,能给域名积累正面信号。把沉睡用户、僵尸账号留到后面信誉建立之后再逐步触达。
案例三:事务邮件和营销邮件混在一起发
一个 SaaS 产品的注册验证邮件、密码重置邮件和周报推送走的是同一个发信域名、同一个 IP 池。周报的打开率很低(不到 5%),退订投诉率偏高。结果连注册验证邮件也开始进垃圾箱。
这个问题的根源是事务邮件(transactional)和营销邮件(marketing)共享了同一个发信信誉。当营销邮件的互动数据差时,域名整体信誉下降,事务邮件跟着遭殃。
Postmark 在业界被认为送达率最高的原因之一就是它严格分离了事务邮件流和广播邮件流——两种邮件走不同的 Message Stream,各自维护独立的信誉。
// 错误做法:事务邮件和营销邮件混用同一个流
await resend.emails.send({
from: '[email protected]',
to: user.email,
subject: '密码重置', // 事务邮件
// 和周报走同一个域名、同一个 IP、同一个信誉池
})
await resend.emails.send({
from: '[email protected]',
to: user.email,
subject: '本周产品更新', // 营销邮件
// 低打开率拖累了域名信誉
})
// 正确做法:域名级别分离
// 事务邮件用 mail.myapp.com
await resendTransactional.emails.send({
from: '[email protected]', // 独立发信域名
to: user.email,
subject: '密码重置',
// 高打开率,建立独立正面信誉
})
// 营销邮件用 newsletter.myapp.com
await resendMarketing.emails.send({
from: '[email protected]', // 独立发信域名
to: user.email,
subject: '本周产品更新',
// 即使打开率低,也只影响自己的域名信誉
})| 邮件类型 | 典型场景 | 打开率预期 | 发信域名 | 优先级 |
|---|---|---|---|---|
| 事务邮件 | 验证、重置密码、账单 | 60%–90% | mail.domain.com | 最高 |
| 通知邮件 | 评论回复、状态变更 | 20%–40% | mail.domain.com | 高 |
| 营销邮件 | 周报、促销、新功能 | 15%–25% | newsletter.domain.com | 中 |
| 冷启动邮件 | 用户召回、再营销 | 5%–10% | newsletter.domain.com | 低 |
如果预算有限、不想维护两个发信域名,至少要在 Postmark 或 SendGrid 里用 Message Stream 把事务邮件和营销邮件分开。同一个域名下,不同的 Stream 维护不同的追踪数据,能部分隔离信誉影响。
邮件模板和内容对送达率的影响
技术认证做好了,邮件内容本身也会影响送达率。收件方的过滤系统不只看 SPF/DKIM/DMARC,还会分析邮件内容的特征。
几个需要注意的点:
纯图片邮件容易被拦截。如果邮件正文只有一张大图、没有文本内容,过滤器会认为这是试图绕过文本检测的垃圾邮件。正确的做法是图文混排,保持合理的文字比例。
Subject 行避免触发词。「FREE」「100% OFF」「ACT NOW」「URGENT」这类词在营销邮件里会提高垃圾邮件评分。不是说不能用,而是不要堆叠使用。
HTML 结构要干净。使用 <table> 布局而不是 <div> + CSS(邮件客户端对 CSS 的支持参差不齐),不要用 base64 编码的图片嵌入正文,避免 JavaScript 和表单元素。
// 错误做法:纯图片邮件
const badEmail = {
html: `
<img src="https://cdn.myapp.com/promo-banner.jpg" width="600" />
<!-- 没有任何文本内容,容易被标记为垃圾邮件 -->
`,
}
// 正确做法:图文混排,有文本回退
const goodEmail = {
html: `
<div style="font-family: -apple-system, sans-serif; max-width: 600px;">
<h2 style="color: #1a1a1a;">本周产品更新</h2>
<p>Hi {{name}},</p>
<p>这周我们上线了三个新功能:</p>
<ul>
<li>仪表盘支持自定义布局</li>
<li>导出报告新增 PDF 格式</li>
<li>团队协作支持 @提及</li>
</ul>
<a href="{{ctaUrl}}" style="display: inline-block; padding: 12px 24px; background: #2563eb; color: white; text-decoration: none; border-radius: 6px;">
查看完整更新
</a>
<p style="color: #666; font-size: 12px; margin-top: 24px;">
不想再收到这类邮件?<a href="{{unsubscribeUrl}}">取消订阅</a>
</p>
</div>
`,
text: `本周产品更新\n\nHi {{name}},\n\n这周我们上线了三个新功能...`, // 纯文本回退版本
}退订链接是硬性要求。Google 和 Yahoo 从 2024 年 6 月起要求批量发件人支持一键退订(RFC 8058),不仅要在邮件正文里放退订链接,还要在 Header 里加 List-Unsubscribe 和 List-Unsubscribe-Post 字段。
// 错误做法:只在正文里放退订链接
const missingHeader = {
to: user.email,
subject: '本周更新',
html: '<a href="https://myapp.com/unsubscribe?token=xxx">取消订阅</a>',
// 缺少 List-Unsubscribe Header
}
// 正确做法:正文 + Header 双通道退订
const withUnsubscribeHeader = {
to: user.email,
subject: '本周更新',
html: '<a href="https://myapp.com/unsubscribe?token=xxx">取消订阅</a>',
headers: {
'List-Unsubscribe': '<https://myapp.com/unsubscribe?token=xxx>',
'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
},
}DMARC 策略的渐进式部署
DMARC 的三个策略级别——none、quarantine、reject——不是选一个就完事了。正确的做法是分阶段推进。
| 阶段 | DMARC 策略 | 持续时间 | 目标 |
|---|---|---|---|
| 监控期 | p=none | 2–4 周 | 收集报告,了解发信来源 |
| 警告期 | p=quarantine; pct=10 | 2–4 周 | 对 10% 的失败邮件执行隔离 |
| 扩大期 | p=quarantine; pct=50 | 2–4 周 | 扩大到 50% |
| 强制执行 | p=reject | 长期 | 100% 拒绝未通过认证的邮件 |
# 第一阶段:监控模式,只收集报告不执行任何动作
_dmarc.mail.myapp.com. TXT "v=DMARC1; p=none; rua=mailto:[email protected]; ruf=mailto:[email protected]; adkim=s; aspf=s"
# 第二阶段:开始隔离,先小比例
_dmarc.mail.myapp.com. TXT "v=DMARC1; p=quarantine; pct=10; rua=mailto:[email protected]; adkim=s; aspf=s"
# 第三阶段:全面拒绝
_dmarc.mail.myapp.com. TXT "v=DMARC1; p=reject; pct=100; rua=mailto:[email protected]; adkim=s; aspf=s"rua 是聚合报告的接收地址,ruf 是取证报告的接收地址。adkim=s 和 aspf=s 表示严格对齐模式——要求 DKIM 签名域名和 SPF 验证域名必须和 From 域名完全一致,子域名不算通过。
DMARC 报告会告诉你:有哪些 IP 在代表你的域名发信、通过了哪些验证、来自哪些收件方。这些数据对发现未授权的发信来源和排查配置问题非常有价值。
ESP 选型对比
不同的邮件服务商在送达率、API 体验和定价上差异不小。以下是我实际用下来或者调研过的几个主要选项:
| 维度 | Postmark | Resend | SendGrid | Amazon SES |
|---|---|---|---|---|
| 事务邮件送达率 | 98%–99%+,业界领先 | 良好,共享 IP 有波动 | 良好,受其他发件人影响 | 良好,但需要自己维护信誉 |
| 流量分离 | ✅ 原生 Message Stream | ⚠️ 事务/营销共享 IP 池 | ⚠️ 需手动配置分离 | ⚠️ 需要独立配置 |
| 开发体验 | API 设计成熟 | React Email 集成好,DX 最好 | SDK 完善但文档臃肿 | 原始,学习曲线陡 |
| 免费额度 | 100 封/月 | 3000 封/月(前 3 个月 100/天) | 100 封/天(永久免费) | 62000 封/月(EC2 托管) |
| 价格(1 万封) | ~$15 | ~$20 | ~$19.95 | ~$1 |
| 适合场景 | 事务邮件为主、对送达率要求极高 | 中小规模、全栈项目 | 营销 + 事务混合 | 大规模、成本敏感 |
如果是独立开发者早期项目,Resend 的 DX 体验最好——API 简洁,和 React Email 配合写模板很舒服,免费额度够 MVP 阶段用。当发送量上来或对送达率有硬性要求时,Postmark 是更稳的选择。Amazon SES 价格最低,但需要自己处理预热、监控和退信管理,适合有运维能力的团队。
日常维护:送达率不是一劳永逸
配置完 DNS、做完预热之后,送达率还需要持续关注。几个日常维护的关键指标:
退信率要控制在 2% 以下,超过 5% 就危险了。硬退信(邮箱不存在)的账号要立即从列表里移除,反复尝试发送不存在的邮箱会严重伤害域名信誉。
投诉率要控制在 0.1% 以下(Google 的 Postmaster Tools 可以查到)。每 1000 封邮件里超过 1 个人点了「标记为垃圾邮件」,就该检查邮件内容和发送频率了。
打开率和点击率是收件方判断你的邮件是否受欢迎的重要信号。持续低打开率会让收件方逐步把你的邮件归入更低优先级的分类。定期清理 90 天内没有打开过邮件的用户,比持续向他们发送效果更好。
// 错误做法:向所有注册用户无差别发送
// await sendNewsletter(allUsers) // ❌ 包含大量沉睡用户
// 正确做法:基于活跃度分层发送
async function sendSegmentedNewsletter(users: User[]) {
const active = users.filter(u => u.lastOpenDaysAgo <= 30)
const dormant = users.filter(u =>
u.lastOpenDaysAgo > 30 && u.lastOpenDaysAgo <= 90
)
// 90 天以上无互动的用户不发送营销邮件
// 先发活跃用户,保护域名信誉
await sendNewsletterBatch(active, { stream: 'marketing' })
// 沉睡用户降低频率,尝试再激活
if (dormant.length > 0) {
await sendReengagementCampaign(dormant, {
frequency: 'biweekly', // 降低发送频率
stream: 'reengagement', // 使用独立 Stream
})
}
}PTR 记录(反向 DNS)也需要检查。PTR 记录把 IP 地址映射回域名,是收件方验证发件人身份的辅助手段。大部分 ESP 会帮你配置 PTR,但如果是自建发信服务器,需要自己设置。
检查清单
按阶段分组,可以在产品上线前后逐项核对。
上线前:基础设施
- 注册独立的发信子域名(如
mail.domain.com),配置好 A 记录和 PTR 记录 - SPF 记录已配置,DNS 查询次数不超过 10 次,覆盖所有实际使用的发信服务
- DKIM 签名已启用,优先使用 Ed25519 算法
- DMARC 记录已配置,初期使用
p=none模式,rua指向有效的报告接收地址 -
List-Unsubscribe和List-Unsubscribe-PostHeader 已在营销邮件中配置 - 邮件模板包含纯文本回退版本
- 在 Gmail Postmaster Tools 和 Microsoft SNDS 中注册了发信域名
上线时:冷启动
- 制定 4–8 周的预热计划,从每天 50–100 封开始
- 预热期间只发给最活跃的用户群体
- 按邮箱服务商(Gmail、Outlook、Yahoo)分组限速,避免单一 ISP 突增
- 事务邮件和营销邮件使用独立的 Message Stream 或独立域名
- 每天检查退信率和投诉率,发现异常立即暂停增量
上线后:日常维护
- 每周查看 DMARC 聚合报告,识别未授权发信来源
- 退信率保持在 2% 以下,硬退信账号立即清除
- 投诉率保持在 0.1% 以下
- 每 90 天清理无互动用户,不再向其发送营销邮件
- DMARC 策略按计划从
none推进到quarantine,最终到reject - SPF 记录定期审计,移除不再使用的第三方服务
- 监控 Gmail Postmaster Tools 中的域名信誉等级
参考资料
- RFC 7208 - Sender Policy Framework (SPF) — SPF 协议规范,定义了授权发信 IP 的声明格式和 10 次 DNS 查询上限。
- RFC 6376 - DomainKeys Identified Mail (DKIM) — DKIM 签名机制规范。
- RFC 7489 - Domain-based Message Authentication, Reporting, and Conformance (DMARC) — DMARC 策略和报告机制规范。
- RFC 8463 - DKIM Ed25519 Signature Algorithm — Ed25519 签名算法在 DKIM 中的应用。
- Gmail Email Sender Guidelines — Google 对发件人的官方要求,包括 SPF/DKIM/DMARC 和一键退订。
- AWS - Guide to IP and Domain Warming and Migrating to Amazon SES — AWS 官方的域名预热和迁移指南。
- Resend - Gmail and Yahoo Bulk Sending Requirements for 2024 — Resend 对 Google/Yahoo 批量发件人新规的解读。
- Validity - 2025 Email Deliverability Benchmark Report — 2025 年全球邮件送达率基准数据。
- Mailmend - 35 Inbox Placement Statistics — 2025–2026 年收件箱放置率统计数据。
- Mailgun - State of Email Deliverability 2025 — Mailgun 年度邮件送达率报告。