From 3c5fe51394f02d80440021211a90dd80b41a45c8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 10 Oct 2023 08:18:26 +0200 Subject: [PATCH] [Mime] Forbid messages that are generators to be used more than once --- src/Symfony/Component/Mime/RawMessage.php | 18 ++++++++++ .../Component/Mime/Tests/RawMessageTest.php | 34 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/Symfony/Component/Mime/RawMessage.php b/src/Symfony/Component/Mime/RawMessage.php index aed822beaa7e4..ee3e2ab86f2cb 100644 --- a/src/Symfony/Component/Mime/RawMessage.php +++ b/src/Symfony/Component/Mime/RawMessage.php @@ -19,6 +19,7 @@ class RawMessage { private iterable|string|null $message = null; + private bool $isGeneratorClosed; public function __construct(iterable|string $message) { @@ -41,12 +42,29 @@ public function toString(): string public function toIterable(): iterable { + if ($this->isGeneratorClosed ?? false) { + trigger_deprecation('symfony/mime', '6.4', 'Sending an email with a closed generator is deprecated and will throw in 7.0.'); + // throw new LogicException('Unable to send the email as its generator is already closed.'); + } + if (\is_string($this->message)) { yield $this->message; return; } + if ($this->message instanceof \Generator) { + $message = ''; + foreach ($this->message as $chunk) { + $message .= $chunk; + yield $chunk; + } + $this->isGeneratorClosed = !$this->message->valid(); + $this->message = $message; + + return; + } + foreach ($this->message as $chunk) { yield $chunk; } diff --git a/src/Symfony/Component/Mime/Tests/RawMessageTest.php b/src/Symfony/Component/Mime/Tests/RawMessageTest.php index 6d53ade9ed496..fa802f4710fc5 100644 --- a/src/Symfony/Component/Mime/Tests/RawMessageTest.php +++ b/src/Symfony/Component/Mime/Tests/RawMessageTest.php @@ -12,10 +12,13 @@ namespace Symfony\Component\Mime\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Mime\RawMessage; class RawMessageTest extends TestCase { + use ExpectDeprecationTrait; + /** * @dataProvider provideMessages */ @@ -46,6 +49,37 @@ public function testSerialization(mixed $messageParameter, bool $supportReuse) } } + /** + * @dataProvider provideMessages + */ + public function testToIterable(mixed $messageParameter, bool $supportReuse) + { + $message = new RawMessage($messageParameter); + $this->assertEquals('some string', implode('', iterator_to_array($message->toIterable()))); + + if ($supportReuse) { + // calling methods more than once work + $this->assertEquals('some string', implode('', iterator_to_array($message->toIterable()))); + } + } + + /** + * @dataProvider provideMessages + * + * @group legacy + */ + public function testToIterableLegacy(mixed $messageParameter, bool $supportReuse) + { + $message = new RawMessage($messageParameter); + $this->assertEquals('some string', implode('', iterator_to_array($message->toIterable()))); + + if (!$supportReuse) { + // in 7.0, the test with a generator will throw an exception + $this->expectDeprecation('Since symfony/mime 6.4: Sending an email with a closed generator is deprecated and will throw in 7.0.'); + $this->assertEquals('some string', implode('', iterator_to_array($message->toIterable()))); + } + } + public static function provideMessages(): array { return [