在PHP邮件头中使用哪个换行符,\r\n还是\n?

28

我看过很多使用PHP邮件函数的例子。有些在头部使用\r\n作为换行符,有些则使用\n。

$headers = "From: Just Me\n"; 
$headers .= "Reply-To:  Just me <$email>\n"; 

vs

->

对比

$headers = "From: Just Me\r\n";
$headers .= "Reply-To:  Just me <$email>\r\n";

哪一个是正确的?

有时候我遇到过使用 \r\n 的情况,一些邮件客户端会将部分头信息解释为邮件文本(丢失这些头信息),这是因为 \r\n 是错误的吗?

8个回答

23

根据PHP文档,应使用CRLF \r\n。此外,为符合RFC 2822规范,行必须由回车符 CR \r 紧接着 换行符 LF \n 分隔。

由于\r\n是Windows平台的本地换行符,而\n适用于Unix,因此您可以在Windows上使用PHP_EOL­Docs常量,在当前运行脚本的平台上选择适当的新行字符。


1
我想知道为什么一些邮件客户端将\r\n解释为两个换行符(似乎Thunderbird也是其中之一)。 - Sam
@Sam 很不幸,我并不完全确定。如果你找到了答案,请告诉我。 - Russell Dias
我从这个问题中提出了一个问题,也许有人知道答案。 - Sam
20
这个答案不太合乎逻辑:如果php文档和RFC明确要求使用\r\n,则在非MS Windows平台上使用常量PHP_EOL肯定会违反这一要求。为什么要使用它?使用文字本身的\r\n就可以了。 - arkascha
3
我注意到,在使用 PHP 函数 mail() 的 $headers 参数(第四个参数)中添加 \r\n 时,我的本地 MTA(通过 sendmail 实现的 postfix)会将 \n 转换为 \r\n。结果发送的电子邮件包含 \r\r\n,这会破坏某些客户端的标头。可能之所以要使用 PHP_EOL 是因为 MTA 需要从 sendmail 获取本地行分隔符。这就解释了在 Unix 系统上需要将 \n 转换为 \r\n 以与 RFC 兼容。 - Phil

13

以防万一搜索引擎检索到此问题,帮助其他人避免我所经历的挫败感:这里有一个额外的奇怪现象。

在Linux上的php 5.2x版本中,我在php mail()中的电子邮件报头中有\r\n,升级到php 5.3.3后,格式和发送神秘地失败了。移除 \r 后,脚本得以修复(在检查了许多其他可能性后)。


我也遇到了这个问题,通过将CRLF替换为普通换行符解决了它。 - alkar
这是因为它们将 \n 转换为 \r\n,所以当您使用 \r\n 时,输出将变为 \r\r\n - user3292788
如果有帮助的话,我注意到在“Content-Transfer-Encoding: 7bit”子句之后,需要有两个\r\n。 - Denis Cousineau

9

如上所述,根据RFC,您应该使用\r\n,但这会破坏几个邮件系统(例如Outlook 2003)的标题。尽管\n不是要使用的“正确”换行符,但在我遇到的所有邮件系统中,它都可以正常工作。因此,我总是只使用\n。


2
一个列出那些输入“\n”会导致邮件头被错误解释的电子邮件客户端列表将是有用的。看起来,使用“\n”字符作为电子邮件头值的一部分的电子邮件客户端程序员是罕见且愚蠢的,因为RFC明确禁止这样做:“字段正文可以由任何US-ASCII字符组成,除了CR和LF。”(第2.2节)。当在终止标头的两个换行符之前有一个单独的“\n”时,客户端的行为是未定义的,因此使用“\n”作为标头值终止符比遵循RFC更明智。 - Dave Scotese

4
RFC官方规定要使用CRLF (\r\n)换行符,但在头部使用Unix换行符(\n)可以避免许多麻烦。一些邮件服务器(例如qmail)会拒绝包含\r\n的邮件消息。
来源:亲身经验,并由此说明得到证实:http://www.php.net/function.mail#40204

3
实际上,人们之所以说 \r\n 无法工作而 \n 可以工作的原因是因为他们在Unix环境下本地发送邮件。这与直接使用SMTP将电子邮件发送到邮件服务器不同。 - Phil

2

我的经验是:HTML邮件在网页客户端中可以正常工作,但在基于微软桌面的客户端(如entourage、outlook)中会出现问题。我使用了\r\n进行换行,只需删除MIME-Version中的\r即可使邮件在所有客户端上正常工作。


1

我更改了我的脚本,使用PHP_EOL代替,看起来可以正常工作--像这样:

//Set Content-type header
$headers  = "MIME-Version: 1.0" . PHP_EOL;
$headers .= "Content-type: text/html; charset=iso-8859-1" . PHP_EOL;
//Additional headers
$headers .= "From: $from" . PHP_EOL;
$headers .= "Cc: $cc"   . PHP_EOL;      
$headers .= "Content-type: text/html" . PHP_EOL;
$headers .= "Bcc: $bcc" . PHP_EOL;

注意:一定要使用双引号而不是单引号,因为后者似乎无法正常工作!

1

我曾经遇到过 Gmail 误解头文件的问题,但仅仅将头文件行保留在 \n 上并不足够,在这种情况下,某些版本的 Outlook 显示电子邮件为空。

https://stackoverflow.com/a/7960957 中提供的解决方案(我选择从 ppa 安装 lucid 上的 postfix 2.9),再加上使用 \n,现在似乎在任何地方都可以工作了。


0
> $mail = new PHPMailer;
 $mail->isSMTP(); 
**$mail->isHTML(true);**

在工作完成后插入此代码

> all html tag <br> <p> in $mail->Body='Hello<br> how are you ?<b>';

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