[Mailer] Add support for multiple mailers
This commit is contained in:
parent
ef2b65aaf1
commit
de5fae4dd8
@ -1555,8 +1555,17 @@ class Configuration implements ConfigurationInterface
|
||||
->arrayNode('mailer')
|
||||
->info('Mailer configuration')
|
||||
->{!class_exists(FullStack::class) && class_exists(Mailer::class) ? 'canBeDisabled' : 'canBeEnabled'}()
|
||||
->validate()
|
||||
->ifTrue(function ($v) { return isset($v['dsn']) && \count($v['transports']); })
|
||||
->thenInvalid('"dsn" and "transports" cannot be used together.')
|
||||
->end()
|
||||
->fixXmlConfig('transport')
|
||||
->children()
|
||||
->scalarNode('dsn')->defaultValue('smtp://null')->end()
|
||||
->scalarNode('dsn')->defaultNull()->end()
|
||||
->arrayNode('transports')
|
||||
->useAttributeAsKey('name')
|
||||
->prototype('scalar')->end()
|
||||
->end()
|
||||
->arrayNode('envelope')
|
||||
->info('Mailer Envelope configuration')
|
||||
->children()
|
||||
|
@ -1977,7 +1977,12 @@ class FrameworkExtension extends Extension
|
||||
|
||||
$loader->load('mailer.xml');
|
||||
$loader->load('mailer_transports.xml');
|
||||
$container->getDefinition('mailer.default_transport')->setArgument(0, $config['dsn']);
|
||||
if (!\count($config['transports']) && null === $config['dsn']) {
|
||||
$config['dsn'] = 'smtp://null';
|
||||
}
|
||||
$transports = $config['dsn'] ? ['main' => $config['dsn']] : $config['transports'];
|
||||
$container->getDefinition('mailer.transports')->setArgument(0, $transports);
|
||||
$container->getDefinition('mailer.default_transport')->setArgument(0, current($transports));
|
||||
|
||||
$classToServices = [
|
||||
SesTransportFactory::class => 'mailer.transport_factory.amazon',
|
||||
|
@ -6,13 +6,18 @@
|
||||
|
||||
<services>
|
||||
<service id="mailer.mailer" class="Symfony\Component\Mailer\Mailer">
|
||||
<argument type="service" id="mailer.default_transport" />
|
||||
<argument type="service" id="mailer.transports" />
|
||||
<argument type="service" id="messenger.default_bus" on-invalid="ignore" />
|
||||
<argument type="service" id="event_dispatcher" on-invalid="ignore" />
|
||||
</service>
|
||||
<service id="mailer" alias="mailer.mailer" />
|
||||
<service id="Symfony\Component\Mailer\MailerInterface" alias="mailer.mailer" />
|
||||
|
||||
<service id="mailer.transports" class="Symfony\Component\Mailer\Transports">
|
||||
<factory service="mailer.transport_factory" method="fromStrings" />
|
||||
<argument type="collection" /> <!-- transports -->
|
||||
</service>
|
||||
|
||||
<service id="mailer.transport_factory" class="Symfony\Component\Mailer\Transport">
|
||||
<argument type="tagged_iterator" tag="mailer.transport_factory" />
|
||||
</service>
|
||||
@ -24,7 +29,7 @@
|
||||
<service id="Symfony\Component\Mailer\Transport\TransportInterface" alias="mailer.default_transport" />
|
||||
|
||||
<service id="mailer.messenger.message_handler" class="Symfony\Component\Mailer\Messenger\MessageHandler">
|
||||
<argument type="service" id="mailer.default_transport" />
|
||||
<argument type="service" id="mailer.transports" />
|
||||
<tag name="messenger.message_handler" />
|
||||
</service>
|
||||
|
||||
|
@ -369,7 +369,8 @@ class ConfigurationTest extends TestCase
|
||||
'scoped_clients' => [],
|
||||
],
|
||||
'mailer' => [
|
||||
'dsn' => 'smtp://null',
|
||||
'dsn' => null,
|
||||
'transports' => [],
|
||||
'enabled' => !class_exists(FullStack::class) && class_exists(Mailer::class),
|
||||
],
|
||||
];
|
||||
|
@ -55,7 +55,7 @@ class MailerTest extends AbstractWebTestCase
|
||||
}
|
||||
};
|
||||
|
||||
$mailer = new Mailer($testTransport, null);
|
||||
$mailer = new Mailer($testTransport);
|
||||
|
||||
$message = (new Email())
|
||||
->subject('Test subject')
|
||||
|
@ -4,6 +4,7 @@ CHANGELOG
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* added support for multiple transports on a `Mailer` instance
|
||||
* [BC BREAK] removed the `auth_mode` DSN option (it is now always determined automatically)
|
||||
* STARTTLS cannot be enabled anymore (it is used automatically if TLS is disabled and the server supports STARTTLS)
|
||||
* [BC BREAK] Removed the `encryption` DSN option (use `smtps` instead)
|
||||
|
@ -22,7 +22,7 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Mailer implements MailerInterface
|
||||
final class Mailer implements MailerInterface
|
||||
{
|
||||
private $transport;
|
||||
private $bus;
|
||||
|
@ -27,6 +27,7 @@ use Symfony\Component\Mailer\Transport\SendmailTransportFactory;
|
||||
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory;
|
||||
use Symfony\Component\Mailer\Transport\TransportFactoryInterface;
|
||||
use Symfony\Component\Mailer\Transport\TransportInterface;
|
||||
use Symfony\Component\Mailer\Transport\Transports;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
@ -54,6 +55,13 @@ class Transport
|
||||
return $factory->fromString($dsn);
|
||||
}
|
||||
|
||||
public static function fromDsns(array $dsns, EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null): TransportInterface
|
||||
{
|
||||
$factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher, $client, $logger)));
|
||||
|
||||
return $factory->fromStrings($dsns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransportFactoryInterface[] $factories
|
||||
*/
|
||||
@ -62,6 +70,16 @@ class Transport
|
||||
$this->factories = $factories;
|
||||
}
|
||||
|
||||
public function fromStrings(array $dsns): Transports
|
||||
{
|
||||
$transports = [];
|
||||
foreach ($dsns as $name => $dsn) {
|
||||
$transports[$name] = $this->fromString($dsn);
|
||||
}
|
||||
|
||||
return new Transports($transports);
|
||||
}
|
||||
|
||||
public function fromString(string $dsn): TransportInterface
|
||||
{
|
||||
$dsns = preg_split('/\s++\|\|\s++/', $dsn);
|
||||
|
69
src/Symfony/Component/Mailer/Transport/Transports.php
Normal file
69
src/Symfony/Component/Mailer/Transport/Transports.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?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\Transport;
|
||||
|
||||
use Symfony\Component\Mailer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Mailer\Exception\LogicException;
|
||||
use Symfony\Component\Mailer\SentMessage;
|
||||
use Symfony\Component\Mailer\SmtpEnvelope;
|
||||
use Symfony\Component\Mime\Message;
|
||||
use Symfony\Component\Mime\RawMessage;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Transports implements TransportInterface
|
||||
{
|
||||
private $transports;
|
||||
private $default;
|
||||
|
||||
/**
|
||||
* @param TransportInterface[] $transports
|
||||
*/
|
||||
public function __construct(iterable $transports)
|
||||
{
|
||||
$this->transports = [];
|
||||
foreach ($transports as $name => $transport) {
|
||||
if (null === $this->default) {
|
||||
$this->default = $transport;
|
||||
}
|
||||
$this->transports[$name] = $transport;
|
||||
}
|
||||
|
||||
if (!$this->transports) {
|
||||
throw new LogicException(sprintf('"%s" must have at least one transport configured.', __CLASS__));
|
||||
}
|
||||
}
|
||||
|
||||
public function send(RawMessage $message, SmtpEnvelope $envelope = null): ?SentMessage
|
||||
{
|
||||
/** @var Message $message */
|
||||
if (RawMessage::class === \get_class($message) || !$message->getHeaders()->has('X-Transport')) {
|
||||
return $this->default->send($message, $envelope);
|
||||
}
|
||||
|
||||
$headers = $message->getHeaders();
|
||||
$transport = $headers->get('X-Transport');
|
||||
$headers->remove('X-Transport');
|
||||
|
||||
if (!isset($this->transports[$transport])) {
|
||||
throw new InvalidArgumentException(sprintf('The "%s" transport does not exist.', $transport));
|
||||
}
|
||||
|
||||
return $this->transports[$transport]->send($message, $envelope);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'all';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user