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 f77b3ad4b5337..1f248d76d24ab 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 @@ -124,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 233afc075a7bc..90932686190de 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 ?? $this->textEncoding; return $this; } @@ -293,12 +296,27 @@ public function getTextCharset(): ?string return $this->textCharset; } + public function getTextEncoding(): ?string + { + return $this->textEncoding; + } + + /** + * @return $this + */ + public function textEncoding(?string $encoding = null): static + { + $this->textEncoding = $encoding; + + return $this; + } + /** * @param resource|string|null $body * * @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 +325,7 @@ public function html($body, string $charset = 'utf-8'): static $this->cachedBody = null; $this->html = $body; $this->htmlCharset = $charset; + $this->htmlEncoding = $encoding ?? $this->htmlEncoding; return $this; } @@ -324,6 +343,21 @@ public function getHtmlCharset(): ?string return $this->htmlCharset; } + public function getHtmlEncoding(): ?string + { + return $this->htmlEncoding; + } + + /** + * @return $this + */ + public function htmlEncoding(?string $encoding = null): static + { + $this->htmlEncoding = $encoding; + + return $this; + } + /** * @param resource|string $body * @@ -436,7 +470,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 +537,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 +595,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 +603,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..023c7d6eed36a 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", @@ -695,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->textEncoding('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()); + } }