zendframework / zend-mail

Mail component from Zend Framework
BSD 3-Clause "New" or "Revised" License
96 stars 111 forks source link

Zend\Mail\Message::formString() wrongly interprets headers with countr-specific characters #91

Open Voyteck opened 8 years ago

Voyteck commented 8 years ago

I have described the problem in an article - here's is part of it exactly about the bug in the method:

After quite extensive debuging, send plenties of emails there and back I recognized the problem actually is about headers that consists local characters (for Poland examples of them might be: ź, ć, ń, ę, ą etc. - other countries might have more or less of such as well). Since messages were sent and received using different mailservers (Exchange, sendmail, Lotus) and different email clients (Outlook, Thunderbird, Windows Mail) - the headers in which these characters appeared were very different - e.g. Exchange (or Outlook - haven't checked that in 100% :) ) was adding Topic-Thread header (as far as I know for message threading) and the full topic was put in there - so this header, among others (such as Topic) also was throwing Exception once tried to be retrieved from the object.

The problem with Zend\Mail\Message::fromString() method was that it actually didn't allowed to specify encoding for the data that is retrieved from RAW message. It simply takes the data and puts into some storage inside the object - and the data itself is retrieved on a lazy-loading basis. So once you try to retrieve the header - the getter is throwing an Exception that data is in wrong format

Here is also a code - overloaded method - that fixes that:

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;
    }

Full information on an error including the solution itself can be found in the following article: http://www.linkedphpers.org/2016/04/zend-framework-2-zendmailmessagefromstr.html

CyberLine commented 5 years ago

2 Years later and still a Problem ...

This is how we fixed that:

Overloading Headers class:

public function addHeaderLine($headerFieldNameOrLine, $fieldValue = null)
{
  if ($fieldValue) {
    $fieldValue = mb_encode_mimeheader($fieldValue);
    return parent::addHeaderLine($headerFieldNameOrLine, $fieldValue);
  }

  return parent::addHeaderLine(mb_encode_mimeheader($headerFieldNameOrLine));
}
Ocramius commented 5 years ago

Please provide a failing test case, and then the fix will likely be trivial.

michalbundyra commented 4 years ago

This repository has been closed and moved to laminas/laminas-mail; a new issue has been opened at https://github.com/laminas/laminas-mail/issues/61.