In case somebody is processing emails via message-queue (symfony/messenger), using memory spool is preferred option. However, memory spool is processed only on Kernel::terminate
event. This event will never occur on long running console worker.
This kernel event is invoking SymfonyBundleSwiftmailerBundleEventListenerEmailSenderListener::onTerminate()
method. You can invoke this method manually by dispatching your own event & subscribing above mentioned method to it.
src/App/Email/Events.php
<?php
namespace AppEmail;
class Events
{
public const UNSPOOL = 'unspool';
}
config/services.yml
services:
AppEmailAmqpHandler:
tags: [messenger.message_handler]
SymfonyBundleSwiftmailerBundleEventListenerEmailSenderListener:
tags:
- name: kernel.event_listener
event: !php/const AppEmailEvents::UNSPOOL
method: onTerminate
your message-queue worker
src/App/Email/AmqpHandler.php
<?php
namespace AppEmail;
use SymfonyComponentEventDispatcherEventDispatcherInterface;
class AmqpHandler
{
/** @var EventDispatcherInterface */
private $eventDispatcher;
/** @var Swift_Mailer */
private $mailer;
public function __construct(EventDispatcherInterface $eventDispatcher, Swift_Mailer $mailer)
{
$this->eventDispatcher = $eventDispatcher;
$this->mailer = $mailer;
}
public function __invoke($emailMessage): void
{
//...
$message = (new Swift_Message($subject))
->setFrom($emailMessage->from)
->setTo($emailMessage->to)
->setBody($emailMessage->body, 'text/html');
$successfulRecipientsCount = $this->mailer->send($message, $failedRecipients);
if ($successfulRecipientsCount < 1 || count($failedRecipients) > 0) {
throw new DeliveryFailureException($message);
}
$this->eventDispatcher->dispatch(Events::UNSPOOL);
}
}
You can read about symfony/messenger here.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…