feature #32927 [Mailer] Add message events logger (fabpot)

This PR was merged into the 4.4 branch.

Discussion
----------

[Mailer] Add message events logger

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | refs #31592, refs #32409, refs #31947, refs #31747
| License       | MIT
| Doc PR        | n/a

To allow testing emails and for the web profiler, we need a way to store all sent/queued messages.

Commits
-------

7642178d76 [Mailer] added message events logger
This commit is contained in:
Fabien Potencier 2019-08-04 18:10:17 +02:00
commit aa93f0b611
9 changed files with 159 additions and 4 deletions

View File

@ -553,6 +553,10 @@ class FrameworkExtension extends Extension
$loader->load('messenger_debug.xml');
}
if (class_exists(Mailer::class)) {
$loader->load('mailer_debug.xml');
}
$container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']);
$container->setParameter('profiler_listener.only_master_requests', $config['only_master_requests']);

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="mailer.logger_message_listener" class="Symfony\Component\Mailer\EventListener\MessageLoggerListener">
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>

View File

@ -4,6 +4,7 @@ CHANGELOG
4.4.0
-----
* Added `MessageEvents` and `MessageLoggerListener` to allow collecting sent emails
* [BC BREAK] `TransportInterface` has a new `getName()` method
* [BC BREAK] Classes `AbstractApiTransport` and `AbstractHttpTransport` moved under `Transport` sub-namespace.
* [BC BREAK] Transports depend on `Symfony\Contracts\EventDispatcher\EventDispatcherInterface`

View File

@ -16,7 +16,7 @@ use Symfony\Component\Mailer\SmtpEnvelope;
use Symfony\Component\Mime\RawMessage;
/**
* Allows the transformation of a Message.
* Allows the transformation of a Message and the SMTP Envelope before the email is sent.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
@ -24,11 +24,15 @@ class MessageEvent extends Event
{
private $message;
private $envelope;
private $transportName;
private $queued;
public function __construct(RawMessage $message, SmtpEnvelope $envelope)
public function __construct(RawMessage $message, SmtpEnvelope $envelope, string $transportName, bool $queued = false)
{
$this->message = $message;
$this->envelope = $envelope;
$this->transportName = $transportName;
$this->queued = $queued;
}
public function getMessage(): RawMessage
@ -50,4 +54,14 @@ class MessageEvent extends Event
{
$this->envelope = $envelope;
}
public function getTransportName(): string
{
return $this->transportName;
}
public function isQueued(): bool
{
return $this->queued;
}
}

View File

@ -0,0 +1,51 @@
<?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\Event;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
class MessageEvents
{
private $events = [];
private $transports = [];
public function add(MessageEvent $event): void
{
$this->events[] = $event;
$this->transports[$event->getTransportName()] = true;
}
public function getTransports(): array
{
return array_keys($this->transports);
}
/**
* @return MessageEvent[]
*/
public function getEvents(string $name = null): array
{
if (null === $name) {
return $this->events;
}
$events = [];
foreach ($this->events as $event) {
if ($name === $event->getTransportName()) {
$events[] = $event;
}
}
return $events;
}
}

View File

@ -0,0 +1,57 @@
<?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\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mailer\Event\MessageEvents;
use Symfony\Contracts\Service\ResetInterface;
/**
* Logs Messages.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class MessageLoggerListener implements EventSubscriberInterface, ResetInterface
{
private $events;
public function __construct()
{
$this->events = new MessageEvents();
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->events = new MessageEvents();
}
public function onMessage(MessageEvent $event): void
{
$this->events->add($event);
}
public function getEvents(): MessageEvents
{
return $this->events;
}
public static function getSubscribedEvents()
{
return [
MessageEvent::class => ['onMessage', -255],
];
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Mailer;
use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mailer\Exception\TransportException;
use Symfony\Component\Mailer\Messenger\SendEmailMessage;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Messenger\MessageBusInterface;
@ -38,6 +40,19 @@ class Mailer implements MailerInterface
return;
}
$message = clone $message;
if (null !== $envelope) {
$envelope = clone $envelope;
} else {
try {
$envelope = new DelayedSmtpEnvelope($message);
} catch (\Exception $e) {
throw new TransportException('Cannot send message without a valid envelope.', 0, $e);
}
}
$event = new MessageEvent($message, $envelope, $this->transport->getName());
$this->dispatcher->dispatch($event);
$this->bus->dispatch(new SendEmailMessage($message, $envelope));
}
}

View File

@ -69,7 +69,7 @@ abstract class AbstractTransport implements TransportInterface
}
}
$event = new MessageEvent($message, $envelope);
$event = new MessageEvent($message, $envelope, $this->getName(), true);
$this->dispatcher->dispatch($event);
$envelope = $event->getEnvelope();
if (!$envelope->getRecipients()) {

View File

@ -20,7 +20,8 @@
"egulias/email-validator": "^2.0",
"psr/log": "~1.0",
"symfony/event-dispatcher": "^4.3",
"symfony/mime": "^4.3.3|^5.0"
"symfony/mime": "^4.3.3|^5.0",
"symfony/service-contracts": "^1.1"
},
"require-dev": {
"symfony/amazon-mailer": "^4.4|^5.0",