Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Mailer] No default sender possible with sf messenger+ sf serializer #37414

Closed
@j-schumann

Description

@j-schumann

Symfony version(s) affected: 5.1, 5.2

Description
A MessageListener cannot be used to add a FROM header when the symfony/mailer is used together with symfony/messenger and symfony/serializer, a LogicException is thrown: An email must have a "From" or a "Sender" header.

How to reproduce
I'm sorry, at the moment I have no reproduce code.

  • create symfony project with messenger, mailer and serializer
  • create a custom event listener for the MessageEvent like the documentation suggests: "Instead of calling ->from() every time you create a new email, you can create an event subscriber and listen to the MessageEvent event to set the same From email to all messages."
framework:
    mailer:
        dsn: '%env(MAILER_DSN)%'
        headers:
            from: '[email protected]'
  • configure the messenger to use the the symfony/serializer:
        serializer:
            default_serializer: 'messenger.transport.symfony_serializer'
  • try to send an email without a sender address, relying on the listener to add it.

Result: exception with 'An email must have a "From" or a "Sender" header.'

Possible Solution
Do not clone $message for the event in https://github.com/symfony/mailer/blob/master/Mailer.php#L48 to allow listeners to modify the message before serialization, they can check isQueued to prevent duplicate modification.

Or, probably not that easy: Don't trigger ensureValidity() when the serializer calls getBody() on Symfony\Component\Mime\Email

Additional context
relevant part of the trace:

#0  Symfony\Component\Mime\Message->ensureValidity() called at [/var/www/html/vendor/symfony/mime/Email.php:408]
#1  Symfony\Component\Mime\Email->ensureValidity() called at [/var/www/html/vendor/symfony/mime/Email.php:433]
#2  Symfony\Component\Mime\Email->generateBody() called at [/var/www/html/vendor/symfony/mime/Email.php:399]
#3  Symfony\Component\Mime\Email->getBody() called at [/var/www/html/vendor/symfony/property-access/PropertyAccessor.php:405]
#4  Symfony\Component\PropertyAccess\PropertyAccessor->readProperty() called at [/var/www/html/vendor/symfony/property-access/PropertyAccessor.php:100]
#5  Symfony\Component\PropertyAccess\PropertyAccessor->getValue() called at [/var/www/html/vendor/symfony/serializer/Normalizer/ObjectNormalizer.php:142]
#6  Symfony\Component\Serializer\Normalizer\ObjectNormalizer->getAttributeValue() called at [/var/www/html/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:176]
#7  Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->normalize() called at [/var/www/html/vendor/symfony/serializer/Serializer.php:154]
#8  Symfony\Component\Serializer\Serializer->normalize() called at [/var/www/html/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:201]
#9  Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->normalize() called at [/var/www/html/vendor/symfony/serializer/Serializer.php:154]
#10 Symfony\Component\Serializer\Serializer->normalize() called at [/var/www/html/vendor/symfony/serializer/Serializer.php:127]
#11 Symfony\Component\Serializer\Serializer->serialize() called at [/var/www/html/vendor/symfony/messenger/Transport/Serialization/Serializer.php:105]
#12 Symfony\Component\Messenger\Transport\Serialization\Serializer->encode() called at [/var/www/html/vendor/symfony/amqp-messenger/Transport/AmqpSender.php:42]
#13 Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpSender->send() called at [/var/www/html/vendor/symfony/amqp-messenger/Transport/AmqpTransport.php:66]
#14 Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransport->send() called at [/var/www/html/vendor/symfony/messenger/Middleware/SendMessageMiddleware.php:69]
#15 Symfony\Component\Messenger\Middleware\SendMessageMiddleware->handle() called at [/var/www/html/vendor/symfony/messenger/Middleware/FailedMessageProcessingMiddleware.php:34]
#16 Symfony\Component\Messenger\Middleware\FailedMessageProcessingMiddleware->handle() called at [/var/www/html/vendor/symfony/messenger/Middleware/DispatchAfterCurrentBusMiddleware.php:67]
#17 Symfony\Component\Messenger\Middleware\DispatchAfterCurrentBusMiddleware->handle() called at [/var/www/html/vendor/symfony/messenger/Middleware/RejectRedeliveredMessageMiddleware.php:48]
#18 Symfony\Component\Messenger\Middleware\RejectRedeliveredMessageMiddleware->handle() called at [/var/www/html/vendor/symfony/messenger/Middleware/AddBusNameStampMiddleware.php:37]
#19 Symfony\Component\Messenger\Middleware\AddBusNameStampMiddleware->handle() called at [/var/www/html/vendor/symfony/messenger/Middleware/TraceableMiddleware.php:43]
#20 Symfony\Component\Messenger\Middleware\TraceableMiddleware->handle() called at [/var/www/html/vendor/symfony/messenger/MessageBus.php:80]
#21 Symfony\Component\Messenger\MessageBus->dispatch() called at [/var/www/html/vendor/symfony/mailer/Mailer.php:54]

The normal flow in working cases is:

  • no messenger
    • the mailer directly calls the transport which dispatches the MessageEvent, the listener adds the FROM header -> everything working
  • messenger with the default serializer

The problem occurs when the symfony serializer is used, which triggers the ensureValidity() method when the message is sent to the bus (see trace).
Because the listeners only receive a cloned message they cannot modify the real mail message object and thus cannot add a sender address.

This also effects PR #36736: The config options to set a default sender will not work because the mentioned exception is thrown because the included Symfony\Component\Mailer\EventListener\MessageListener will not be able to set headers because of the clone().

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions