无法理解为什么Zend_Mail :: addHeader()会删除换行符

时间:2012-01-03 22:07:52

标签: php zend-framework smtp mime zend-mail

(因为这是我的第一个问题,所以我只想说,我希望它不是特定于Zend的。就我所知,这不应该是一个问题。虽然我可以把它贴在一个Zend特定的论坛,我觉得我至少有可能在这里得到一个好的答案,特别是因为答案可能涉及超越Zend Framework的MIME相关问题。我基本上试图了解我是否是这个问题面对应该被视为ZF错误,或者如果我误解或滥用它。)

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

最终,我传递的标题太长了(我认为> 1000个字符),而且我收到了错误。我很困惑,因为我知道它是通过PHP的原生wordwrap()函数传递的,然后我将值传递给Zend_Mail :: addHeader(),所以我认为行长度永远不会成为问题。

事实证明,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);

此方法对值进行编码(根据需要对quoted-printable或base64进行编码)并将其块化为适当长度的行,但如果包含“不可打印的字符”,则,由Zend_Mime确定:: isPrintable($值)。

考虑到这种方法,换行符(\ n)确实被认为是不可打印的字符!因此,如果只是在前一个方法调用中没有将它们从字符串中剥离出来,那么长标题将被编码为QP并且被分成72个字符行,并且一切都可以正常工作。事实上,我做了一个测试,在那里我注释掉了对_filterOther()的调用,并且长标头被编码并且没有任何问题。但是现在我刚刚对ZF进行了粗心的破解而没有真正理解我删除的那条线背后的目的,所以这不是一个长期的解决方案。

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

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

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


更新:如果有人想关注ZF问题,我就此开了一个问题,这里是:Zend_Mail::addHeader() UNfolds long headers, then throws exception

1 个答案:

答案 0 :(得分:6)

你可能碰到了一些事情。根据{{​​3}},SMTP中的文本行不能超过1000个字符:

  

文字行

     

包含is的文本行的最大总长度   1000个字符(不包括重复的前导点   透明度)。使用SMTP可以增加此数量   服务扩展。

标头不能包含换行符,这可能是Zend剥离它们的原因。对于长标题,通常会插入换行符(SMTP中的CRLF)和用于“换行”它们的选项卡。

摘自RFC 2821

  

每个标题字段都可以被视为单个逻辑行   ASCII字符,包括字段名称和字段正文。   为方便起见,这个概念的领域 - 身体部分   实体可以分成多行表示;这个   被称为“折叠”。一般规则是在哪里   可以是线性白色空间(不仅仅是LWSP-chars),一个CRLF   紧随其后的是至少一个LWSP-char可能   插入

我会说_encodeHeader()函数应该看一下行长度,如果标题长于某个魔术值,请执行“换行和制表符”以使其跨越多行。