From 75b8c663d393f0dcda12cb2ea024657f77850fb6 Mon Sep 17 00:00:00 2001 From: Kumulo Date: Thu, 7 Mar 2024 18:43:02 +0100 Subject: [PATCH 1/4] [Mime][Email] Add encoders to text and html parts --- .../Twig/Tests/Mime/TemplatedEmailTest.php | 2 ++ src/Symfony/Component/Mime/Email.php | 16 ++++++++++------ src/Symfony/Component/Mime/Tests/EmailTest.php | 2 ++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php b/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php index f77b3ad4b5337..8f151856cfc07 100644 --- a/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php @@ -75,8 +75,10 @@ public function testSymfonySerialize() }, "text": null, "textCharset": null, + "textEncoding": null, "html": null, "htmlCharset": null, + "htmlEncoding": null, "attachments": [ {%A "body": "Some Text file",%A diff --git a/src/Symfony/Component/Mime/Email.php b/src/Symfony/Component/Mime/Email.php index 233afc075a7bc..977ac86329a34 100644 --- a/src/Symfony/Component/Mime/Email.php +++ b/src/Symfony/Component/Mime/Email.php @@ -45,6 +45,7 @@ class Email extends Message private $text; private ?string $textCharset = null; + private ?string $textEncoding = null; /** * @var resource|string|null @@ -52,6 +53,7 @@ class Email extends Message private $html; private ?string $htmlCharset = null; + private ?string $htmlEncoding = null; private array $attachments = []; private ?AbstractPart $cachedBody = null; // Used to avoid wrong body hash in DKIM signatures with multiple parts (e.g. HTML + TEXT) due to multiple boundaries. @@ -267,7 +269,7 @@ public function getPriority(): int * * @return $this */ - public function text($body, string $charset = 'utf-8'): static + public function text($body, string $charset = 'utf-8', ?string $encoding = null): static { if (null !== $body && !\is_string($body) && !\is_resource($body)) { throw new \TypeError(sprintf('The body must be a string, a resource or null (got "%s").', get_debug_type($body))); @@ -276,6 +278,7 @@ public function text($body, string $charset = 'utf-8'): static $this->cachedBody = null; $this->text = $body; $this->textCharset = $charset; + $this->textEncoding = $encoding; return $this; } @@ -298,7 +301,7 @@ public function getTextCharset(): ?string * * @return $this */ - public function html($body, string $charset = 'utf-8'): static + public function html($body, string $charset = 'utf-8', ?string $encoding = null): static { if (null !== $body && !\is_string($body) && !\is_resource($body)) { throw new \TypeError(sprintf('The body must be a string, a resource or null (got "%s").', get_debug_type($body))); @@ -307,6 +310,7 @@ public function html($body, string $charset = 'utf-8'): static $this->cachedBody = null; $this->html = $body; $this->htmlCharset = $charset; + $this->htmlEncoding = $encoding; return $this; } @@ -436,7 +440,7 @@ private function generateBody(): AbstractPart [$htmlPart, $otherParts, $relatedParts] = $this->prepareParts(); - $part = null === $this->text ? null : new TextPart($this->text, $this->textCharset); + $part = null === $this->text ? null : new TextPart($this->text, $this->textCharset, 'plain', $this->textEncoding); if (null !== $htmlPart) { if (null !== $part) { $part = new AlternativePart($part, $htmlPart); @@ -503,7 +507,7 @@ private function prepareParts(): ?array $otherParts[] = $part; } if (null !== $htmlPart) { - $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); + $htmlPart = new TextPart($html, $this->htmlCharset, 'html', $this->htmlEncoding); } return [$htmlPart, $otherParts, array_values($relatedParts)]; @@ -561,7 +565,7 @@ public function __serialize(): array $this->html = (new TextPart($this->html))->getBody(); } - return [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, parent::__serialize()]; + return [$this->text, $this->textCharset, $this->textEncoding, $this->html, $this->htmlCharset, $this->htmlEncoding, $this->attachments, parent::__serialize()]; } /** @@ -569,7 +573,7 @@ public function __serialize(): array */ public function __unserialize(array $data): void { - [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, $parentData] = $data; + [$this->text, $this->textCharset, $this->textEncoding, $this->html, $this->htmlCharset, $this->htmlEncoding, $this->attachments, $parentData] = $data; parent::__unserialize($parentData); } diff --git a/src/Symfony/Component/Mime/Tests/EmailTest.php b/src/Symfony/Component/Mime/Tests/EmailTest.php index ae61f26f605b4..5964882733250 100644 --- a/src/Symfony/Component/Mime/Tests/EmailTest.php +++ b/src/Symfony/Component/Mime/Tests/EmailTest.php @@ -532,8 +532,10 @@ public function testSymfonySerialize() { "text": "Text content", "textCharset": "utf-8", + "textEncoding": null, "html": "HTML content", "htmlCharset": "utf-8", + "htmlEncoding": null, "attachments": [ { "filename": "test.txt", From dce774e9a6cb692c261054b2d2580d41d93bc5a6 Mon Sep 17 00:00:00 2001 From: Kumulo Date: Fri, 8 Mar 2024 01:05:41 +0100 Subject: [PATCH 2/4] [Bridge] [Twig] Add encoders for Mime TemplatedEmail --- src/Symfony/Bridge/Twig/Mime/BodyRenderer.php | 2 +- .../Twig/Tests/Mime/TemplatedEmailTest.php | 13 ++++++ src/Symfony/Component/Mime/Email.php | 36 ++++++++++++++- .../Component/Mime/Tests/EmailTest.php | 44 +++++++++++++++++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php b/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php index d5b6d14c139a0..d4e9c203e811f 100644 --- a/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php +++ b/src/Symfony/Bridge/Twig/Mime/BodyRenderer.php @@ -74,7 +74,7 @@ public function render(Message $message): void // if text body is empty, compute one from the HTML body if (!$message->getTextBody() && null !== $html = $message->getHtmlBody()) { $text = $this->converter->convert(\is_resource($html) ? stream_get_contents($html) : $html, $message->getHtmlCharset()); - $message->text($text, $message->getHtmlCharset()); + $message->text($text, $message->getHtmlCharset(), $message->getHtmlEncoding()); } }; diff --git a/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php b/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php index 8f151856cfc07..1f248d76d24ab 100644 --- a/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Mime/TemplatedEmailTest.php @@ -126,4 +126,17 @@ public function testSymfonySerialize() $this->assertEquals($expected->getHeaders(), $n->getHeaders()); $this->assertEquals($expected->getBody(), $n->getBody()); } + + public function testHtmlEncoding() + { + $email = new TemplatedEmail(); + + $email + ->htmlTemplate('text.html.twig') + ->context(['a' => 'b']); + $this->assertNull($email->getHtmlEncoding()); + + $email->htmlEncoding('base64'); + $this->assertSame('base64', $email->getHtmlEncoding()); + } } diff --git a/src/Symfony/Component/Mime/Email.php b/src/Symfony/Component/Mime/Email.php index 977ac86329a34..f675d4e4fc1f2 100644 --- a/src/Symfony/Component/Mime/Email.php +++ b/src/Symfony/Component/Mime/Email.php @@ -278,7 +278,7 @@ public function text($body, string $charset = 'utf-8', ?string $encoding = null) $this->cachedBody = null; $this->text = $body; $this->textCharset = $charset; - $this->textEncoding = $encoding; + $this->textEncoding = $encoding ?? $this->textEncoding; return $this; } @@ -296,6 +296,22 @@ public function getTextCharset(): ?string return $this->textCharset; } + public function getTextEncoding(): ?string + { + return $this->textEncoding; + } + + /** + * @param string|null $encoding + * + * @return $this + */ + public function textEncoding(?string $encoding = null): static + { + $this->textEncoding = $encoding; + return $this; + } + /** * @param resource|string|null $body * @@ -310,7 +326,7 @@ public function html($body, string $charset = 'utf-8', ?string $encoding = null) $this->cachedBody = null; $this->html = $body; $this->htmlCharset = $charset; - $this->htmlEncoding = $encoding; + $this->htmlEncoding = $encoding ?? $this->htmlEncoding; return $this; } @@ -328,6 +344,22 @@ public function getHtmlCharset(): ?string return $this->htmlCharset; } + public function getHtmlEncoding(): ?string + { + return $this->htmlEncoding; + } + + /** + * @param string|null $encoding + * + * @return $this + */ + public function htmlEncoding(?string $encoding = null): static + { + $this->htmlEncoding = $encoding; + return $this; + } + /** * @param resource|string $body * diff --git a/src/Symfony/Component/Mime/Tests/EmailTest.php b/src/Symfony/Component/Mime/Tests/EmailTest.php index 5964882733250..ec15ed2f2ce50 100644 --- a/src/Symfony/Component/Mime/Tests/EmailTest.php +++ b/src/Symfony/Component/Mime/Tests/EmailTest.php @@ -697,4 +697,48 @@ public function testEmailsWithAttachmentsWhichAreAFileInstanceCanBeUnserialized( $this->assertCount(1, $attachments); $this->assertStringContainsString('foo_bar_xyz_123', $attachments[0]->getBody()); } + + public function testTextEncoding() + { + $email = new Email(); + + $email->text('foo'); + $this->assertNull($email->getTextEncoding()); + + $email->textEncoding('base64'); + $this->assertSame('base64', $email->getTextEncoding()); + + $email->textEncoding(null); + $this->assertNull($email->getTextEncoding()); + + $email->text('foo', 'utf-8', 'base64'); + $this->assertSame('base64', $email->getTextEncoding()); + + $email = new Email(); + $email->assertNull('base64'); + $email->text('foo'); + $this->assertSame('base64', $email->getTextEncoding()); + } + + public function testHtmlEncoding() + { + $email = new Email(); + + $email->html('foo'); + $this->assertNull($email->getHtmlEncoding()); + + $email->htmlEncoding('base64'); + $this->assertSame('base64', $email->getHtmlEncoding()); + + $email->htmlEncoding(null); + $this->assertNull($email->getHtmlEncoding()); + + $email->html('foo', 'utf-8', 'base64'); + $this->assertSame('base64', $email->getHtmlEncoding()); + + $email = new Email(); + $email->htmlEncoding('base64'); + $email->html('foo'); + $this->assertSame('base64', $email->getHtmlEncoding()); + } } From 436429aefbc9a082a34e805b6b9dfe49afa05318 Mon Sep 17 00:00:00 2001 From: Kumulo Date: Fri, 8 Mar 2024 01:09:10 +0100 Subject: [PATCH 3/4] Update Email with coding standard --- src/Symfony/Component/Mime/Email.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Mime/Email.php b/src/Symfony/Component/Mime/Email.php index f675d4e4fc1f2..90932686190de 100644 --- a/src/Symfony/Component/Mime/Email.php +++ b/src/Symfony/Component/Mime/Email.php @@ -302,13 +302,12 @@ public function getTextEncoding(): ?string } /** - * @param string|null $encoding - * * @return $this */ public function textEncoding(?string $encoding = null): static { $this->textEncoding = $encoding; + return $this; } @@ -350,13 +349,12 @@ public function getHtmlEncoding(): ?string } /** - * @param string|null $encoding - * * @return $this */ public function htmlEncoding(?string $encoding = null): static { $this->htmlEncoding = $encoding; + return $this; } From db1959827a9afa2d33752a459a5c07b667050fef Mon Sep 17 00:00:00 2001 From: Kumulo Date: Fri, 8 Mar 2024 01:15:24 +0100 Subject: [PATCH 4/4] Fix Email unit test --- src/Symfony/Component/Mime/Tests/EmailTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Mime/Tests/EmailTest.php b/src/Symfony/Component/Mime/Tests/EmailTest.php index ec15ed2f2ce50..023c7d6eed36a 100644 --- a/src/Symfony/Component/Mime/Tests/EmailTest.php +++ b/src/Symfony/Component/Mime/Tests/EmailTest.php @@ -715,7 +715,7 @@ public function testTextEncoding() $this->assertSame('base64', $email->getTextEncoding()); $email = new Email(); - $email->assertNull('base64'); + $email->textEncoding('base64'); $email->text('foo'); $this->assertSame('base64', $email->getTextEncoding()); }