MailBeforeValidateEvent in Shopware6

54 Views Asked by At

I'm currently working with the MailBeforeValidateEvent in Shopware and I'd like to know if this event is triggered before emails are sent to the queue. I couldn't find detailed information in the documentation, and I'm hoping someone with experience in this area could clarify.

1

There are 1 best solutions below

0
Marcus On BEST ANSWER

Assuming you are using the newest Shopware 6 version (currently: v6.5.6.1) in a default configuration:

The MailBeforeValidateEvent is dispatched at the start of Shopware\Core\Content\Mail\Service\MailService::send():

/**
 * @param mixed[] $data
 * @param mixed[] $templateData
 */
public function send(array $data, Context $context, array $templateData = []): ?Email
{
    $event = new MailBeforeValidateEvent($data, $context, $templateData);
    $this->eventDispatcher->dispatch($event);
    /* ... */

Then — towards the end of the same function — the mail is sent:

    /* ... */
    $this->mailSender->send($mail);

    $event = new MailSentEvent($data['subject'], $recipients, $contents, $context, $templateData['eventName'] ?? null);
    $this->eventDispatcher->dispatch($event);

    return $mail;
}

Which leads to Shopware\Core\Content\Mail\Service\MailSender::send() which calls Symfony\Component\Mailer\Mailer::send(), inside the Symfony\Component\Mailer\Messenger\SendEmailMessage is dispatched:

public function send(RawMessage $message, Envelope $envelope = null): void
{
    if (null === $this->bus) {
        $this->transport->send($message, $envelope);

        return;
    }

    $stamps = [];
    if (null !== $this->dispatcher) {
        // The dispatched event here has `queued` set to `true`; the goal is NOT to render the message, but to let
        // listeners do something before a message is sent to the queue.
        // We are using a cloned message as we still want to dispatch the **original** message, not the one modified by listeners.
        // That's because the listeners will run again when the email is sent via Messenger by the transport (see `AbstractTransport`).
        // Listeners should act depending on the `$queued` argument of the `MessageEvent` instance.
        $clonedMessage = clone $message;
        $clonedEnvelope = null !== $envelope ? clone $envelope : Envelope::create($clonedMessage);
        $event = new MessageEvent($clonedMessage, $clonedEnvelope, (string) $this->transport, true);
        $this->dispatcher->dispatch($event);
        $stamps = $event->getStamps();

        if ($event->isRejected()) {
            return;
        }
    }

    try {
        $this->bus->dispatch(new SendEmailMessage($message, $envelope), $stamps);
    } catch (HandlerFailedException $e) {
        foreach ($e->getNestedExceptions() as $nested) {
            if ($nested instanceof TransportExceptionInterface) {
                throw $nested;
            }
        }
        throw $e;
    }
}

It gets handled by the Symfony\Component\Mailer\Messenger\MessageHandler, which calls the configured mail transport (sendmail, etc.).

So MailBeforeValidateEvent is triggered before the email is sent to the queue.