symfony/mailerの非同期送信処理
symfonyでは少なくとも5.4以降では、symfiny/mailerでもメール送信の非同期処理がデフォルトで有効になっている。
以下はSending Emails with MailerのSending Messages Asyncの翻訳。
Sending Messages Async
[$mailer->send($email)] を呼び出すと、電子メールはすぐにトランスポートに送信されます。パフォーマンスを向上させるために、Messengerを利用して、後でMessengerトランスポート経由でメッセージを送信できます。
Messenger のドキュメントに従って、トランスポートを構成することから始めます。すべての設定が完了したら、[$mailer->send()] を呼び出すと、SendEmailMessage メッセージがデフォルトのメッセージ バス ([messenger.default_bus]) を介してディスパッチされます。 [async] というトランスポートがあると仮定すると、そこにメッセージをルーティングできます。
# config/packages/messenger.yaml
framework:
messenger:
transports:
async: "%env(MESSENGER_TRANSPORT_DSN)%"
routing:
'Symfony\Component\Mailer\Messenger\SendEmailMessage': async
これにより、メッセージはすぐに配信されるのではなく、後で処理されるようにトランスポートに送信されます (Messenger: Sync & Queued Message Handling を参照してください)。メールの「レンダリング」(計算されたヘッダー、本文のレンダリングなど) も延期され、Messenger ハンドラーによってメールが送信される直前にのみ行われることに注意してください。
非同期の無効化
[message_bus] オプションを使用して、メッセージのディスパッチに使用するバスを構成できます。これを [false] に設定して、Mailer トランスポートを直接呼び出し、非同期配信を無効にすることもできます。
# config/packages/mailer.yaml
framework:
mailer:
message_bus: app.another_bus #falseにすると同期的に直接実行される。
TemplatedEmailによる事前レンダリング(6.2以降)
[$mailer->send($email)] を呼び出す前に電子メールをレンダリングする次の例は、Symfony 6.2 で機能します。
電子メールを非同期で送信する場合、そのインスタンスはシリアライズ可能である必要があります。これは Email インスタンスの場合は常に当てはまりますが、TemplatedEmail を送信するときは、[context] がシリアライズ可能であることを確認する必要があります。 Doctrine エンティティのようにシリアル化できない変数がある場合は、それらをより具体的な変数に置き換えるか、[$mailer->send($email)] を呼び出す前にメールをレンダリングします。
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\BodyRendererInterface;
public function action(MailerInterface $mailer, BodyRendererInterface $bodyRenderer)
{
$email = (new TemplatedEmail())
->htmlTemplate($template)
->context($context)
;
$bodyRenderer->render($email);
$mailer->send($email);
}
以上がsymfony/mailerの翻訳の内容。この非同期実行がデフォルトで有効なせいで、なぜ送信されないのか悩みまくった。