Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Mime] useisRendered method to ensure we can avoid rendering an email twice#59596

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

walva
Copy link
Contributor

@walvawalva commentedJan 23, 2025
edited
Loading

QA
Branch?6.4
Bug fix?yes? Not sure
New feature?no
Deprecations?no
Issues
LicenseMIT

Description:

After upgrading my project from Symfony 5.4 to 6.4, due thischange, I encountered an issue where asynchronous email sending failed due to serialization problems withTemplatedEmail. According to theSymfony documentation, when sending an email asynchronously, the email instance must be serializable. While Mailer instances are inherently serializable,TemplatedEmailrequires that its context be serializable. If the context contains non-serializable variables, such as Doctrine entities, it's recommended to either replace them with serializable variables or render the email before calling$mailer->send($email).

To address this, I decorated the SymfonyMailer to force the rendering of emails using theBodyRendererInterface::render(Message $message): void method. However, this approach led to an exception indicating that the context was empty. The method successfully rendered the email, clearing its context, but the sameTemplatedEmailobject was rendered again later in the execution process, specifically in theMessageListener.

To prevent this double rendering, I utilized theTemplatedEmail::isRendered(): bool method, as seen in theAbstractTransport. This ensures that if an email is already rendered, it won't be rendered again, preserving the context and preventing serialization issues.

Solution

The proposed fix involves checking if theTemplatedEmail has already been rendered before attempting to render it again. By using theisRendered() method, we can avoid unnecessary re-rendering, which can lead to empty contexts and serialization problems during asynchronous email sending.

Impact

This correction allows classes extendingTemplatedEmail to be sent asynchronously without encountering errors related to double rendering or context loss due to serialization issues, as outlined in the documentation.

References

Symfony Mailer Documentation
MessageListener Implementation
AbstractTransport Implementation
This pull request aims to enhance the robustness of asynchronous email handling in Symfony by ensuring that TemplatedEmail instances are not rendered multiple times, thereby maintaining their context and serializability.

Original message:

Following up my comment onhttps://github.com/symfony/symfony/pull/47075/files.

I would recommend using the method TemplatedEmail::isRendered() the same way it is used inAbstractTransport.php.

Keeping like this prevents subclass of TemplatedEmail with computed html template to not be rendered twice, such asNotificationEmail.

This change will allow developers to create a subclass of template emails and render them before sending them async, without rendering them twice.

maelanleborgne reacted with thumbs up emoji
@nicolas-grekas
Copy link
Member

Would there be a way to test this?

@walva
Copy link
ContributorAuthor

@nicolas-grekas I need to take a closer look to it.

@OskarStarkOskarStark changed the title[Mime] use isRendered method to ensure we can avoid rendering an email twice[Mime] useisRendered method to ensure we can avoid rendering an email twiceJan 29, 2025
@walvawalvaforce-pushed thefix/cant-render-email-manually branch 4 times, most recently fromc6c75a6 to234c657CompareJanuary 30, 2025 09:17
@walva
Copy link
ContributorAuthor

Hey 👋

I reviewed the existing tests and found that thetestRenderedOnce test already covers the core logic behind this fix. However, I added some additional checks to verify that theisRendered method behaves as expected.

Since the test below is very similar totestRenderedOnce, I feel like adding it might be redundant. However, I can still submit it if you think it adds value. Let me know what you prefer!

publicfunctiontestEmailIsNotRenderedTwice(){$twig =newEnvironment(newArrayLoader(['text' =>'Initial Text','html' =>'<b>Initial HTML</b>',    ]));$renderer =newBodyRenderer($twig);$email =newTemplatedEmail();$email->textTemplate('text');$email->htmlTemplate('html');// First render$renderer->render($email);$this->assertTrue($email->isRendered());$this->assertEquals('Initial Text',$email->getTextBody());$this->assertEquals('<b>Initial HTML</b>',$email->getHtmlBody());// Manually setting the text and HTML content to simulate a previous render$email->text('Manually Set Text');$email->html('Manually Set HTML');// Second render should not override manually set values$renderer->render($email);$this->assertEquals('Manually Set Text',$email->getTextBody());$this->assertEquals('Manually Set HTML',$email->getHtmlBody());}

@walvawalvaforce-pushed thefix/cant-render-email-manually branch from234c657 to2d37c79CompareJanuary 30, 2025 09:53
@nicolas-grekas
Copy link
Member

Thank you@walva.

walva reacted with thumbs up emoji

@nicolas-grekasnicolas-grekas merged commit0beb17a intosymfony:6.4Feb 4, 2025
9 of 11 checks passed
@walvawalva deleted the fix/cant-render-email-manually branchFebruary 10, 2025 07:38
This was referencedFeb 26, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers
No reviews
Assignees
No one assigned
Projects
None yet
Milestone
6.4
Development

Successfully merging this pull request may close these issues.

3 participants
@walva@nicolas-grekas@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp