修复 Movable Type 使用访客邮箱作发件人的问题

| No Comments << Previous

  Movable Type(MT)作为一个相当“古老”的内容管理系统,曾经在博客时代非常流行。最近重新维护这个多年没有打理的博客时,发现有几条待审核评论,一直没有收到邮件通知。

  经过排查发现,问题出在 Movable Type 的评论通知邮件机制上。

  先说说 Movable Type 的邮件发送方式。

  在默认情况下,MT 会使用访客提交评论时留下的 Email 地址作为邮件的 From(发件人)地址。这个设计在十几年前基本没有问题,而且还有一个优点:管理员收到评论通知邮件后,可以直接点击“回复”,邮件会自动发送给评论者。

  随着现代邮件系统安全策略的变化,这种设计已经不再适用。现在主流邮件服务商(例如 Gmail 等)都会验证邮件发送域名的 SPF、DKIM 以及 DMARC 认证。如果 SMTP 服务器发送邮件时使用的 From 地址并不属于当前邮件服务器控制的域名,接收方通常会认为这是一封伪造邮件并拒收。例如,本次遇到的错误:

2026-07-10 13:30:04 1wi3m9-000000072Tb-3X2f ** vistor@example.com R=dnslookup T=remote_smtp H=gmail-smtp-in.l.google.com [192.178.164.26]

SMTP error from remote mail server after pipelined end of data:

550-5.7.26 Your email has been blocked because the sender is unauthenticated.
550-5.7.26 Gmail requires all senders to authenticate with either SPF or DKIM.

Authentication results:
DKIM = did not pass
SPF [] with ip: [100.100.100.100] = did not pass

  从上面的日志可以看到,邮件服务器实际发送 IP 并没有通过 Gmail 的 SPF/DKIM 验证,邮件直接被拒收。

问题定位

  下面以 Movable Type 6 为例,通过检查 Movable Type 的邮件发送代码,发现评论通知邮件发送逻辑位于 lib/MT/App.pm 中的 _send_comment_notification 函数,其中原始代码逻辑如下:

require MT::Mail;
my $author = $entry->author;
$app->set_language( $author->preferred_language )
    if $author && $author->preferred_language;
my $from_addr;
my $reply_to;
if ( $cfg->EmailReplyTo ) {
    $reply_to = $comment->email;
}
else {
    $from_addr = $comment->email;
}
$from_addr = $cfg->EmailAddressMain;
$reply_to  = $comment->email;

  当 EmailReplyTo 没有启用时(MT后台没有对应设置,默认也就不会使用System Email),MT 会直接把访客评论留下的邮箱 vistor@example.com 作为邮件的 From 地址 , 这正是现代邮件系统无法接受的行为。

临时修补方法

  备份并修改 lib/MT/App.pm ,找到 _send_comment_notification 函数,大约在1570行附近,将原来的逻辑:

if ( $cfg->EmailReplyTo ) {
    $reply_to = $comment->email;
}
else {
    $from_addr = $comment->email;
}

  修改为:

$from_addr = $cfg->EmailAddressMain;
$reply_to  = $comment->email;

  修改后邮件头由 From: visitor@example.com To: blog-author@example.com 变为 From: MT SYSTEM EMAIL Reply-To: vistor@example.com To: blog-author@example.com 这样既满足现代邮件系统的 SPF/DKIM 验证要求,又保留了管理员直接回复评论者的便利。

  如果你的MT System Email设置的是自己的域名邮箱,只需在域名里增加一条TXT记录,将服务器的IP加进去就可以了,比如:"v=spf1 include:spf.example.com ip4:YourMailServerIP ~all"

  该考虑更换博客程序了。。。

本文结束。

Leave a comment