zendframework/zend-mail

header lazy loading breaks header access

glensc opened this issue · 2 comments

take this example code, after calling $message->getHeaders() to lazy-load the headers, the DKIM-Signature header can not be retrieved:

<?php

require __DIR__.'/vendor/autoload.php';
use PHPUnit\Framework\TestCase;
use Zend\Mail\Storage;

$headerValue = "v=1; a=rsa-sha25; c=relaxed/simple; d=example.org; h=\r\n\tcontent-language:content-type:content-type:in-reply-to";
$headers = "DKIM-Signature: {$headerValue}";

$message = new Storage\Message(['headers' => $headers, 'content' => 'irrelevant']);
$h = $message->getHeaders();
// calling toString will lazy load all headers
// and break DKIM-Signature
$h->toString();
$x = $h->get('DKIM-Signature');
// not reached here

i've narrowed it down to iconv_mime_decode in Zend\Mail\Header\HeaderWrap::mimeDecodeValue

seems it strips \n for no apparent reason, leaving \r in place, thus breaking header continuation sequence (\r\n\t) (less is used to visually see \r):

$ php71 -r 'var_dump(iconv_mime_decode($s="v=1; a=rsa-sha256; c=relaxed/simple; d=example.net; h=\r\n bb", ICONV_MIME_DECODE_CONTINUE_ON_ERROR, "UTF-8"));var_dump($s);'|less

string(58) "v=1; a=rsa-sha256; c=relaxed/simple; d=example.net; h=^M bb"
string(59) "v=1; a=rsa-sha256; c=relaxed/simple; d=example.net; h=
 bb"

exception trace from mimeDecodeValue method calls (maybe useful):

#0 zend-mail/src/Header/GenericHeader.php(36): Zend\Mail\Header\HeaderWrap::mimeDecodeValue('v=1; a=rsa-sha2...')
#1 zend-mail/src/Headers.php(482): Zend\Mail\Header\GenericHeader::fromString('DKIM-Signature:...')
#2 zend-mail/src/Headers.php(231): Zend\Mail\Headers->loadHeader('DKIM-Signature:...')
#3 zend-mail/src/Headers.php(115): Zend\Mail\Headers->addHeaderLine('DKIM-Signature:...')
#4 zend-mail/vendor/zendframework/zend-mime/src/Decode.php(142): Zend\Mail\Headers::fromString('DKIM-Signature:...', '\n')
#5 zend-mail/src/Storage/Part.php(112): Zend\Mime\Decode::splitMessage('DKIM-Signature:...', 'DKIM-Signature:...', NULL)
#6 zend-mail/src/Storage/Message.php(54): Zend\Mail\Storage\Part->__construct(Array)
#7 zend-mail/test1.php(10): Zend\Mail\Storage\Message->__construct(Array)
#8 {main}

#0 zend-mail/src/Header/GenericHeader.php(36): Zend\Mail\Header\HeaderWrap::mimeDecodeValue('v=1; a=rsa-sha2...')
#1 zend-mail/src/Headers.php(497): Zend\Mail\Header\GenericHeader::fromString('DKIM-Signature:...')
#2 zend-mail/src/Headers.php(398): Zend\Mail\Headers->lazyLoadHeader(0)
#3 zend-mail/src/Headers.php(425): Zend\Mail\Headers->current()
#4 zend-mail/test1.php(14): Zend\Mail\Headers->toString()
#5 {main}

closing as #188 got merged