为什么联系表单是你最大的垃圾邮件隐患
大多数联系表单都被配置为直接根据用户输入发送邮件。这使它们极易被利用。
目录
问题比你想象的更早出现
自 2000 年代初以来,联系表单一直是垃圾邮件的传播途径;但随着邮件服务商收紧身份验证要求,这个问题变得更严重。大多数联系表单仍然以同样的方式构建:用户填写表单,你的服务器在 From 头中使用用户的地址发送一封邮件,然后你等待回复。
这是典型的邮件伪造漏洞。垃圾邮件发送者可以利用你的表单发送看起来来自任意地址的邮件,并通过你服务器的 IP 路由出去。如果有足够多的垃圾邮件以这种方式发出,你的域名会被标记,你的合法事务邮件也将无法送达收件箱。
修复方法很直接,但大多数教程仍然做错了。
联系表单为什么如此容易被利用
一个典型的联系表单接受三个字段:姓名、邮箱和消息。服务器端处理程序会取出该邮箱地址,并直接放入一封外发 SMTP 邮件的 From 头中。这样回复很方便——你只需在收件箱里点击“回复”——但这也等于给了垃圾邮件发送者一份礼物。
当垃圾邮件发送者发现你的表单时,会发生以下情况:
- 他们在“from”字段中填入受害者的邮箱地址并提交表单
- 你的服务器照常发送一封邮件,并在
From头中使用该受害者的地址 - 受害者的邮件服务器看到一封声称来自其域名、但源自你 IP 的邮件
- 如果你的域名缺少正确的 SPF/DKIM/DMARC 记录(即使有记录也一样),邮件仍可能送达,因为许多服务器对联系表单流量较为宽松
- 受害者收到一封看起来来自自己地址的垃圾邮件,或者你的域名因伪造行为被标记
这不是理论攻击。它一直在发生。如果你运行联系表单却从未检查过邮件服务器日志,你很可能已经在以这种方式被利用。
发送联系表单邮件的正确方式
修复方法是永远不要把用户输入放进 From 头。应改为:
- From:
[email protected](或任何你控制的地址) - Reply-To: 用户提交的邮箱地址
- Subject: 如有需要可以包含用户姓名,但绝不要包含其邮箱
- Body: 包含所有表单数据,并清晰标注
这样,你的服务器只会从你拥有且已正确验证的地址发送邮件。当你在收件箱中点击“回复”时,邮件仍会发给用户——这正是 Reply-To 的作用。但垃圾邮件发送者无法利用你的表单冒充任意地址。
大多数邮件库都原生支持这一点。在 PHP 的 PHPMailer 中:
$mail->setFrom('[email protected]', 'Contact Form');
$mail->addReplyTo($_POST['email'], $_POST['name']);
在 Python 的 smtplib 与 email.mime 中:
msg['From'] = '[email protected]'
msg['Reply-To'] = form_data['email']
在使用 Nodemailer 的 Node.js 中:
const mailOptions = {
from: '[email protected]',
replyTo: req.body.email,
// ...
};
如果你的联系表单目前把用户输入放进 From 头,这就是一行代码的修复。今天就做。
速率限制不是可选项
即使邮件头处理得当,一个没有保护的联系表单仍然是垃圾邮件入口。垃圾邮件发送者会用不同的消息内容提交你的表单数百次,你的收件箱会被垃圾信息填满。
你需要在多个层面设置速率限制:
- 按 IP: 同一 IP 每小时不超过 5 次提交
- 按邮箱: 同一邮箱地址每天不超过 3 次提交
- 全局: 所有用户每小时不超过 50 次提交(根据你的流量调整)
速率限制应放在应用程序代码中,而不仅仅是 Web 服务器配置中。Nginx 和 Apache 的速率限制可以有所帮助,但它们在请求层面运作,并不了解邮箱地址或特定于表单的滥用模式。
如果你使用框架,通常会有可以直接接入的速率限制中间件。如果你从零开始构建,一个带过期键的简单 Redis 计数器就足够了:
key = f"contact_form:{ip_address}"
count = redis.incr(key)
if count == 1:
redis.expire(key, 3600) # 1 hour
if count > 5:
return error("Rate limit exceeded")
这并非无懈可击——垃圾邮件发送者可以轮换 IP——但它会显著提高滥用成本。
CAPTCHA 是权衡,不是解决方案
Google 的 reCAPTCHA v3 是不可见的,并会根据行为给用户打分,听起来很理想。实践中,它阻止合法用户的频率往往高于预期,尤其是使用 VPN、Tor 或共享企业网络的用户。
reCAPTCHA v2(“I'm not a robot”复选框)更可靠,但会增加摩擦。蜜罐字段——人类不会填写但机器人会填写的隐藏表单输入——可以在不影响用户的情况下捕获低级机器人,但任何严肃的垃圾邮件发送者都能轻易绕过。
最佳方法是分层:
- 正确的邮件头(不可协商)
- 速率限制(不可协商)
- 蜜罐字段(容易实现且没有坏处)
- 只有在上述措施之后仍有大量垃圾邮件时,才使用 CAPTCHA
如果你确实添加 CAPTCHA,请使用 reCAPTCHA v3,并设置较低阈值(0.5 或更低),同时为得分较低的用户回退到 v2。这样可以让大多数用户保持低摩擦,同时仍能阻止机器人。
何时使用第三方表单服务
如果你运营的是小型网站,并且不想维护表单基础设施,Formspree、Tally 或 Netlify Forms 等第三方服务会为你处理这一切。它们会进行速率限制、验证,并从自己的域名发送邮件,因此你的声誉可以保持干净。
权衡之处在于,你会把用户数据发送给第三方,这可能与你的隐私政策或 GDPR 义务冲突。在客户端处理数据 是注重隐私的团队中日益增长的趋势,但联系表单本质上需要服务器端处理——你无法在不暴露凭据的情况下从浏览器发送邮件。
如果你处理敏感咨询(法律、医疗、金融),你很可能需要运行自己的表单基础设施。对于其他场景,第三方服务是一个合理选择。
DMARC 问题
即使你修复了联系表单的邮件头,如果你的域名缺少 DMARC 策略,你仍然不安全。DMARC 会告诉接收邮件服务器,在邮件未通过 SPF 或 DKIM 检查时该如何处理。没有它,垃圾邮件发送者仍然可以发送看起来来自你域名的邮件,即使他们没有使用你的服务器。
设置 DMARC 超出了本文范围,但如果你重视邮件声誉,这是不可协商的。先从仅监控策略(p=none)开始,并在确认你的合法邮件已正确通过身份验证后,逐步迁移到 p=quarantine 或 p=reject。
那么 Cookie 同意与表单跟踪 呢?
如果你的联系表单使用分析工具或营销像素来跟踪提交,你很可能受 GDPR 和 ePrivacy 规则约束。大多数联系表单不需要跟踪——你已经知道有人提交了表单,因为你收到了邮件——但如果你使用 Facebook Pixel 或 Google Analytics 事件之类的东西,就需要在这些脚本加载之前获得明确同意。
最简单的方法是完全不跟踪联系表单提交。如果你必须跟踪,请只在用户同意后加载跟踪脚本,并确保你的同意横幅合规。
关键要点
- 永远不要把用户提交的邮箱地址放进
From头。请改用Reply-To。 - 速率限制是必须的。应在应用层实现,而不仅仅是在 Web 服务器层。
- 蜜罐字段是免费的收益。CAPTCHA 应作为最后手段。
- 第三方表单服务对小型网站来说是合理选择,但会带来隐私方面的权衡。
- 如果你从自己的域名发送任何邮件,就需要 DMARC 策略。
FAQ
Q: 我可以直接禁用联系表单,改用 mailto 链接吗?
A: 可以,但 mailto 链接会把你的邮箱地址暴露给抓取工具,并且你会失去收集结构化数据的能力。如果垃圾邮件已经难以承受,mailto 链接比一个有问题的联系表单更好,但修好表单比两者都更好。
Q: 如果我出于正当原因需要从用户的地址发送邮件怎么办?
A: 你几乎肯定不需要。如果你认为需要,你很可能是在试图解决一个工作流问题(例如回复路由),而 Reply-To 已经解决了这个问题。如果你确实需要从任意地址发送邮件,你需要的是具备正确身份验证的专用邮件服务,而不是联系表单。
Q: 我如何知道自己的联系表单是否已经被滥用?
A: 检查邮件服务器日志中的外发 SMTP 连接。如果你看到大量发送到不认识地址的外发邮件,或者你的域名已被 Spamhaus 等垃圾邮件数据库标记,你很可能正在被用作中继。MXToolbox 等工具可以检查你的域名声誉。
Q: 使用免费的 CAPTCHA 服务安全吗?
A: Google 的 reCAPTCHA 免费且被广泛使用,但它会向 Google 发送用户数据,这可能与你的隐私政策冲突。hCaptcha 是一个注重隐私的替代方案,不会用你的用户训练 AI 模型。Cloudflare Turnstile 也是一个选项,比传统 CAPTCHA 更少打扰用户。
Q: SPF、DKIM 和 DMARC 有什么区别?
A: SPF 列出哪些邮件服务器被允许从你的域名发送邮件。DKIM 会对外发邮件进行加密签名,使收件人可以验证邮件未被篡改。DMARC 将二者关联起来,并告诉收件人在邮件未通过 SPF 或 DKIM 检查时该如何处理。要实现正确的邮件身份验证,三者都需要。
Sources
- OWASP: Email Header Injection — 详细解释联系表单如何被用于邮件伪造。
- RFC 5322: Internet Message Format — 定义邮件头(包括
From和Reply-To)的技术标准。 - DMARC.org: Overview — 用于理解和实施 DMARC 策略的官方资源。
- Spamhaus: Domain Blocklists — 检查你的域名是否已因垃圾邮件被标记,并了解阻止列表的工作方式。


