Skip to content

[Mailer] Sending Messages Async with json serializer does not work #33394

Open
@TheRatG

Description

@TheRatG

Symfony version(s) affected: symfony/mailer: 4.3.4

Description
Sending Messages Async with json serializer does not work with SendEmailMessage.

Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException : Cannot create an instance of Symfony\Component\Mime\RawMessage from serialized data because its constructor requires parameter "message" to be present.
/home/vagrant/www/fxbackoffice.local/vendor/symfony/serializer/Normalizer/AbstractNormalizer.php:505
 ...

How to reproduce

framework:
    messenger:
        serializer:
            default_serializer: messenger.transport.symfony_serializer
            symfony_serializer:
                format: json
        transports:
            async: "%env(MESSENGER_TRANSPORT_DSN)%"

        routing:
            'Symfony\Component\Mailer\Messenger\SendEmailMessage':  async

Activity

changed the title [-][Mailer] [/-] [+][Mailer] Sending Messages Async with json serializer does not work[/+] on Aug 30, 2019
danielchodusov

danielchodusov commented on Sep 13, 2019

@danielchodusov

Iam having the same issue. Sending message async doesn't work. On serialization I recive " A message must have a text or an HTML part or attachments."

mlojewski

mlojewski commented on Nov 7, 2019

@mlojewski

Check if your symfony/twig-bundle is in 4.3 version - helped for me

Mrkisha

Mrkisha commented on Dec 13, 2019

@Mrkisha

Having exact same problem, and have symfony/twig-bundle:4.4.

xabbuh

xabbuh commented on Dec 14, 2019

@xabbuh
Member

Can any of you create a small example application that allows to reproduce the issue?

diabl0

diabl0 commented on Dec 20, 2019

@diabl0

Sample app showing error: https://github.com/diabl0/async-mailer

Nyholm

Nyholm commented on Jan 26, 2020

@Nyholm
Member

I can confirm this issue.

It happens because we cannot normalize RawMessage from Mime component. It has a constructor with required arguments.

We need to use a serializer with the PropertyNormalizer normalizer, then everything will be fine. Im not sure why PropertyNormalizer is not configured by default though...

wtorsi

wtorsi commented on Jan 28, 2020

@wtorsi

Actually, i've already written about this bug to fabpot, about 6 months ago i hope, but I can't find it now, so i can't say what he said about this problem.
In my app I'm using Mailer in another already async handler.

For quick fix, my decision was to create custom Mailer (thx to container), to exclude redundant de/normalization.

#services/mailer.yaml
services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false

    Mailer\Mailer: ~
    Symfony\Component\Mailer\MailerInterface: '@Mailer\Mailer'

# Mailer/Mailer.php
<?php

namespace Mailer;

use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Mime\RawMessage;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

class Mailer implements MailerInterface
{
    private TransportInterface $transport;

    public function __construct(TransportInterface $transport)
    {
        $this->transport = $transport;
    }

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


32 remaining items

mabumusa1

mabumusa1 commented on Apr 5, 2022

@mabumusa1

@florentdestremau I support your change, we need to use JSON instead of php-serialization

mabumusa1

mabumusa1 commented on May 31, 2022

@mabumusa1

@florentdestremau please make a PR, I will review it and hopefully, we can get it merged. This is important feature

florentdestremau

florentdestremau commented on May 31, 2022

@florentdestremau
Contributor

I have no idea what is needed so unless a contributor is willing to point out the direction, this isn't going anywhere for now

RCheesley

RCheesley commented on Jul 21, 2022

@RCheesley

@Nyholm is there any chance of getting some guidance on this issue? It's blocking a pretty major PR we need to integrate in our next major release of Mautic to switch from Swiftmailer to Symfony Mailer but folks don't seem to be clear on how to proceed.

fabpot

fabpot commented on Jul 27, 2022

@fabpot
Member

IIUC, there is no issue to fix in Symfony Mailer, but it's more about the inability to serialize an email to JSON via the Symfony serializer.

Wirone

Wirone commented on Jul 27, 2022

@Wirone
Contributor

@fabpot I don't know if you're familiar with my comment but IMHO there was architectural issue in Mailer/Mime component. I said "was" because I don't use Messenger/Mailer currently and I don't know state of the codebase. But looking at SendEmailMessage at 6.2 it looks like issue remains.

kor3k

kor3k commented on Jan 12, 2023

@kor3k
Contributor

what about widening SendEmailMessage::$message and SendEmailMessage::__construct($message) type to RawMessage|Email ? would that suffice for serializer to handle it properly?

kor3k

kor3k commented on Jan 12, 2023

@kor3k
Contributor

@fabpot please, could you explain why is it designed this way ( #33394 (comment) ) ? 🙏
as you are the author of these classes/logic.
understanding it will be a good start to wrap around this issue.
notably

  • the inheritance RawMessage -> Message -> Email
  • most (all?) consumer methods are typed to RawMessage
  • Email is a child class of RawMessage but totally overrides its constructor
  • RawMessage is mainly used for types in signatures

seems to me that RawMessage is kinda substitute for an interface.

macghriogair

macghriogair commented on Oct 31, 2024

@macghriogair

Any update on this one?
It seems kind of counter intuitive, having to configure an extra transport (which includes a separate failure transport, too) with native PHP Serializer, while all other transports are working with JSON.
On the other hand, when using SendEmailMessage, you are probably consuming the Mail with Symfony itself.
Don't get me wrong, just wondering if this issue is a won't fix or needs support :)

Cafeine42

Cafeine42 commented on May 19, 2025

@Cafeine42

As rapid fix, I reused the Normalizer provided by @TheRatG (many thanks to them!) to work around this issue. I added a AutoconfigureTag to enable it faster. Tested on Sf 7.4.

namespace App\Serializer;

use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\Mailer\Messenger\SendEmailMessage;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

#[AutoconfigureTag('serializer.normalizer', ['priority' => 500])]
class SendEmailMessageDenormalizer implements NormalizerInterface, DenormalizerInterface
{
    public function supportsNormalization($data, $format = null, array $context = []): bool
    {
        return $data instanceof SendEmailMessage && $format === 'json';
    }

    public function normalize($data, $format = null, array $context = []): float|int|bool|\ArrayObject|array|string|null
    { return [__CLASS__ => addslashes(serialize($data))];
    }

    public function supportsDenormalization($data, $type, $format = null, array $context = []): bool
    {
        return $type == SendEmailMessage::class && $format === 'json' && isset($data[__CLASS__]);
    }

    public function denormalize($data, $type, $format = null, array $context = []): mixed
    {
        return unserialize(stripslashes($data[__CLASS__]));
    }

    public function getSupportedTypes(?string $format): array
    {
        return [SendEmailMessage::class => true];
    }
}

What would be the best long-term solution here?

Should we consider revisiting the RawMessage class so it can be natively supported by the Symfony serializer? That could imply deprecating it in its current form and introducing a new class that would be fully supported wherever RawMessage is currently used.

Alternatively, could introducing a few interfaces help make things more flexible and extensible?

Or would it make more sense to simply include this Normalizer directly in the Mail component?

I'd love to hear your thoughts on the most sustainable path forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @fabpot@weaverryan@sebo@stof@Wirone

        Issue actions

          [Mailer] Sending Messages Async with json serializer does not work · Issue #33394 · symfony/symfony