Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file, in reverse

### Added

- [#166](https://github.com/zendframework/zend-mail/pull/166) adds functionality for handling `References` and `In-Reply-To` headers.

- [#148](https://github.com/zendframework/zend-mail/pull/148) adds the optional constructor argument `$comment` and the method `getComment()` to the class
`Zend\Mail\Address`. When a comment is present, `toString()` will include it in the representation.

Expand Down
2 changes: 2 additions & 0 deletions src/Header/HeaderLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ class HeaderLoader extends PluginClassLoader
'content-transfer-encoding' => 'Zend\Mail\Header\ContentTransferEncoding',
'date' => 'Zend\Mail\Header\Date',
'from' => 'Zend\Mail\Header\From',
'in-reply-to' => 'Zend\Mail\Header\InReplyTo',
'message-id' => 'Zend\Mail\Header\MessageId',
'mimeversion' => 'Zend\Mail\Header\MimeVersion',
'mime_version' => 'Zend\Mail\Header\MimeVersion',
'mime-version' => 'Zend\Mail\Header\MimeVersion',
'received' => 'Zend\Mail\Header\Received',
'references' => 'Zend\Mail\Header\References',
'replyto' => 'Zend\Mail\Header\ReplyTo',
'reply_to' => 'Zend\Mail\Header\ReplyTo',
'reply-to' => 'Zend\Mail\Header\ReplyTo',
Expand Down
142 changes: 142 additions & 0 deletions src/Header/IdentificationField.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php
/**
* @see https://github.com/zendframework/zend-mail for the canonical source repository
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-mail/blob/master/LICENSE.md New BSD License
*/

namespace Zend\Mail\Header;

use Zend\Mail\Headers;

/**
* @see https://tools.ietf.org/html/rfc5322#section-3.6.4
*/
abstract class IdentificationField implements HeaderInterface
{
/**
* @var string lower case field name
*/
protected static $type;

/**
* @var string[]
*/
protected $messageIds;

/**
* @var string
*/
protected $fieldName;

/**
* @param string $headerLine
* @return static
*/
public static function fromString($headerLine)
{
list($name, $value) = GenericHeader::splitHeaderLine($headerLine);
if (strtolower($name) !== static::$type) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid header line for "%s" string',
__CLASS__
));
}

$value = HeaderWrap::mimeDecodeValue($value);

$messageIds = array_map(
[IdentificationField::class, "trimMessageId"],
explode(" ", $value)
);

$header = new static();
$header->setIds($messageIds);

return $header;
}

/**
* @param string $id
* @return string
*/
private static function trimMessageId($id)
{
return trim($id, "\t\n\r\0\x0B<>");
}

/**
* @return string
*/
public function getFieldName()
{
return $this->fieldName;
}

/**
* @param bool $format
* @return string
*/
public function getFieldValue($format = HeaderInterface::FORMAT_RAW)
{
return implode(Headers::FOLDING, array_map(function ($id) {
return sprintf('<%s>', $id);
}, $this->messageIds));
}

/**
* @param string $encoding Ignored; headers of this type MUST always be in
* ASCII.
* @return static This method is a no-op, and implements a fluent interface.
*/
public function setEncoding($encoding)
{
return $this;
}

/**
* @return string Always returns ASCII
*/
public function getEncoding()
{
return 'ASCII';
}

/**
* @return string
*/
public function toString()
{
return sprintf('%s: %s', $this->fieldName, $this->getFieldValue());
}

/**
* Set the message ids
*
* @param string[] $ids
* @return static This method implements a fluent interface.
*/
public function setIds($ids)
{
foreach ($ids as $id) {
if (! HeaderValue::isValid($id)
|| preg_match("/[\r\n]/", $id)
) {
throw new Exception\InvalidArgumentException('Invalid ID detected');
}
}

$this->messageIds = array_map([IdentificationField::class, "trimMessageId"], $ids);
return $this;
}

/**
* Retrieve the message ids
*
* @return string[]
*/
public function getIds()
{
return $this->messageIds;
}
}
14 changes: 14 additions & 0 deletions src/Header/InReplyTo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/**
* @see https://github.com/zendframework/zend-mail for the canonical source repository
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-mail/blob/master/LICENSE.md New BSD License
*/

namespace Zend\Mail\Header;

class InReplyTo extends IdentificationField
{
protected $fieldName = 'In-Reply-To';
protected static $type = 'in-reply-to';
}
14 changes: 14 additions & 0 deletions src/Header/References.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/**
* @see https://github.com/zendframework/zend-mail for the canonical source repository
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-mail/blob/master/LICENSE.md New BSD License
*/

namespace Zend\Mail\Header;

class References extends IdentificationField
{
protected $fieldName = 'References';
protected static $type = 'references';
}
70 changes: 70 additions & 0 deletions test/Header/IdentificationFieldTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
/**
* @see https://github.com/zendframework/zend-mail for the canonical source repository
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com)
* @license https://github.com/zendframework/zend-mail/blob/master/LICENSE.md New BSD License
*/

namespace ZendTest\Mail\Header;

use PHPUnit\Framework\TestCase;
use Zend\Mail\Header\IdentificationField;
use Zend\Mail\Header\InReplyTo;
use Zend\Mail\Header\References;

class IdentificationFieldTest extends TestCase
{
public function stringHeadersProvider()
{
return array_merge(
[
[
References::class,
'References: <1234@local.machine.example> <3456@example.net>',
['1234@local.machine.example', '3456@example.net']
]
],
$this->reversibleStringHeadersProvider()
);
}

public function reversibleStringHeadersProvider()
{
return [
[References::class, 'References: <1234@local.machine.example>', ['1234@local.machine.example']],
[
References::class,
"References: <1234@local.machine.example>\r\n <3456@example.net>",
['1234@local.machine.example', '3456@example.net']
],
[InReplyTo::class, 'In-Reply-To: <3456@example.net>', ['3456@example.net']]
];
}

/**
* @dataProvider stringHeadersProvider
* @param string $className
* @param string $headerString
* @param string[] $ids
*/
public function testDeserializationFromString($className, $headerString, $ids)
{
/** @var IdentificationField $header */
$header = $className::fromString($headerString);
$this->assertEquals($ids, $header->getIds());
}

/**
* @dataProvider reversibleStringHeadersProvider
* @param string $className
* @param string $headerString
* @param string[] $ids
*/
public function testSerializationToString($className, $headerString, $ids)
{
/** @var IdentificationField $header */
$header = new $className();
$header->setIds($ids);
$this->assertEquals($headerString, $header->toString());
}
}