feat: send mailings over MailJet smtp in dedicated worker process

This commit is contained in:
Björn Fromme committed 2026-08-12 15:47:04 +02:00
1 parent a5c98025d0
commit e0a9562fc6
14 files changed
+480 -44

No files matched your search

+18
View File
@@ -44,6 +44,20 @@ class Mailer
->context($context)
;
// Both headers are read and removed further down the stack: X-Transport by
// Mailer\Transport\Transports when the mail is handed to a transport, and
// X-Bus-Transport by Mailer\EventListener\MessengerTransportListener while the
// mail is queued. Without them a mail takes the first mailer transport and the
// routing configured for SendEmailMessage, which is what every caller but the
// teamer mailing wants.
if (null !== $config['transport']) {
$email->getHeaders()->addTextHeader('X-Transport', $config['transport']);
}
if (null !== $config['bus_transport']) {
$email->getHeaders()->addTextHeader('X-Bus-Transport', $config['bus_transport']);
}
foreach ($config['attachments'] as $attachment) {
/* @var EmailAttachmentInterface $attachment */
$attachment->attachTo($email);
@@ -83,6 +97,8 @@ class Mailer
'to' => $this->defaults['to'],
'subject_parameters' => [],
'attachments' => [],
'transport' => null,
'bus_transport' => null,
])
->setRequired([
'template',
@@ -93,6 +109,8 @@ class Mailer
->setAllowedTypes('subject', 'string')
->setAllowedTypes('subject_parameters', 'array')
->setAllowedTypes('attachments', 'array')
->setAllowedTypes('transport', ['null', 'string'])
->setAllowedTypes('bus_transport', ['null', 'string'])
;
return $resolver->resolve($options);
@@ -0,0 +1,37 @@
<?php
namespace App\Email;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mime\Message;
/**
* Keeps the X-Bus-Transport header out of the mail that is actually delivered.
*
* Symfony's own listener removes the header while queueing, but it is handed a clone of
* the message and the original is what goes onto the bus (see Mailer::send(), which says
* so in as many words). The routing works either way - the stamp is read off that clone -
* but without this the header travels all the way to the recipient, and with the Mailjet
* API transport it is forwarded as a custom header on top, telling everyone which queue
* we sort our mail into.
*
* Only the delivering pass is of interest here: while the mail is queued the header still
* has to be there for Symfony to route on.
*/
#[AsEventListener(event: MessageEvent::class)]
class RemoveBusTransportHeaderListener
{
public function __invoke(MessageEvent $event): void
{
if (true === $event->isQueued()) {
return;
}
$message = $event->getMessage();
if ($message instanceof Message) {
$message->getHeaders()->remove('X-Bus-Transport');
}
}
}