薛定谔的电子邮件

Lobsters Hottest 新闻

摘要

文章详细介绍了作者因SPF、DKIM、DMARC等认证协议导致的电子邮件转发挑战,并描述了使用Outlook规则和Cloudflare服务等工具解决该问题的各种尝试。

<p>追踪我处理失败电子邮件重定向的过程。</p> <p><a href="https://lobste.rs/s/qtsnvd/schrodinger_email">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/08/22 11:06

# 薛定谔的邮箱:https://yashgarg.dev/posts/the-schrodinger-email/ 目录 - 1. [问题所在](#the-problem) - 2. [尝试 #1 —— Outlook 规则](#attempt-1---outlook-rule) - 2.1. [第一个线索](#the-first-clue) - 2.2. [身份验证相关](#the-authentication-stuff) - 2.3. [原始邮件本身没问题](#the-original-email-was-fine) - 3. [尝试 #2 —— 添加 @outlook.com 别名](#attempt-2--add-an-outlookcom-alias) - 4. [尝试 #3 —— Cloudflare 邮件路由](#attempt-3--cloudflare-email-routing) - 5. [尝试 #4 —— Email Worker](#attempt-4--email-worker) - 6. [最终解决方案](#the-final-solution) 邮件能有多难?我曾经也这么想。大错特错。这篇文章基本就是我在邮件基础设施上瞎折腾并自食其果的记录。 ## 问题所在 作为一个拥有多张信用卡的人(别评判!)—— 我喜欢使用像 [CRED](https://cred.club/) 或 [Fold](https://fold.money/) 这样的应用在一个地方追踪它们。这些应用经常要求访问邮箱以读取账单,而我不想授予它们对我邮箱的完全访问权限。因此,我有一个单独的邮箱地址,通过[邮件规则](https://support.microsoft.com/en-us/outlook/mail/manage-email-messages-by-using-rules-in-outlook)来转发邮件。但问题在于,*转发*操作会移除原始发件人信息,也就是银行的信息,而我希望保留所有这些信息。理想情况下,这一切应该能正常运行,我也不用写这篇文章了 :P ## 尝试 #1 —— Outlook 规则 我创建了一个规则,用于*将任何邮件重定向到我的 Gmail 地址*以进行测试。规则本身是有效的,但没有任何状态指示,所以你无法判断它是否失败?用户体验太差了。幸运的是,Gmail 的[邮件管理员](https://en.wikipedia.org/wiki/Postmaster_(computing))会发送一个通知,说明重定向失败,原因是:**“Gmail 检测到此消息可能可疑,因为发送域的信誉非常低。”** 这是一个硬性的 [SMTP](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) 拒绝,事情正是从这里开始变得有趣的。 ### 第一个线索 原始的测试邮件是从 Gmail 发送到 Outlook 的。当 Outlook 接收它时,身份验证结果完全正常: ``` SPF: PASS DKIM: PASS DMARC: PASS ``` 为什么当 Outlook 试图转发时,Gmail 会拒绝它?重要的细节是**邮件转发会创建另一个 SMTP 投递**。所以,流程本质上是:第一跳完成的身份验证并不意味着第二跳会被自动接受。 ### 身份验证相关 那么 [SPF](https://en.wikipedia.org/wiki/Sender_Policy_Framework)、[DKIM](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail) 和 [DMARC](https://en.wikipedia.org/wiki/DMARC) 到底与此有何关系?这些是标准的电子邮件身份验证协议,用于验证邮件来源,并帮助防止欺骗和滥用。 #### 发送方策略框架 (SPF) SPF 基本上解决的问题是: > **这台服务器是否被允许代表此域名发送邮件?** 如果 `example.com` 通过其自己的邮件服务器发送电子邮件,SPF 可以验证这些服务器是否被授权。但转发改变了投递消息的服务器。原始消息可能来自 Google 的基础设施。经过 Outlook 重定向后:Gmail 现在是从 Microsoft 的基础设施而非原始发件人的基础设施接收消息。这会使 SPF 变得复杂。 #### 域名密钥识别邮件 (DKIM) DKIM 的工作方式不同。原始发件人可以对消息进行密码学签名。只要转发系统不修改消息的签名部分,该签名就可以在转发中保留。这是 DKIM 对于转发邮件特别重要的一个原因。 #### 基于域的消息认证、报告与合规性 (DMARC) DMARC 将身份验证结果与可见的 `From:` 地址中的域名关联起来。该策略作为 DNS TXT 记录发布在 `_dmarc` 下: ``` _dmarc.example.com TXT "v=DMARC1; p=reject" ``` 这里,`p=reject` 告诉接收邮件服务器拒绝未通过该域 DMARC 策略的消息。因此,转发可能造成以下几方面的不匹配: - 最初发送消息的实体, - 现在传输该消息的实体, - 以及消息声称来自的域名。 存在像 [ARC](https://en.wikipedia.org/wiki/Authenticated_Received_Chain) 这样的机制,可以在转发跳之间保留身份验证信息,但接收邮件服务器仍然会做出自己的投递决策。而且,Gmail 不仅查看 SPF/DKIM/DMARC。它还有反垃圾邮件和信誉系统来防止滥用。 ### 原始邮件本身没问题 查看测试消息的邮件头,Outlook 已成功验证了原始的 Gmail 消息: ``` spf=pass dkim=pass dmarc=pass ``` 所以第一跳是正常的。失败发生在 Outlook 的转发引擎尝试第二跳时。邮件头给了我另一个线索: ``` Resent-From: auto-submitted: auto-generated x-ms-exchange-generated-message-source: Mailbox Rules Agent ``` 换句话说,这不是我手动发送的另一封邮件。**是 Outlook 的邮箱规则代理生成了这次重定向投递。** 我发现微软本应在这个问题在2024年得到修复?微软已经[记录](https://support.microsoft.com/en-US/Support/known-issues/fixes-or-workarounds-for-recent-issues-on-outlook-com)了涉及国家/地区域名地址和 Gmail 因本质上相同错误而拒绝消息的问题。记录的解决方法是添加一个 `@outlook.com` 别名。于是我为同一个 Microsoft 帐户添加了一个 `[email protected]` 的别名。我还将 `@outlook.com` 地址设置为主别名,而不是 `@outlook.in`。然后我再次运行了完全相同的重定向测试。**它仍然失败了**,因为重定向消息的邮件头仍然包含: ``` Resent-From: x-ms-exchange-generated-message-source: Mailbox Rules Agent ``` 新的 `@outlook.com` 别名并未改变自动重定向所使用的身份。因此,别名解决方法对于这个特定的重定向路径没有帮助。 ## 尝试 #3 —— Cloudflare 邮件路由 好吧。如果 Outlook 不想直接投递到 Gmail,也许我可以在中间加入另一层[邮件路由](https://www.cloudflare.com/products/email-routing/)。我设置了路由规则,比如将 `[email protected]` 的邮件转发到 Gmail。这个想法是让 Cloudflare 来处理转发,而不是让 Outlook 直接将重定向消息投递到 Gmail。 不幸的是,这也没有解决问题。增加一层转发本身并不能解决邮件跨越多个 SMTP 跳时可能发生的身份验证和信誉问题。 此时,我的邮件架构开始看起来像这样:(此处省略架构图) 不用说,这也没用。 ## 尝试 #4 —— Email Worker 我在想,与其直接重定向到我的 Gmail 地址,如果我使用 `[email protected]` 并通过一个 [Email Worker](https://developers.cloudflare.com/email-service/api/route-emails/email-handler/) 进行路由,然后由我自己转发消息呢?代码可以很简单,像这样: ```javascript export default { async email(message, env, ctx) { console.log("From:", message.from); console.log("To:", message.to); await message.forward("[email protected]"); }, }; ``` 这个想法是,我将消息接收到我的 Worker 中,然后完全控制它的后续处理。但我没有意识到,Cloudflare 会在消息到达 Worker **之前**执行其身份验证检查。如果入站邮件未通过这些检查,它就会在有机会运行我的代码之前被拒绝。 > Cloudflare 对传入邮件执行 SPF、DKIM、DMARC 和 ARC 检查。根据发件人的 DMARC 策略,未通过身份验证的消息将被拒绝。 就这样,我最后的希望也破灭了。 ## 最终解决方案 我做了我非常不想做的事情。我手动将所有**与银行相关的邮件**从 Outlook 移到了我的 Gmail 地址。这并非我真正想要的优雅解决方案,但经历这一切之后,它比与邮件基础设施斗争要简单得多。我在这上面花了比预期更多的时间,但无论如何,完成了。 下次再见! 👋

相似文章

电子邮件的未来

Hacker News Top

Fastmail探讨了AI驱动的邮件过滤和助手如何使邮件认证标准(SPF、DKIM、DMARC)成为防止伪造和网络钓鱼的关键基础设施。

电子邮件加密

Lobsters Hottest

本文追溯了电子邮件从其去中心化、基于信任的起源到现代安全问题的历史,解释了SMTP和MIME等协议是如何作为技术限制的变通方案而出现的,但这使电子邮件容易受到窃听和篡改。

自建电子邮件持续急剧下降

Hacker News Top

过去十年的DNS测量显示,电子邮件基础设施正围绕两大提供商整合,DMARC实施趋于平稳,且存在庞大的长尾基础设施,引发了对弹性的担忧。