2015-09-29 7 views
0

Fatal error: Uncaught exception 'Zend\Mail\Exception\RuntimeException' with message 'Malformed header detected' in /var/www/html/plugins/ZendFramework/ZendFramework-2.4.7/library/Zend/Mail/Headers.php on line 88ZendMail - ошибка в заголовках

Это сообщение об ошибке, которое я получаю, когда пытаюсь использовать функцию Zend\Mail\Storage\Imap::getMessage(). Если я прокомментирую строку, где вызывается ошибка (точнее, я должен прокомментировать обе строки, где эта же ошибка выбрасывается из одной и той же функции), я могу прочитать тему сообщения, но позже на некоторых электронные письма, которые я получаю:

Fatal error: Uncaught exception 'Zend\Mail\Header\Exception\InvalidArgumentException' with message 'Invalid header value detected' in /var/www/html/plugins/ZendFramework/ZendFramework-2.4.7/library/Zend/Mail/Header/GenericHeader.php on line 61

Как я тестировал плагин, я не использовал любое другое расширение или плагин в то время как я получил эти ошибки, только расширение PHP Xdebug, для целей отладки. Вот весь мой код:

try { 
$mail = new Zend\Mail\Storage\Imap(array('host'  => 'my.mail.host', 
            'user'  => '[email protected]', 
            'password' => 'xxxxxxxxx')); 
} 
catch (Zend\Mail\Exception $e) { 
print_r($e); 
} 

$undecodable=array(); 
$mail->selectFolder('INBOX'); 

$list=array(1,2,3,4); 

foreach ($list as $mid) { 
$message=$mail->getMessage($mid); 
$content=array(
    'html' => array(
     'part'  => null, 
     'content' => null 
    ), 
    'plain' => array(
     'part'  => null, 
     'content' => null 
    ) 
); 
foreach (new RecursiveIteratorIterator($message) as $part) { 
    try { 
     $strtok=strtok($part->contentType, ';'); 
     if (($strtok == 'text/html') || ($strtok == 'text/plain')) { 
      switch ($part->contentTransferEncoding) { 
       case 'base64': 
        $contentDecoded = base64_decode($part->getContent()); 
        break; 
       case 'quoted-printable': 
        $contentDecoded = quoted_printable_decode($part->getContent()); 
        break; 
       case 'default': 
        $contentDecoded='undecodable'; 
        $undecodable[]=$part->contentTransferEncoding; 
        break; 
      } 
      $strtok=explode("/",$strtok); 
      $strtok=$strtok[1]; 
      $content[$strtok]['part']=$part; 
      $content[$strtok]['content']=$contentDecoded; 
     } 
    } catch (Zend\Mail\Exception $e) { 
     // ignore 
    } 
} 
echo "Message: " . $message->subject."<BR>"; 
if (!empty($content['html']['content'])) echo "HTML part found! "; 
if (!empty($content['plain']['content'])) echo "Plain part found! "; 
echo "<BR><BR>Next message"; 
} 
exit; 

ПРИМЕЧАНИЕ: сообщение идентификаторы правильно, я могу принести все из по telneting почтового сервера, все они существуют

ответ

0

Это та же самая проблема, которая появляется в Zend \ Mail \ Message :: fromString(). Метод действительно идет нормально - поскольку он принимает сообщение RAW и создает объект. Однако проблемы возникают, когда вы пытаетесь связаться с любыми заголовками сообщений, используя методы класса. Заголовки заголовков реализованы в шаблоне с ленивой загрузкой, поэтому объект факта состоит из «неправильных» заголовков, не распознается после создания объекта методом Zend \ Mail \ Message :: fromString().

Проблема в моем случае появляется, когда заголовки состоят из локальных символов (для Польши их примерами могут быть: ź, ć, ń, ę, ą и т. Д. - другие страны могут иметь более или менее такие, как хорошо). Я проверял сообщения, отправленные и полученные с использованием разных почтовых серверов (Exchange, sendmail, Lotus) и разных почтовых клиентов (Outlook, Thunderbird, Windows Mail). Заголовки, в которых эти символы появились, были очень разными. Exchange (или Outlook - не проверял, что в 100% :)) добавлял заголовок Topic-Thread (насколько я знаю, для потоковой передачи сообщений), и была добавлена ​​полная тема - так что этот заголовок, среди прочего (например, Тема) также бросали Исключение, когда-то пытались получить из объекта.

Проблема с методом Zend \ Mail \ Message :: fromString() состояла в том, что на самом деле не разрешено указывать кодировку для данных, которые извлекаются из сообщения RAW. Он просто берет данные и помещает их в некоторую память внутри объекта - и сами данные извлекаются на основе ленивой загрузки. Итак, как только вы попытаетесь получить заголовок - геттер бросает исключение, что данные находятся в неправильном формате.

Что я делал, это создание класса наследования и изменение способа работы Zend \ Mail \ Message :: fromString(). Вы можете найти код ниже:

public static function fromString(string $rawMessage, string $encoding = 'UTF-8') { 
     $message = parent::fromString($rawMessage); 
     foreach($message->getHeaders()->toArray() as $headerName => $headerValue) { 
      try { 
       $message->getHeaders()->get($headerName); 
      } catch (\Zend\Mail\Header\Exception\InvalidArgumentException $e) { // catches only if Header is wrongly structured 
       $message->getHeaders()->removeHeader($headerName); 
       $header = new \Zend\Mail\Header\GenericHeader(); 
       $header->setEncoding($encoding); 
       $header->setFieldName($headerName); 
       $header->setFieldValue($headerValue); 
       $message->getHeaders()->addHeader($header); 
      } 
     } 
     $message->getHeaders()->setEncoding($encoding); // All headers are encoded in $encoding 
     return $message; 
    } 

Так что вы можете увидеть здесь, что я вношу дополнительный параметр $ кодирования для этого метода, который позволяет указать кодировку сообщения. Параметр имеет значение по умолчанию UTF-8 - в основном, поэтому метод будет совместим вниз (в то время как PHP бросает уведомление, это не :)). Затем он запускает стандартный родительский метод для создания объекта - как я описал до того, как он еще не сработает.) Затем у нас есть код, который пытается «очистить» заголовки - позвонив каждому из них и поймав InvalidArgumentException, если выброшено. Если это исключение поднято (и уловлено кодом try ... catch ...) - заголовок удаляется и воссоздается, но с правильной кодировкой $. После того, как все заголовки проверены и потенциально заменены правильно закодированными, я снова вызываю метод setEncoding() для всех заголовков - для всех заголовков, которые не были «заменены» в foreach() {try ... catch. .} block - поэтому все заголовки будут закодированы в одной кодировке. Я знаю, что вы можете подумать, почему бы вам просто не выполнить этот метод setEncoding() для всех существующих заголовков?Ну, я попробовал - и этот тоже вызывает исключение :) Так, как я полагаю, метод просто вызывает каждый заголовок, но как только вызов - ленивая загрузка вызывает исключение.

Вся идея была также описана в следующих Article.

 Смежные вопросы

  • Нет связанных вопросов^_^