Не могу понять, почему Zend_Mail :: addHeader () удаляет символы новой строки - PullRequest
8 голосов
/ 04 января 2012

(Поскольку это мой первый ТАК вопрос, позвольте мне сказать, что я надеюсь, что он не слишком специфичен для Zend. Насколько я могу судить, это не должно быть проблемой. Хотя я мог бы опубликовать его в Форум, посвященный Zend, я чувствую, что, по крайней мере, с такой же вероятностью я получу здесь хороший ответ, тем более что ответ может касаться проблем, связанных с MIME, которые выходят за рамки Zend Framework. Я в основном пытаюсь понять, является ли проблема столкновение должно рассматриваться как ошибка ZF, или если я что-то неправильно понимаю или неправильно использую.)

Я использую Zend_Mail для создания сообщения MIME, которое отправляется через SendGrid, службу рассылки электронной почты. Их платформа позволяет отправлять электронные письма через их 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);

Этот метод кодирует значение (для печати в кавычках или base64, в зависимости от ситуации) и разбивает его на строки соответствующей длины, но только , если оно содержит «непечатные символы», как определено Zend_Mime: :. isPrintable ($ значение)

Если посмотреть на этот метод, символы новой строки (\ n) действительно считаются непечатными символами! Таким образом, если бы только они не были удалены из строки в предыдущем вызове метода, длинный заголовок закодировался бы как QP и был бы разбит на 72-символьные строки, и все работало бы хорошо. Фактически, я сделал тест, где закомментировал вызов _filterOther (), и длинный заголовок кодируется и проходит без проблем. Но теперь я только что сделал небрежный взлом ZF, не понимая цели, стоящей за удаленной строкой, так что это не может быть долгосрочным решением.

Моим среднесрочным решением было расширение Zend_Mail и создание нового метода addHeaderForceEncode (), который всегда будет кодировать значение заголовка и, таким образом, всегда разбивать его на короткие строки. Но я все еще не удовлетворен, потому что я не понимаю, почему этот вызов _filterOther () был необходим в первую очередь - возможно, мне вообще не нужно было обходить его.

Может ли кто-нибудь объяснить мне, почему существует такое поведение, когда зачеркивается новая строка? Кажется, что это неизбежно приводит к ситуациям, когда заголовок может стать слишком длинным, если он не содержит никаких «непечатных символов», кроме символов новой строки.

Я провел несколько разных поисков по этой теме и просмотрел некоторые сообщения об ошибках ZF, но не видел, чтобы кто-нибудь говорил об этом. Удивительно, но это, кажется, действительно неясная проблема. К вашему сведению, я работаю с ZF 1.11.11.


Обновление: В случае, если кто-то захочет следить за проблемой ZF, которую я открыл по этому поводу, вот она: Zend_Mail :: addHeader () Раскрывает длинные заголовки, затем выдает исключение

1 Ответ

6 голосов
/ 04 января 2012

Возможно, вы столкнулись с несколькими вещами. Согласно RFC 2821 , текстовые строки в SMTP не могут превышать 1000 символов:

текстовая строка

Максимальная общая длина текстовой строки, включая 1000 символов (не считая дублирующуюся начальную точку для прозрачность). Это число может быть увеличено за счет использования SMTP Сервисные расширения.

Заголовок не может содержать символы новой строки, поэтому, вероятно, Zend удаляет их. Для длинных заголовков обычно вставляют разрыв строки (CRLF в SMTP) и вкладку для их «переноса».

Выдержка из RFC 822 :

Каждое поле заголовка можно рассматривать как одну логическую строку Символы ASCII, содержащие имя поля и тело поля. Для удобства полевая часть этого концептуального сущность может быть разбита на многострочное представление; этот называется "складной". Общее правило таково, что везде может быть линейно-пробелом (НЕ просто LWSP-символами), CRLF сразу за ним по крайней мере один LWSP-символ может быть вместо вставлена.

Я бы сказал, что функция _encodeHeader(), возможно, должна смотреть на длину строки, и если заголовок длиннее некоторого магического значения, используйте "wrap and tab", чтобы он занимал несколько строк.

...