feature #36736 [FrameworkBundle][Mailer] Add a way to configure some email headers from semantic configuration (fabpot)
This PR was merged into the 5.2-dev branch.
Discussion
----------
[FrameworkBundle][Mailer] Add a way to configure some email headers from semantic configuration
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | yes <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets | n/a <!-- prefix each issue number with "Fix #", if any -->
| License | MIT
| Doc PR | not yet
The configuration allows to set global `sender` and `recipients`, but for the *envelope*.
If you want to set some global headers, it was not possible (a default `from` header for instance, of a `bcc`).
That's implemented in this PR.
Commits
-------
805e9e62c1
[FrameworkBundle][Mailer] Add a way to configure some email headers from semantic configuration
This commit is contained in:
commit
4d477ec3f0
@ -1492,6 +1492,7 @@ class Configuration implements ConfigurationInterface
|
||||
->thenInvalid('"dsn" and "transports" cannot be used together.')
|
||||
->end()
|
||||
->fixXmlConfig('transport')
|
||||
->fixXmlConfig('header')
|
||||
->children()
|
||||
->scalarNode('message_bus')->defaultNull()->info('The message bus to use. Defaults to the default bus if the Messenger component is installed.')->end()
|
||||
->scalarNode('dsn')->defaultNull()->end()
|
||||
@ -1515,6 +1516,20 @@ class Configuration implements ConfigurationInterface
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('headers')
|
||||
->normalizeKeys(false)
|
||||
->useAttributeAsKey('name')
|
||||
->prototype('array')
|
||||
->normalizeKeys(false)
|
||||
->beforeNormalization()
|
||||
->ifTrue(function ($v) { return !\is_array($v) || array_keys($v) !== ['value']; })
|
||||
->then(function ($v) { return ['value' => $v]; })
|
||||
->end()
|
||||
->children()
|
||||
->variableNode('value')->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
|
@ -89,6 +89,7 @@ use Symfony\Component\Messenger\MessageBus;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Messenger\Transport\TransportFactoryInterface;
|
||||
use Symfony\Component\Messenger\Transport\TransportInterface;
|
||||
use Symfony\Component\Mime\Header\Headers;
|
||||
use Symfony\Component\Mime\MimeTypeGuesserInterface;
|
||||
use Symfony\Component\Mime\MimeTypes;
|
||||
use Symfony\Component\Notifier\Bridge\Firebase\FirebaseTransportFactory;
|
||||
@ -1986,12 +1987,24 @@ class FrameworkExtension extends Extension
|
||||
}
|
||||
}
|
||||
|
||||
$recipients = $config['envelope']['recipients'] ?? null;
|
||||
$sender = $config['envelope']['sender'] ?? null;
|
||||
|
||||
$envelopeListener = $container->getDefinition('mailer.envelope_listener');
|
||||
$envelopeListener->setArgument(0, $sender);
|
||||
$envelopeListener->setArgument(1, $recipients);
|
||||
$envelopeListener->setArgument(0, $config['envelope']['sender'] ?? null);
|
||||
$envelopeListener->setArgument(1, $config['envelope']['recipients'] ?? null);
|
||||
|
||||
if ($config['headers']) {
|
||||
$headers = new Definition(Headers::class);
|
||||
foreach ($config['headers'] as $name => $data) {
|
||||
$value = $data['value'];
|
||||
if (\in_array(strtolower($name), ['from', 'to', 'cc', 'bcc', 'reply-to'])) {
|
||||
$value = (array) $value;
|
||||
}
|
||||
$headers->addMethodCall('addHeader', [$name, $value]);
|
||||
}
|
||||
$messageListener = $container->getDefinition('mailer.message_listener');
|
||||
$messageListener->setArgument(0, $headers);
|
||||
} else {
|
||||
$container->removeDefinition('mailer.message_listener');
|
||||
}
|
||||
}
|
||||
|
||||
private function registerNotifierConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
|
@ -39,6 +39,11 @@
|
||||
<tag name="kernel.event_subscriber"/>
|
||||
</service>
|
||||
|
||||
<service id="mailer.message_listener" class="Symfony\Component\Mailer\EventListener\MessageListener">
|
||||
<argument /> <!-- headers -->
|
||||
<tag name="kernel.event_subscriber"/>
|
||||
</service>
|
||||
|
||||
<service id="mailer.logger_message_listener" class="Symfony\Component\Mailer\EventListener\MessageLoggerListener">
|
||||
<tag name="kernel.event_subscriber"/>
|
||||
</service>
|
||||
|
@ -560,14 +560,19 @@
|
||||
<xsd:complexType name="mailer">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="envelope" type="mailer_envelope" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="header" type="header" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="dsn" type="xsd:string" />
|
||||
<xsd:attribute name="message-bus" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="header" mixed="true">
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="mailer_envelope">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="sender" type="xsd:string" />
|
||||
<xsd:element name="sender" type="xsd:string" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="recipients" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
@ -493,6 +493,7 @@ class ConfigurationTest extends TestCase
|
||||
'transports' => [],
|
||||
'enabled' => !class_exists(FullStack::class) && class_exists(Mailer::class),
|
||||
'message_bus' => null,
|
||||
'headers' => [],
|
||||
],
|
||||
'notifier' => [
|
||||
'enabled' => !class_exists(FullStack::class) && class_exists(Notifier::class),
|
||||
|
@ -7,5 +7,10 @@ $container->loadFromExtension('framework', [
|
||||
'sender' => 'sender@example.org',
|
||||
'recipients' => ['redirected@example.org', 'redirected1@example.org'],
|
||||
],
|
||||
'headers' => [
|
||||
'from' => 'from@example.org',
|
||||
'bcc' => ['bcc1@example.org', 'bcc2@example.org'],
|
||||
'foo' => 'bar',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
@ -13,6 +13,9 @@
|
||||
<framework:recipients>redirected@example.org</framework:recipients>
|
||||
<framework:recipients>redirected1@example.org</framework:recipients>
|
||||
</framework:envelope>
|
||||
<framework:header name="from">from@example.org</framework:header>
|
||||
<framework:header name="bcc">bcc1@example.org</framework:header>
|
||||
<framework:header name="foo">bar</framework:header>
|
||||
</framework:mailer>
|
||||
</framework:config>
|
||||
</container>
|
||||
|
@ -6,3 +6,7 @@ framework:
|
||||
recipients:
|
||||
- redirected@example.org
|
||||
- redirected1@example.org
|
||||
headers:
|
||||
from: from@example.org
|
||||
bcc: [bcc1@example.org, bcc2@example.org]
|
||||
foo: bar
|
||||
|
@ -1435,6 +1435,11 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertSame('sender@example.org', $l->getArgument(0));
|
||||
$this->assertSame(['redirected@example.org', 'redirected1@example.org'], $l->getArgument(1));
|
||||
$this->assertEquals(new Reference('messenger.default_bus', ContainerInterface::NULL_ON_INVALID_REFERENCE), $container->getDefinition('mailer.mailer')->getArgument(1));
|
||||
|
||||
$this->assertTrue($container->hasDefinition('mailer.message_listener'));
|
||||
$l = $container->getDefinition('mailer.message_listener');
|
||||
$h = $l->getArgument(0);
|
||||
$this->assertCount(3, $h->getMethodCalls());
|
||||
}
|
||||
|
||||
public function testMailerWithDisabledMessageBus(): void
|
||||
|
@ -45,7 +45,7 @@
|
||||
"symfony/expression-language": "^4.4|^5.0",
|
||||
"symfony/http-client": "^4.4|^5.0",
|
||||
"symfony/lock": "^4.4|^5.0",
|
||||
"symfony/mailer": "^4.4|^5.0",
|
||||
"symfony/mailer": "^5.2",
|
||||
"symfony/messenger": "^4.4|^5.0",
|
||||
"symfony/mime": "^4.4|^5.0",
|
||||
"symfony/process": "^4.4|^5.0",
|
||||
@ -79,7 +79,7 @@
|
||||
"symfony/http-client": "<4.4",
|
||||
"symfony/form": "<4.4",
|
||||
"symfony/lock": "<4.4",
|
||||
"symfony/mailer": "<4.4",
|
||||
"symfony/mailer": "<5.2",
|
||||
"symfony/messenger": "<4.4",
|
||||
"symfony/mime": "<4.4",
|
||||
"symfony/property-info": "<4.4",
|
||||
|
@ -13,8 +13,11 @@ namespace Symfony\Component\Mailer\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Mailer\Event\MessageEvent;
|
||||
use Symfony\Component\Mailer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Mailer\Exception\RuntimeException;
|
||||
use Symfony\Component\Mime\BodyRendererInterface;
|
||||
use Symfony\Component\Mime\Header\Headers;
|
||||
use Symfony\Component\Mime\Header\MailboxListHeader;
|
||||
use Symfony\Component\Mime\Message;
|
||||
|
||||
/**
|
||||
@ -24,13 +27,38 @@ use Symfony\Component\Mime\Message;
|
||||
*/
|
||||
class MessageListener implements EventSubscriberInterface
|
||||
{
|
||||
public const HEADER_SET_IF_EMPTY = 1;
|
||||
public const HEADER_ADD = 2;
|
||||
public const HEADER_REPLACE = 3;
|
||||
public const DEFAULT_RULES = [
|
||||
'from' => self::HEADER_SET_IF_EMPTY,
|
||||
'return-path' => self::HEADER_SET_IF_EMPTY,
|
||||
'reply-to' => self::HEADER_ADD,
|
||||
'to' => self::HEADER_SET_IF_EMPTY,
|
||||
'cc' => self::HEADER_ADD,
|
||||
'bcc' => self::HEADER_ADD,
|
||||
];
|
||||
|
||||
private $headers;
|
||||
private $headerRules = [];
|
||||
private $renderer;
|
||||
|
||||
public function __construct(Headers $headers = null, BodyRendererInterface $renderer = null)
|
||||
public function __construct(Headers $headers = null, BodyRendererInterface $renderer = null, array $headerRules = self::DEFAULT_RULES)
|
||||
{
|
||||
$this->headers = $headers;
|
||||
$this->renderer = $renderer;
|
||||
foreach ($headerRules as $headerName => $rule) {
|
||||
$this->addHeaderRule($headerName, $rule);
|
||||
}
|
||||
}
|
||||
|
||||
public function addHeaderRule(string $headerName, int $rule): void
|
||||
{
|
||||
if ($rule < 1 || $rule > 3) {
|
||||
throw new InvalidArgumentException(sprintf('The "%d" rule is not supported.', $rule));
|
||||
}
|
||||
|
||||
$this->headerRules[$headerName] = $rule;
|
||||
}
|
||||
|
||||
public function onMessage(MessageEvent $event): void
|
||||
@ -54,14 +82,38 @@ class MessageListener implements EventSubscriberInterface
|
||||
foreach ($this->headers->all() as $name => $header) {
|
||||
if (!$headers->has($name)) {
|
||||
$headers->add($header);
|
||||
} else {
|
||||
if (Headers::isUniqueHeader($name)) {
|
||||
continue;
|
||||
}
|
||||
$headers->add($header);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($this->headerRules[$name] ?? self::HEADER_SET_IF_EMPTY) {
|
||||
case self::HEADER_SET_IF_EMPTY:
|
||||
break;
|
||||
|
||||
case self::HEADER_REPLACE:
|
||||
$headers->remove($name);
|
||||
$headers->add($header);
|
||||
|
||||
break;
|
||||
|
||||
case self::HEADER_ADD:
|
||||
if (!Headers::isUniqueHeader($name)) {
|
||||
$headers->add($header);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$h = $headers->get($name);
|
||||
if (!$h instanceof MailboxListHeader) {
|
||||
throw new RuntimeException(sprintf('Unable to set header "%s".', $name));
|
||||
}
|
||||
|
||||
Headers::checkHeaderClass($header);
|
||||
foreach ($header->getAddresses() as $address) {
|
||||
$h->addAddress($address);
|
||||
}
|
||||
}
|
||||
}
|
||||
$message->setHeaders($headers);
|
||||
}
|
||||
|
||||
private function renderMessage(Message $message): void
|
||||
|
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Mailer\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\Event\MessageEvent;
|
||||
use Symfony\Component\Mailer\EventListener\MessageListener;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Header\Headers;
|
||||
use Symfony\Component\Mime\Header\MailboxListHeader;
|
||||
use Symfony\Component\Mime\Header\UnstructuredHeader;
|
||||
use Symfony\Component\Mime\Message;
|
||||
|
||||
class MessageListenerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideHeaders
|
||||
*/
|
||||
public function testHeaders(Headers $initialHeaders, Headers $defaultHeaders, Headers $expectedHeaders, array $rules = MessageListener::DEFAULT_RULES)
|
||||
{
|
||||
$message = new Message($initialHeaders);
|
||||
$listener = new MessageListener($defaultHeaders, null, $rules);
|
||||
$event = new MessageEvent($message, new Envelope(new Address('sender@example.com'), [new Address('recipient@example.com')]), 'smtp');
|
||||
$listener->onMessage($event);
|
||||
|
||||
$this->assertEquals($expectedHeaders, $event->getMessage()->getHeaders());
|
||||
}
|
||||
|
||||
public function provideHeaders(): iterable
|
||||
{
|
||||
$initialHeaders = new Headers();
|
||||
$defaultHeaders = (new Headers())
|
||||
->add(new MailboxListHeader('from', [new Address('from-default@example.com')]))
|
||||
;
|
||||
yield 'No defaults, all headers copied over' => [$initialHeaders, $defaultHeaders, $defaultHeaders];
|
||||
|
||||
$initialHeaders = new Headers();
|
||||
$defaultHeaders = (new Headers())
|
||||
->add(new UnstructuredHeader('foo', 'bar'))
|
||||
->add(new UnstructuredHeader('bar', 'foo'))
|
||||
;
|
||||
yield 'No defaults, default is to set if empty' => [$initialHeaders, $defaultHeaders, $defaultHeaders];
|
||||
|
||||
$initialHeaders = (new Headers())
|
||||
->add(new UnstructuredHeader('foo', 'initial'))
|
||||
;
|
||||
$defaultHeaders = (new Headers())
|
||||
->add(new UnstructuredHeader('foo', 'bar'))
|
||||
->add(new UnstructuredHeader('bar', 'foo'))
|
||||
;
|
||||
$expectedHeaders = (new Headers())
|
||||
->add(new UnstructuredHeader('foo', 'initial'))
|
||||
->add(new UnstructuredHeader('bar', 'foo'))
|
||||
;
|
||||
yield 'Some defaults, default is to set if empty' => [$initialHeaders, $defaultHeaders, $expectedHeaders];
|
||||
|
||||
$initialHeaders = (new Headers())
|
||||
->add(new UnstructuredHeader('foo', 'initial'))
|
||||
;
|
||||
$defaultHeaders = (new Headers())
|
||||
->add(new UnstructuredHeader('foo', 'bar'))
|
||||
->add(new UnstructuredHeader('bar', 'foo'))
|
||||
;
|
||||
$rules = [
|
||||
'foo' => MessageListener::HEADER_REPLACE,
|
||||
];
|
||||
yield 'Some defaults, replace if set' => [$initialHeaders, $defaultHeaders, $defaultHeaders, $rules];
|
||||
|
||||
$initialHeaders = (new Headers())
|
||||
->add(new UnstructuredHeader('foo', 'bar'))
|
||||
;
|
||||
$defaultHeaders = (new Headers())
|
||||
->add(new UnstructuredHeader('foo', 'foo'))
|
||||
;
|
||||
$expectedHeaders = (new Headers())
|
||||
->add(new UnstructuredHeader('foo', 'bar'))
|
||||
->add(new UnstructuredHeader('foo', 'foo'))
|
||||
;
|
||||
$rules = [
|
||||
'foo' => MessageListener::HEADER_ADD,
|
||||
];
|
||||
yield 'Some defaults, add if set (not unique header)' => [$initialHeaders, $defaultHeaders, $expectedHeaders, $rules];
|
||||
|
||||
$initialHeaders = (new Headers())
|
||||
->add(new MailboxListHeader('bcc', [new Address('bcc-initial@example.com')]))
|
||||
;
|
||||
$defaultHeaders = (new Headers())
|
||||
->add(new MailboxListHeader('bcc', [new Address('bcc-default@example.com'), new Address('bcc-default-1@example.com')]))
|
||||
;
|
||||
$expectedHeaders = (new Headers())
|
||||
->add(new MailboxListHeader('bcc', [new Address('bcc-initial@example.com'), new Address('bcc-default@example.com'), new Address('bcc-default-1@example.com')]))
|
||||
;
|
||||
yield 'bcc, add another bcc (unique header)' => [$initialHeaders, $defaultHeaders, $expectedHeaders];
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
"egulias/email-validator": "^2.1.10",
|
||||
"psr/log": "~1.0",
|
||||
"symfony/event-dispatcher": "^4.4|^5.0",
|
||||
"symfony/mime": "^4.4|^5.0",
|
||||
"symfony/mime": "^5.2",
|
||||
"symfony/polyfill-php80": "^1.15",
|
||||
"symfony/service-contracts": "^1.1|^2"
|
||||
},
|
||||
|
@ -21,10 +21,23 @@ use Symfony\Component\Mime\Exception\LogicException;
|
||||
*/
|
||||
final class Headers
|
||||
{
|
||||
private static $uniqueHeaders = [
|
||||
private const UNIQUE_HEADERS = [
|
||||
'date', 'from', 'sender', 'reply-to', 'to', 'cc', 'bcc',
|
||||
'message-id', 'in-reply-to', 'references', 'subject',
|
||||
];
|
||||
private const HEADER_CLASS_MAP = [
|
||||
'date' => DateHeader::class,
|
||||
'from' => MailboxListHeader::class,
|
||||
'sender' => MailboxHeader::class,
|
||||
'reply-to' => MailboxListHeader::class,
|
||||
'to' => MailboxListHeader::class,
|
||||
'cc' => MailboxListHeader::class,
|
||||
'bcc' => MailboxListHeader::class,
|
||||
'message-id' => IdentificationHeader::class,
|
||||
'in-reply-to' => IdentificationHeader::class,
|
||||
'references' => IdentificationHeader::class,
|
||||
'return-path' => PathHeader::class,
|
||||
];
|
||||
|
||||
private $headers = [];
|
||||
private $lineLength = 76;
|
||||
@ -122,6 +135,22 @@ final class Headers
|
||||
return $this->add(new ParameterizedHeader($name, $value, $params));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function addHeader(string $name, $argument, array $more = []): self
|
||||
{
|
||||
$parts = explode('\\', self::HEADER_CLASS_MAP[$name] ?? UnstructuredHeader::class);
|
||||
$method = 'add'.ucfirst(array_pop($parts));
|
||||
if ('addUnstructuredHeader' === $method) {
|
||||
$method = 'addTextHeader';
|
||||
} elseif ('addIdentificationHeader' === $method) {
|
||||
$method = 'addIdHeader';
|
||||
}
|
||||
|
||||
return $this->$method($name, $argument, $more);
|
||||
}
|
||||
|
||||
public function has(string $name): bool
|
||||
{
|
||||
return isset($this->headers[strtolower($name)]);
|
||||
@ -132,28 +161,12 @@ final class Headers
|
||||
*/
|
||||
public function add(HeaderInterface $header): self
|
||||
{
|
||||
static $map = [
|
||||
'date' => DateHeader::class,
|
||||
'from' => MailboxListHeader::class,
|
||||
'sender' => MailboxHeader::class,
|
||||
'reply-to' => MailboxListHeader::class,
|
||||
'to' => MailboxListHeader::class,
|
||||
'cc' => MailboxListHeader::class,
|
||||
'bcc' => MailboxListHeader::class,
|
||||
'message-id' => IdentificationHeader::class,
|
||||
'in-reply-to' => IdentificationHeader::class,
|
||||
'references' => IdentificationHeader::class,
|
||||
'return-path' => PathHeader::class,
|
||||
];
|
||||
self::checkHeaderClass($header);
|
||||
|
||||
$header->setMaxLineLength($this->lineLength);
|
||||
$name = strtolower($header->getName());
|
||||
|
||||
if (isset($map[$name]) && !$header instanceof $map[$name]) {
|
||||
throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $map[$name], get_debug_type($header)));
|
||||
}
|
||||
|
||||
if (\in_array($name, self::$uniqueHeaders, true) && isset($this->headers[$name]) && \count($this->headers[$name]) > 0) {
|
||||
if (\in_array($name, self::UNIQUE_HEADERS, true) && isset($this->headers[$name]) && \count($this->headers[$name]) > 0) {
|
||||
throw new LogicException(sprintf('Impossible to set header "%s" as it\'s already defined and must be unique.', $header->getName()));
|
||||
}
|
||||
|
||||
@ -201,7 +214,19 @@ final class Headers
|
||||
|
||||
public static function isUniqueHeader(string $name): bool
|
||||
{
|
||||
return \in_array($name, self::$uniqueHeaders, true);
|
||||
return \in_array($name, self::UNIQUE_HEADERS, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws LogicException if the header name and class are not compatible
|
||||
*/
|
||||
public static function checkHeaderClass(HeaderInterface $header): void
|
||||
{
|
||||
$name = strtolower($header->getName());
|
||||
|
||||
if (($c = self::HEADER_CLASS_MAP[$name] ?? null) && !$header instanceof $c) {
|
||||
throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $c, get_debug_type($header)));
|
||||
}
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
|
@ -13,9 +13,11 @@ namespace Symfony\Component\Mime\Tests\Header;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Header\DateHeader;
|
||||
use Symfony\Component\Mime\Header\Headers;
|
||||
use Symfony\Component\Mime\Header\IdentificationHeader;
|
||||
use Symfony\Component\Mime\Header\MailboxListHeader;
|
||||
use Symfony\Component\Mime\Header\PathHeader;
|
||||
use Symfony\Component\Mime\Header\UnstructuredHeader;
|
||||
|
||||
class HeadersTest extends TestCase
|
||||
@ -63,6 +65,31 @@ class HeadersTest extends TestCase
|
||||
$this->assertNotNull($headers->get('Return-Path'));
|
||||
}
|
||||
|
||||
public function testAddHeader()
|
||||
{
|
||||
$headers = new Headers();
|
||||
$headers->addHeader('from', ['from@example.com']);
|
||||
$headers->addHeader('return-path', 'return@example.com');
|
||||
$headers->addHeader('foo', 'bar');
|
||||
$headers->addHeader('date', $now = new \DateTimeImmutable());
|
||||
$headers->addHeader('message-id', 'id@id');
|
||||
|
||||
$this->assertInstanceOf(MailboxListHeader::class, $headers->get('from'));
|
||||
$this->assertEquals([new Address('from@example.com')], $headers->get('from')->getBody());
|
||||
|
||||
$this->assertInstanceOf(PathHeader::class, $headers->get('return-path'));
|
||||
$this->assertEquals(new Address('return@example.com'), $headers->get('return-path')->getBody());
|
||||
|
||||
$this->assertInstanceOf(UnstructuredHeader::class, $headers->get('foo'));
|
||||
$this->assertSame('bar', $headers->get('foo')->getBody());
|
||||
|
||||
$this->assertInstanceOf(DateHeader::class, $headers->get('date'));
|
||||
$this->assertSame($now, $headers->get('date')->getBody());
|
||||
|
||||
$this->assertInstanceOf(IdentificationHeader::class, $headers->get('message-id'));
|
||||
$this->assertSame(['id@id'], $headers->get('message-id')->getBody());
|
||||
}
|
||||
|
||||
public function testHasReturnsFalseWhenNoHeaders()
|
||||
{
|
||||
$headers = new Headers();
|
||||
|
Reference in New Issue
Block a user