Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merge branch 'hotfix/mail-mime-encoding' of https://github.com/Maks3w…
Browse files Browse the repository at this point in the history
…/zf2 into hotfix/zf2-258
  • Loading branch information
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 66 deletions.
2 changes: 1 addition & 1 deletion src/Header/AbstractAddressList.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public function getFieldValue()
}

if ('ASCII' !== $encoding) {
$name = HeaderWrap::mimeEncodeValue($name, $encoding, false);
$name = HeaderWrap::mimeEncodeValue($name, $encoding);
}
$emails[] = sprintf('%s <%s>', $name, $email);
}
Expand Down
48 changes: 18 additions & 30 deletions src/Header/HeaderWrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
namespace Zend\Mail\Header;

use Zend\Mail\Headers;
use Zend\Mime\Mime;

/**
* Utility class used for creating wrapped or MIME-encoded versions of header
Expand All @@ -45,7 +46,7 @@ abstract class HeaderWrap
public static function wrap($value, HeaderInterface $header)
{
if ($header instanceof UnstructuredInterface) {
return static::wrapUnstructuredHeader($value);
return static::wrapUnstructuredHeader($value, $header);
} elseif ($header instanceof StructuredInterface) {
return static::wrapStructuredHeader($value, $header);
}
Expand All @@ -56,23 +57,28 @@ public static function wrap($value, HeaderInterface $header)
* Wrap an unstructured header line
*
* Wrap at 78 characters or before, based on whitespace.
*
* @param string $value
*
* @param string $value
* @param HeaderInterface $header
* @return string
*/
protected static function wrapUnstructuredHeader($value)
protected static function wrapUnstructuredHeader($value, HeaderInterface $header)
{
return wordwrap($value, 78, Headers::FOLDING);
$encoding = $header->getEncoding();
if ($encoding == 'ASCII') {
return wordwrap($value, 78, Headers::FOLDING);
}
return static::mimeEncodeValue($value, $encoding, 78);
}

/**
* Wrap a structured header line
*
* @param string $value
* @param HeaderInterface $header
* @param string $value
* @param StructuredInterface $header
* @return string
*/
protected static function wrapStructuredHeader($value, HeaderInterface $header)
protected static function wrapStructuredHeader($value, StructuredInterface $header)
{
$delimiter = $header->getDelimiter();

Expand All @@ -97,29 +103,11 @@ protected static function wrapStructuredHeader($value, HeaderInterface $header)
*
* @param string $value
* @param string $encoding
* @param bool $splitWords Whether or not to split the $value on whitespace
* and encode each word separately.
* @return string
* @param int $lineLength maximum line-length, by default 998
* @return string Returns the mime encode value without the last line ending
*/
public static function mimeEncodeValue($value, $encoding, $splitWords = false)
public static function mimeEncodeValue($value, $encoding, $lineLength = 998)
{
if ($splitWords) {
$words = array_map(function($word) use ($encoding) {
$header = iconv_mime_encode('Header', $word, array(
'scheme' => 'Q',
'line-length' => 78,
'output-charset' => $encoding,
));
return str_replace('Header: ', '', $header);
}, explode(' ', $value));
return implode(Headers::FOLDING, $words);
}

$header = iconv_mime_encode('Header', $value, array(
'scheme' => 'Q',
'line-length' => 998,
'output-charset' => $encoding,
));
return str_replace('Header: ', '', $header);
return Mime::encodeQuotedPrintableHeader($value, $encoding, $lineLength, Headers::EOL);
}
}
2 changes: 1 addition & 1 deletion src/Header/MultipleHeadersInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface MultipleHeadersInterface
interface MultipleHeadersInterface extends HeaderInterface
{
public function toStringMultipleHeaders(array $headers);
}
2 changes: 1 addition & 1 deletion src/Header/Sender.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function getFieldValue()
if (!empty($name)) {
$encoding = $this->getEncoding();
if ('ASCII' !== $encoding) {
$name = HeaderWrap::mimeEncodeValue($name, $encoding, false);
$name = HeaderWrap::mimeEncodeValue($name, $encoding);
}
$email = sprintf('%s %s', $name, $email);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Header/StructuredInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface StructuredInterface
interface StructuredInterface extends HeaderInterface
{
/**
* Return the delimiter at which a header line should be wrapped
Expand Down
8 changes: 2 additions & 6 deletions src/Header/Subject.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Subject implements HeaderInterface, UnstructuredInterface
class Subject implements UnstructuredInterface
{
/**
* @var string
Expand Down Expand Up @@ -82,11 +82,7 @@ public function getFieldName()
*/
public function getFieldValue()
{
$encoding = $this->getEncoding();
if ($encoding == 'ASCII') {
return HeaderWrap::wrap($this->subject, $this);
}
return HeaderWrap::mimeEncodeValue($this->subject, $encoding, true);
return HeaderWrap::wrap($this->subject, $this);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Header/UnstructuredInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface UnstructuredInterface
interface UnstructuredInterface extends HeaderInterface
{
}
79 changes: 79 additions & 0 deletions test/Header/HeaderWrapTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Mail
* @subpackage UnitTests
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace ZendTest\Mail\Header;

use Zend\Mail\Header\HeaderWrap;

/**
* @category Zend
* @package Zend_Mail
* @subpackage UnitTests
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @group Zend_Mail
*/
class HeaderWrapTest extends \PHPUnit_Framework_TestCase
{
public function testWrapUnstructuredHeaderAscii()
{
$string = str_repeat('foobarblahblahblah baz bat', 4);
$header = $this->getMock('Zend\Mail\Header\UnstructuredInterface');
$header->expects($this->any())
->method('getEncoding')
->will($this->returnValue('ASCII'));
$expected = wordwrap($string, 78, "\r\n ");

$test = HeaderWrap::wrap($string, $header);
$this->assertEquals($expected, $test);
}

/**
* @group ZF2-258
*/
public function testWrapUnstructuredHeaderMime()
{
$string = str_repeat('foobarblahblahblah baz bat', 3);
$header = $this->getMock('Zend\Mail\Header\UnstructuredInterface');
$header->expects($this->any())
->method('getEncoding')
->will($this->returnValue('UTF-8'));
$expected = "=?UTF-8?Q?foobarblahblahblah=20baz=20batfoobarblahblahblah=20baz=20?=\r\n"
. " =?UTF-8?Q?batfoobarblahblahblah=20baz=20bat?=";

$test = HeaderWrap::wrap($string, $header);
$this->assertEquals($expected, $test);
$this->assertEquals($string, iconv_mime_decode($test));
}

/**
* @group ZF2-359
*/
public function testMimeEncoding()
{
$string = 'Umlauts: ä';
$expected = '=?UTF-8?Q?Umlauts:=20=C3=A4?=';

$test = HeaderWrap::mimeEncodeValue($string, 'UTF-8', 78);
$this->assertEquals($expected, $test);
$this->assertEquals($string, iconv_mime_decode($test, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8'));
}
}
31 changes: 6 additions & 25 deletions test/MessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -617,10 +617,6 @@ public function testEncodingIsMutable()

public function testSettingNonAsciiEncodingForcesMimeEncodingOfSomeHeaders()
{
if (!function_exists('iconv_mime_encode')) {
$this->markTestSkipped('Encoding relies on iconv extension');
}

$this->message->addTo('[email protected]', 'ZF DevTeam');
$this->message->addFrom('[email protected]', "Matthew Weier O'Phinney");
$this->message->addCc('[email protected]', 'ZF Contributors List');
Expand All @@ -630,38 +626,23 @@ public function testSettingNonAsciiEncodingForcesMimeEncodingOfSomeHeaders()

$test = $this->message->headers()->toString();

$expected = $this->encodeString('ZF DevTeam', 'UTF-8');
$expected = '=?UTF-8?Q?ZF=20DevTeam?=';
$this->assertContains($expected, $test);
$this->assertContains('<[email protected]>', $test);

$expected = $this->encodeString("Matthew Weier O'Phinney", 'UTF-8');
$expected = "=?UTF-8?Q?Matthew=20Weier=20O'Phinney?=";
$this->assertContains($expected, $test, $test);
$this->assertContains('<[email protected]>', $test);

$expected = $this->encodeString("ZF Contributors List", 'UTF-8');
$expected = '=?UTF-8?Q?ZF=20Contributors=20List?=';
$this->assertContains($expected, $test);
$this->assertContains('<[email protected]>', $test);

$expected = $this->encodeString("ZF CR Team", 'UTF-8');
$expected = '=?UTF-8?Q?ZF=20CR=20Team?=';
$this->assertContains($expected, $test);
$this->assertContains('<[email protected]>', $test);

$self = $this;
$words = array_map(function($word) use ($self) {
return $self->encodeString($word, 'UTF-8');
}, explode(' ', 'This is a subject'));
$expected = 'Subject: ' . implode("\r\n ", $words);
$this->assertContains($expected, $test, $test);
}

public function encodeString($string, $charset)
{
$encoded = iconv_mime_encode('Header', $string, array(
'scheme' => 'Q',
'output-charset' => $charset,
'line-length' => 998,
));
$encoded = str_replace('Header: ', '', $encoded);
return $encoded;
$expected = 'Subject: =?UTF-8?Q?This=20is=20a=20subject?=';
$this->assertContains($expected, $test);
}
}

0 comments on commit 3288109

Please sign in to comment.