【问题标题】:Do the mail() headers have to be terminated with a line break? (IncrediMail issue)mail() 标头是否必须以换行符终止? (IncrediMail 问题)
【发布时间】:2011-10-03 14:43:16
【问题描述】:

我正在使用一个函数来发送 UTF8 电子邮件。 由于至少有一个收件人对我的函数发送的电子邮件有问题(不是 UTF8,所以特殊字符损坏;一些邮件标题出现在正文中),我想知道是否必须在标题字符串的末尾添加另一个换行符:

function mail_utf8($to, $subject = "(No subject)", $message = "", $header = "")
{
   $header_ = 'MIME-Version: 1.0'."\r\n".'Content-type: text/plain; charset=UTF-8'."\r\n";
   $header_ .= "From: my@mail.com"; //Should be optional...
   if (!empty($header)) $header_ .= "\r\n".$header;
   $out = mail($to, '=?UTF-8?B?'.base64_encode($subject).'?=', $message, $header_);

   return $out;
}

那么什么是正确的 - mail_utf8("x@y.z", "", "blah", "")mail_utf8("x@y.z", "", "blah", "\r\n")

编辑:这种事情的明显资源 - www.php.net/mail - 仅在示例#4中使用这样的换行符,与#2不同。

Edit2:这是当前版本。有关详细信息,请参阅 cmets。

function mail_utf8($to, $subject = "(No subject)", $message = "", $header = "")
{
$linebreak = PHP_EOL; //Seems to work everywhere, including IncrediMail
$linebreak = "\n"; //Debug
$header_ = 'MIME-Version: 1.0'.$linebreak.'Content-type: text/plain; charset=UTF-8'.$linebreak;
$header_ .= "From: my@mail.com".$linebreak;
if (!empty($header)) $header_ .= $header.$linebreak; //Last line break !?
$out = mail($to, '=?UTF-8?B?'.base64_encode($subject).'?=', $message, $header_);

return $out;
}

【问题讨论】:

  • 好吧,你的代码中都没有使用。
  • 一些邮件标题出现在正文中”部分让我认为您的标题中可能有空行,例如"Content-type: text/plain; charset=UTF-8\r\n\r\nAnother-header: value"。我会将\r\n 附加到From: 行并确保$headers 参数不以\r\n 开头。
  • @binaryLV:正如我在下面写的,似乎 IncrediMail(电子邮件客户端 - 不是邮件服务器)在“MIME-Version: 1.0”之后产生了第一个双换行符,这可以解释为什么“Content- Type: ..." 是正文的第一行(同样,仅在 IncrediMail 中)。但是通过使用“\n”而不是“\r\n”,我不再符合标准了,对吧?
  • (1) 我仍然建议将"\r\n"$header_ .= "\r\n".$header; 语句移动到$header_ .= "From: my@mail.com";,这样在删除设置From: 时可能会省去一些麻烦。 (2) 至于不符合标准,以某种方式获取接收消息的原始来源是值得的。您的 MTA 可能确实将 \r\n 替换为 \r\r\n(如其他人所述),但某些客户端可能能够处理此类情况。如果你能得到接收消息的原始来源,你可以在PHP中使用\r\n时检查是否有\r\n\r\r\n
  • @binaryLV:我查看了使用 16 进制编辑器使用 Thunderbird 下载的最终电子邮件。无论我是否将 $linebreak(参见第一篇文章中的 Edit2)设置为 "\r\n" 或 "\n" - 标题中都有单个 CRLF (13, 10) 作为中断 - 应该如此。在 IncrediMail 中,这仅适用于“\n”(或 PHP_EOL)。正如您所提到的,使用 "\r\n" 没有 CRCRLF (13, 13, 10)!但最后一个标题行是“Content-Type:”,后跟一个空行 (CRLFCRLF = 13, 10, 13, 10),然后是“Content-type: text/plain...”(这是我的标题,注意小写 T)。那么 TB 会修复它还是 IM 会破坏它?

标签: php email line-breaks


【解决方案1】:

尝试仅使用\n 而不是\r\n 来终止每个标题行。

如果没有收到消息,请尝试仅使用 LF (\n)。一些穷人 优质的 Unix 邮件传输代理自动将 LF 替换为 CRLF (如果使用 CRLF,则会导致 CR 加倍)。这应该是最后一次 度假村,因为它不符合 » RFC 2822.

来源:PHP mail() Function

【讨论】:

  • 好吧,这显然解决了表面上的问题。对我的电子邮件有疑问的人使用 IncrediMail 作为客户端。我已经检查过了,使用我的函数发送的电子邮件(没有终止换行符)和使用 IncrediMail 接收的电子邮件都损坏了 - 第一个正文行是“Content-Type:...”。但是只有“\n”作为分隔符(末尾仍然没有换行符),IncrediMail 可以正确显示电子邮件,除了用户输入 (
【解决方案2】:

我认为你不能像在第 5 行那样在标题顶部传递换行符,并尽量避免使用大量引号,这看起来很混乱。

重构的函数示例:

  function mail_utf8($to, $subject = "(No subject)", $message = "", $header = "") {
    $header_  = "MIME-Version: 1.0\r\nContent-type: text/plain; charset=UTF-8\r\n";
    $header_ .= "From: my@mail.com\r\n";
    if(!empty($header)) $header_ .= $header;
    $out = mail($to, '=?UTF-8?B?'.base64_encode($subject).'?=', $message, $header_);
    return $out;
  }

【讨论】:

  • 我会将\r\n 添加到From: 行。
  • 我不在最终标题的顶部使用换行符。我的代码和你的代码之间的区别在于我的代码没有在传递给 mail() 的标题末尾放置换行符。您的代码将执行此操作(如果 $header 参数为空)。我的代码中缺少的换行符是我提出问题的最初原因。
猜你喜欢
  • 2014-03-18
  • 1970-01-01
  • 1970-01-01
  • 2011-01-14
  • 2021-05-31
  • 1970-01-01
  • 1970-01-01
  • 2019-06-29
  • 2018-01-06
相关资源
最近更新 更多