(因为这是我的第一个 SO 问题,所以我只想说我希望它不是 Zend 特定的。据我所知,这应该不是问题。虽然我可以在 Zend 特定的论坛上发布它,但我感觉我至少有可能在这里得到一个好的答案,特别是因为答案可能涉及超越 Zend 框架的 MIME 相关问题。我基本上是想了解我面临的问题是否应该被视为 ZF错误,或者如果我误解了某些东西或滥用了它。)
我一直在使用 Zend_Mail 构建通过 SendGrid(一种电子邮件分发服务)发送的 MIME 消息。他们的平台允许您通过他们的 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 想要完全控制格式和换行。Zend_Mail::addHeader() 中调用的下一个方法是
$value = $this->_encodeHeader($value);
这个方法对值进行编码(无论是quoted-printable 还是 base64,视情况而定)并将其分块成适当长度的行,但前提是它包含由 Zend_Mime::isPrintable($value) 确定的“不可打印字符”。
研究这种方法,换行符 (\n) 确实被认为是不可打印的字符!因此,如果在之前的方法调用中没有将它们从字符串中删除,那么长标头将被编码为 QP 并分块为 72 个字符的行,一切都会正常工作。事实上,我做了一个测试,我注释掉了对 _filterOther() 的调用,并且长标头被编码并且没有问题地通过。但是现在我只是对 ZF 进行了粗心的破解,并没有真正理解我删除的线路背后的目的,所以这不是一个长期的解决方案。
我的中期解决方案是扩展 Zend_Mail 并创建一个新方法 addHeaderForceEncode(),它将始终对标头的值进行编码,因此始终将其分块为短行。但我仍然不满意,因为我不明白为什么首先需要调用 _filterOther() —— 也许我根本不应该解决它。
谁能向我解释为什么存在这种剥离换行符的行为?如果标题不包含换行符以外的任何“不可打印字符”,它似乎不可避免地会导致标题变得太长的情况。
我已经对这个主题进行了很多不同的搜索,并查看了一些 ZF 错误报告,但没有看到任何人谈论这个。令人惊讶的是,这似乎是一个非常模糊的问题。仅供参考,我正在使用 ZF 1.11.11。
更新:如果有人想关注我打开的 ZF 问题,这里是:Zend_Mail::addHeader() 展开长标题,然后抛出异常