Php Can';我不明白为什么Zend_Mail::addHeader()会删除换行符

Php Can';我不明白为什么Zend_Mail::addHeader()会删除换行符,php,zend-framework,smtp,mime,zend-mail,Php,Zend Framework,Smtp,Mime,Zend Mail,(因为这是我的第一个SO问题,我只想说我希望它不是太具体。据我所知,这不应该是一个问题。虽然我可以把它发布在一个特定于Zend的论坛上,但我觉得我至少有可能在这里得到一个好的答案,特别是因为答案可能涉及超越Zend框架的MIME相关问题.我基本上是想了解我所面临的问题是否应该被视为ZF错误,或者我是否误解或误用了它。) 我一直在使用Zend_Mail构建MIME消息,该消息通过SendGrid(一种电子邮件分发服务)发送。他们的平台允许您通过他们的SMTP服务器发送电子邮件,但当您使用一个特殊标

(因为这是我的第一个SO问题,我只想说我希望它不是太具体。据我所知,这不应该是一个问题。虽然我可以把它发布在一个特定于Zend的论坛上,但我觉得我至少有可能在这里得到一个好的答案,特别是因为答案可能涉及超越Zend框架的MIME相关问题.我基本上是想了解我所面临的问题是否应该被视为ZF错误,或者我是否误解或误用了它。)

我一直在使用Zend_Mail构建MIME消息,该消息通过SendGrid(一种电子邮件分发服务)发送。他们的平台允许您通过他们的SMTP服务器发送电子邮件,但当您使用一个特殊标头(X-SMTPAPI)时,它提供了额外的功能,该标头的值是一个JSON编码的专有参数字符串,可能会很长

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

事实证明,addHeader()非常有意地剥离换行符,并且没有通过注释的方式进行特殊解释

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


// In Zend_Mail::_filterOther()
$rule = array("\r" => '',
              "\n" => '',
              "\t" => '',
);
return strtr($data, $rule);
好的,一开始这似乎是合理的——也许ZF想要完全控制格式化和换行

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

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

我的中期解决方案是扩展Zend_Mail并创建一个新方法addHeaderForceEncode(),该方法将始终对标头的值进行编码,从而始终将其分为几行。但我仍然不满意,因为我不明白为什么会这样_filterOther()首先,打电话是必要的——也许我根本不应该在这方面工作

有人能向我解释为什么会出现这种剥离换行符的行为吗?这似乎不可避免地会导致这样的情况:如果标题中不包含除换行符以外的任何“不可打印字符”,则标题可能会过长

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



更新:如果有人想关注我就此打开的ZF问题,这里是:

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

文本行

文本行的最大总长度,包括 1000个字符(不包括复制的前导点) 透明度)。此数字可能会因使用SMTP而增加 服务扩展

标头不能包含换行符,所以Zend可能正是出于这个原因将其剥离。对于长标头,通常会插入换行符(SMTP中的CRLF)和“包装”选项卡

摘录自:

可以将每个标题字段视为一个逻辑行 ASCII字符,包括字段名和字段正文。 为方便起见,此概念图的字段主体部分 图元可以拆分为多行表示;此 被称为“折叠”。一般规则是 可以是线性空白(而不仅仅是LWSP字符)、CRLF 可改为紧跟至少一个LWSP字符 插入


我想说,
\u encodeHeader()
函数可能应该查看行长度,如果标题长度超过某个神奇值,请执行“换行和制表”以使其跨越多行。

StackOverflow可以回答所有问题;)+1回答您的第一个问题。感谢您让我感到受欢迎。我也检查了一下,Zend_Mail似乎不支持页眉折叠,也没有为您提供添加未处理的“原始页眉”的方法。看来这一修改最好是在
Zend\u Mail\u Transport\u Abstract
编制领导方法中进行的。如果将第三个参数
$append
传递到
addHeader
,它将折叠附加的数据,但还会在行尾添加一个逗号,我认为这会破坏JSON。这可能值得创建一个新的逻辑。我不明白您为什么说“标题不能包含换行符,所以这可能就是Zend剥离换行符的原因”,因为换行符作为CRLF的一部分是折叠所必需的(正如您通过RFC 822指出的)。但总的来说,我认为你同意addHeader()或_encodeHeader()中缺少一些意识?@LinusR:我认为Zend并不期望出现折叠的标题,这就是为什么它会剥离新行。在我看来,Zend要么接受折叠的标题(每个CRLF后面都有空格;没有裸露的CR或LF),要么尝试折叠长标题。谢谢你们两位的想法。我将在采埃孚的追踪器上打开一个问题。
$value = $this->_encodeHeader($value);