diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index e8b69475aa3a1..cb9eaeaf3d3b3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -553,6 +553,10 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $
$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']);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_debug.xml
new file mode 100644
index 0000000000000..17ed496661f73
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_debug.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/Mailer/CHANGELOG.md b/src/Symfony/Component/Mailer/CHANGELOG.md
index 6a0669faca03f..76b895a6809e5 100644
--- a/src/Symfony/Component/Mailer/CHANGELOG.md
+++ b/src/Symfony/Component/Mailer/CHANGELOG.md
@@ -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`
diff --git a/src/Symfony/Component/Mailer/Event/MessageEvent.php b/src/Symfony/Component/Mailer/Event/MessageEvent.php
index 187f2c21c9dae..1ceb0916605b5 100644
--- a/src/Symfony/Component/Mailer/Event/MessageEvent.php
+++ b/src/Symfony/Component/Mailer/Event/MessageEvent.php
@@ -16,7 +16,7 @@
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
*/
@@ -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 @@ public function setEnvelope(SmtpEnvelope $envelope): void
{
$this->envelope = $envelope;
}
+
+ public function getTransportName(): string
+ {
+ return $this->transportName;
+ }
+
+ public function isQueued(): bool
+ {
+ return $this->queued;
+ }
}
diff --git a/src/Symfony/Component/Mailer/Event/MessageEvents.php b/src/Symfony/Component/Mailer/Event/MessageEvents.php
new file mode 100644
index 0000000000000..a921022cedab0
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Event/MessageEvents.php
@@ -0,0 +1,51 @@
+
+ *
+ * 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
+ */
+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;
+ }
+}
diff --git a/src/Symfony/Component/Mailer/EventListener/MessageLoggerListener.php b/src/Symfony/Component/Mailer/EventListener/MessageLoggerListener.php
new file mode 100644
index 0000000000000..093bf2bb9e5ac
--- /dev/null
+++ b/src/Symfony/Component/Mailer/EventListener/MessageLoggerListener.php
@@ -0,0 +1,57 @@
+
+ *
+ * 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
+ */
+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],
+ ];
+ }
+}
diff --git a/src/Symfony/Component/Mailer/Mailer.php b/src/Symfony/Component/Mailer/Mailer.php
index 324f50cad7803..db87602022c63 100644
--- a/src/Symfony/Component/Mailer/Mailer.php
+++ b/src/Symfony/Component/Mailer/Mailer.php
@@ -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 @@ public function send(RawMessage $message, SmtpEnvelope $envelope = null): void
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));
}
}
diff --git a/src/Symfony/Component/Mailer/Transport/AbstractTransport.php b/src/Symfony/Component/Mailer/Transport/AbstractTransport.php
index 3dd59c195c302..90b04c19abbba 100644
--- a/src/Symfony/Component/Mailer/Transport/AbstractTransport.php
+++ b/src/Symfony/Component/Mailer/Transport/AbstractTransport.php
@@ -69,7 +69,7 @@ public function send(RawMessage $message, SmtpEnvelope $envelope = null): ?SentM
}
}
- $event = new MessageEvent($message, $envelope);
+ $event = new MessageEvent($message, $envelope, $this->getName(), true);
$this->dispatcher->dispatch($event);
$envelope = $event->getEnvelope();
if (!$envelope->getRecipients()) {
diff --git a/src/Symfony/Component/Mailer/composer.json b/src/Symfony/Component/Mailer/composer.json
index 5c4ad672a7bc8..9d63924b08e70 100644
--- a/src/Symfony/Component/Mailer/composer.json
+++ b/src/Symfony/Component/Mailer/composer.json
@@ -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",