Swiftmailer not sending immediately

你。 提交于 2019-12-31 01:47:13

问题


I have successfully configure my symfony webapp to sending email using SMTP. But all my sending email are being put into the spool directory.

This should only occurs whem there is an error in the sending. Is that correct?

But if I execute the command swiftmailer:spool:send --env=prod, all my emails are sending correctly.

Why my server are not sending the email immediately? Is that because I fixed an error? Is there any way to fix this?

swiftmailer:

spool:
    type: file
    path: %kernel.root_dir%/spool

回答1:


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 Symfony\Bundle\SwiftmailerBundle\EventListener\EmailSenderListener::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 App\Email;

class Events
{
    public const UNSPOOL = 'unspool';
}

config/services.yml

services:    
    App\Email\AmqpHandler:
      tags: [messenger.message_handler]

    Symfony\Bundle\SwiftmailerBundle\EventListener\EmailSenderListener:
        tags:
            - name: kernel.event_listener
              event: !php/const App\Email\Events::UNSPOOL
              method: onTerminate

your message-queue worker src/App/Email/AmqpHandler.php

<?php

namespace App\Email;

use Symfony\Component\EventDispatcher\EventDispatcherInterface;

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.




回答2:


You can force to flush the spool. For example :

$mailer = $this->container->get('mailer');
$mailer->send($message);

$spool = $mailer->getTransport()->getSpool();
$transport = $this->container->get('swiftmailer.transport.real');
if ($spool and $transport) $spool->flushQueue($transport);

Check also your spool configuration in config.yml.

If you have :

swiftmailer:
    ....
    spool:     { type: memory }

mails get sent on the kernel terminate event (so at the end of the page)




回答3:


A just add the command swiftmailer:spool:send into crontab. This step wasn't clear on Symfony documentation.



来源:https://stackoverflow.com/questions/29802225/swiftmailer-not-sending-immediately

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!