php编码函数 base58,来自PHP的电子邮件的主题标头编码已损坏

TL; DR

$preferences = ['input-charset' => 'UTF-8', 'output-charset' => 'UTF-8'];

$encoded_subject = iconv_mime_encode('Subject', $subject, $preferences);

$encoded_subject = substr($encoded_subject, strlen('Subject: '));

mail($to, $encoded_subject, $message, $headers);

要么

mb_internal_encoding('UTF-8');

$encoded_subject = mb_encode_mimeheader($subject, 'UTF-8', 'B', "\r\n", strlen('Subject: '));

mail($to, $encoded_subject, $message, $headers);

问题与解决方案

和标头仅适用于您的邮件正文。 对于标头,有一种机制可以指定RFC 2047中指定的编码。

您应该通过对进行编码,该版本自PHP 5起就存在:

$preferences = ["input-charset" => "UTF-8", "output-charset" => "UTF-8"];

$encoded_subject = iconv_mime_encode("Subject", $subject, $preferences);

更改以匹配您的字符串的编码。您应将保留为。在PHP 5.4之前,请使用iconv_mime_decode("=?CP1250?B?QWhvaiwgc3bsdGU=?=", 0, "UTF-8")而不是[]。

现在是(不包含换行符)

Subject: =?UTF-8?B?VmVyeSBsb25nIHRleHQgY29udGFpbmluZyBzcGVjaWFsIGM=?=

=?UTF-8?B?aGFyYWN0ZXJzIGxpa2UgxJvFocSNxZnFvsO9w6HDrcOpPD4/PSsqIHA=?=

=?UTF-8?B?cm9kdWNlcyBzZXZlcmFsIGVuY29kZWQtd29yZHMsIHNwYW5uaW5nIG0=?=

=?UTF-8?B?dWx0aXBsZSBsaW5lcw==?=

为包含:

Very long text containing special characters like ěščřžýáíé<>?=+* produces several encoded-words, spanning multiple lines

它是如何工作的?

函数拆分文本,将每个片段分别编码为令牌,并折叠它们之间的空格。 编码字为,其中:

是(对于Base 64 –请参见)或(对于Quoted可打印–请参见),

是用编码的字符串,该字符串在解码后具有字符集。

您可以通过或直接通过iconv_mime_decode("=?CP1250?B?QWhvaiwgc3bsdGU=?=", 0, "UTF-8")将解码为UTF-8字符串(捷克语中为)。

编码为编码字比较复杂,因为规范要求每个编码字令牌的长度最多为75个字节,并且包含任何编码字令牌的每一行的长度都必须最大为76个字节(包括连续行开头的空白) )。 不要自己实现编码。 您真正需要知道的是遵守规范。

有趣的相关阅读是Wikipedia文章Unicode和电子邮件。

备择方案

一个基本的选择是仅使用一组受限字符。 ASCII保证有效。 正如user2250504建议的那样,ISO Latin 1(ISO-8859-1)也可能也可以工作,因为在未指定编码时,它通常用作备用。 但是这些字符集很小,您可能无法对所需的所有字符进行编码。 此外,RFC并未提及Latin 1是否应工作。

您也可以使用,就像Paul Norman回答的那样,但是使用起来很不正确。

您必须使用来设置mbstring函数的内部使用的编码。 函数期望输入字符串采用这种编码。 注意:的第二个参数与输入字符串无关(尽管手册说了什么)。 它对应于编码词中的(请参见上面的工作原理)。 在将输入字符串传递给B或Q编码之前,将从内部编码重新编码为该字符串。

自PHP 5.6起,可能不需要设置内部编码,因为不推荐使用基础的配置选项,而推荐使用选项,此选项默认情况下已设置为UTF-8。 请注意,这只是一个默认值,在代码中依赖默认值可能是不合适的。

您必须在输入字符串中包含标题名称和冒号。 RFC对行长施加了严格的限制,它也必须适用于第一行! 另一种方法是摆弄第五个参数(;最后一个参数截至2015年9月),但这更加不方便。

该实现可能存在错误。 即使正确使用,也可能会损坏输出。 至少这是手册页上的许多评论所说的。 我没有找到任何问题,但是我知道编码单词的实现很棘手。 如果您发现或中潜在或实际的错误,请在评论中告知我。

使用至少还有一个好处:它并不总是对所有标头内容进行编码,这样可以节省空间并使文本易于阅读。 仅非ASCII部分需要编码。 与上面的示例类似的输出为:

Subject: Very long text containing special characters like

=?UTF-8?B?xJvFocSNxZnFvsO9w6HDrcOpPD4/PSsqIHByb2R1Y2VzIHNldmVyYWwgZW5j?=

=?UTF-8?B?b2RlZC13b3Jkcywgc3Bhbm5pbmcgbXVsdGlwbGUgbGluZXM=?=

的使用示例:

mb_internal_encoding('UTF-8');

$encoded_subject = mb_encode_mimeheader("Subject: $subject", 'UTF-8');

$encoded_subject = substr($encoded_subject, strlen('Subject: '));

mail($to, $encoded_subject, $message, $headers);

这是本文顶部的TL; DR中的代码段的替代方法。 实际上,它不只是保留的空间,而是将其放到那里,然后将其删除,以便能够与的愚蠢接口一起使用。

如果您更喜欢mbstring函数而不是iconv函数,则可能要使用。它内部使用,但是会自动编码消息的主题和正文。 同样,请小心使用。

除主题以外的标题需要不同的处理

请注意,对于所有可能包含非ASCII字符的标头,您都不能假定对标头的全部内容进行编码是可以的。 例如。 “发件人”,“收件人”,“抄送”,“密件抄送”和“答复收件人”可能包含其所包含地址的名称,但只能对名称进行编码,而不能对地址进行编码。 原因是令牌仅在某些情况下才可以替换、和令牌(请参阅RFC 2047的§5)。

其他标题中非ASCII文本的编码是一个相关但不同的问题。 如果您想了解更多有关此主题的信息,请搜索。 如果找不到答案,请提出另一个问题,并在评论中指出我的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值