php - 不明白为什么 Zend_Mail::addHeader() 去掉换行符

标签 php zend-framework smtp mime zend-mail

(因为这是我的第一个 SO 问题,我只想说我希望它不是太特定于 Zend。据我所知这应该不是问题。虽然我可以将它发布在Zend 特定的论坛,我觉得我至少有可能在这里得到一个好的答案,特别是因为答案可能涉及超越 Zend Framework 的与 MIME 相关的问题。我基本上是想了解我是否在facing 应该被认为是 ZF 错误,或者如果我误解了某些东西或误用了它。)

我一直在使用 Zend_Mail 构建一条 MIME 消息,该消息通过电子邮件分发服务 SendGrid 发送。他们的平台允许您通过他们的 SMTP 服务器发送电子邮件,但在您使用特殊 header (X-SMTPAPI) 时提供附加功能,该 header 的值为专有参数的 JSON 编码字符串,可能会变得很长。

最终,我传递的 header 太长了(我认为 >1000 个字符),并且出现了错误。我很困惑,因为我知道在我将值传递给 Zend_Mail::addHeader() 之前它是通过 PHP 的 native wordwrap() 函数传递的,所以我认为行长度永远不会成为问题。

事实证明,addHeader() 非常有意地去除了换行符,并且没有通过注释的方式进行特别解释。

// In Zend_Mail::addHeader()
$value = $this->_filterOther($value);


// In Zend_Mail::_filterOther()
$rule = array("\r" => '',
              "\n" => '',
              "\t" => '',
);
return strtr($data, $rule);

好吧,一开始这似乎很合理——也许 ZF 想要完全控制格式和换行。 Zend_Mail::addHeader() 中调用的下一个方法是

$value = $this->_encodeHeader($value);

此方法对值进行编码(根据需要引用可打印或 base64)并将其分成适当长度的行,但如果它包含由 Zend_Mime 确定的“不可打印字符”::isPrintable($value).

查看那个方法,换行符 (\n) 确实被认为是不可打印的字符!因此,如果在之前的方法调用中没有将它们从字符串中剥离,那么长 header 将被编码为 QP 并分成 72 个字符的行,一切都会正常进行。事实上,我做了一个测试,在其中我注释掉了对 _filterOther() 的调用,并且长 header 被编码并且没有问题地通过。但是现在我只是粗心地攻击了 ZF,而没有真正理解我删除的行背后的目的,所以这不是一个长期的解决方案。

我的中期解决方案是扩展 Zend_Mail 并创建一个新方法 addHeaderForceEncode(),它总是对标题的值进行编码,因此总是将它分成短行。但我仍然不满意,因为我不明白为什么 _filterOther() 调用首先是必要的——也许我根本不应该解决它。

任何人都可以向我解释为什么存在这种剥离换行符的行为吗?如果标题不包含除换行符之外的任何“不可打印字符”,这似乎不可避免地会导致标题变得太长的情况。

我对这个主题做了很多不同的搜索,并查看了一些 ZF 错误报告,但没有看到有人谈论这个。令人惊讶的是,这似乎是一个非常晦涩的问题。仅供引用,我正在使用 ZF 1.11.11。


更新:如果有人想关注我打开的 ZF 问题,请看这里:Zend_Mail::addHeader() UNfolds long headers, then throws exception

最佳答案

您可能遇到了一些问题。每RFC 2821 , SMTP 中的文本行不能超过 1000 个字符:

text line

The maximum total length of a text line including the is 1000 characters (not counting the leading dot duplicated for transparency). This number may be increased by the use of SMTP Service Extensions.

标题不能包含换行符,所以这可能就是 Zend 去除它们的原因。对于长 header ,通常会插入一个换行符(SMTP 中的 CRLF)和一个制表符来“换行”它们。

摘自 RFC 822 :

Each header field can be viewed as a single, logical line of ASCII characters, comprising a field-name and a field-body. For convenience, the field-body portion of this conceptual entity can be split into a multiple-line representation; this is called "folding". The general rule is that wherever there may be linear-white-space (NOT simply LWSP-chars), a CRLF immediately followed by AT LEAST one LWSP-char may instead be inserted.

我会说 _encodeHeader() 函数应该查看行的长度,如果标题比某个神奇的值长,则执行“换行和制表”以使其跨越多行.

关于php - 不明白为什么 Zend_Mail::addHeader() 去掉换行符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8719322/

相关文章:

sql - Zend 框架 : How to combine three tables in one query using Joins?

java - 我的 SMTP 发件人抛出错误 421

php - INSERT IGNORE INTO 不起作用

php 修剪功能不起作用

php - 带有 CGridView 的 CJUIDatePicker 不起作用

php - 使用 GoogleAPI 返回 2 个不同查询的搜索结果数。 (PHP)

php - PHP中的线程?

php - 禁用一个 Zend Multioption 表单 MultiCheckbox

.net - 为什么<system.net><mailSettings>中<smtp>元素有 "from"属性?我怎样才能使用它?

php - 如何配置PHP发送电子邮件?