使用PHP发送邮件:头部被解释为正文?

3

当我使用\r\n作为邮件头中的换行符(根据文档应该是这样的)发送PHP邮件时

$headers = "From: $email\r\n"; 
$headers .= "Reply-To:  Just me <$email>\r\n"; 
$headers .= 'Content-type: text/plain; charset=iso-8859-1' . "\r\n";
$headers .= "Content-Transfer-Encoding: 8bit\r\n";
$subject = "Hello world";
$body = "<html><p>Hey, whats up?</p></html>";

mail($to, $subject, $body, $headers);

一些邮件客户端会将 \r\n 解释为两个换行符。因此,对于上述的 mail() 函数,实际的邮件内容应该是这样的:
X-Message-Delivery: Vj0LEdMMtPAYT0xO0Q9MTtTQ0w9MA==
X-Message-Status: n
Received: from server75.publicompserver.de ([92.43.108.63]) by snt0-mc2-f13.Snt0.hotmail.com with Microsoft SMTPSVC(6.0.3790.4675);
 Thu, 9 Dec 2010 12:09:22 -0800
Message-ID: <40177C.70807@justme.org>
[lots of other headers]
Date: Thu, 09 Dec 2010 21:09:32 +0100
X-OriginalArrivalTime: 09 Dec 2010 20:09:22.0873 (UTC) FILETIME=[F88C3A90:01CB97DC]
From: $email

Reply-To:  Just me <$email>

Content-type: text/html; charset=iso-8859-1

Content-Transfer-Encoding: 8bit

<html><p>Hey, whats up?</p></html>

现在有些客户端(例如googlemail)将忽略这些额外的换行符。其他一些客户端(如thunderbird)将解释第一个额外的换行符为标题的结尾,并将其余的标题行解释为正文的部分(丢失标题信息,此时邮件呈现为文本而非HTML)。
我也看到其他发送电子邮件的网站出现了类似的问题。
这里发生了什么?\r\n 是根据文档正确的换行符,还是其他原因造成了问题?
如何解决这个问题?将换行符从\r\n 改为\n似乎有所帮助,但由于文档说“应该使用\r\n”,这难道不是正确的解决方法吗?

在你之前的问题中,我提到了 PHP_EOL 常量。你尝试过使用它吗? - Russell Dias
由于这些脚本正在Apache/Unix上运行,因此PHP_EOL将是\n,不是吗? - Sam
也许有人可以阐述一下Unix的sendmail脚本是如何将\n转换为\r\n的。 - Russell Dias
你在示例中使用\r\n不一致。有些标题是以CRLF结尾的,而有些则只有LF。 - Thanatos
@Thanatos,是的,抱歉,我从不同的来源中编写了这个示例,因为我不想让它包含真实的电子邮件地址。现在已经更正了。 - Sam
3个回答

8
这在文档中提到了:http://php.net/manual/en/function.mail.php:"如果消息未被接收,请尝试仅使用LF(\n)。一些质量较差的Unix邮件传输代理会自动将LF替换为CRLF(如果使用CRLF,则会导致CR加倍)。这应该是最后的选择,因为它不符合RFC 2822。"
所以,正如你所说的:这不是正确的方式,但这就是现实。

1
那我应该使用 \r\n 直到有一个邮件接收者抱怨,然后改用 \n 吗?但是如果回复头丢失,他们如何确保抱怨,以便我可以注意到而不是只删除消息呢? - Sam
2
我的猜测是为了最大的兼容性,仅使用 \n,而不管 RFC 的规定,只要你的测试显示这种方法没有问题。 - jcomeau_ictx

0

正如您之前的问题所提到的,每个平台都以不同的方式(CRLF或LF)限定行。最好通过PHP_EOL常量将此决策留给PHP处理。


PHP_EOL只是Unix平台上\n的另一种写法,而所有这些脚本都在Unix系统上运行,所以你会说我应该忽略RFC 2822,改用\n? - Sam
这份文档中的注释提供了一些线索:http://www.php.net/manual/en/function.mail.php#100563 - Russell Dias
这个关于 \r\n 被改成 \r\r\n 的评论解释了问题的一些:http://www.php.net/manual/en/function.mail.php#100193 - Sam

0
在你的代码中,有些头部行使用了\r\n,而其他行只使用了\n。如果你保持一致,也许这个问题就不会出现了。

哦,抱歉,这不是真正的代码,这只是我临时编写的一些示例 - 代码本身是一致的,是我的错误! - Sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接