From e885860edc4a78f561dc546b6a8975575df5bf1c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 16 Apr 2020 16:21:43 +0200 Subject: [PATCH] Fix From/Sender handling in Emails --- .../Mailer/EventListener/EnvelopeListener.php | 8 ++++++ .../Mailer/Transport/AbstractTransport.php | 4 --- src/Symfony/Component/Mime/Message.php | 15 ++++++++--- .../Mime/Tests/Crypto/SMimeSignerTest.php | 4 ++- .../Component/Mime/Tests/EmailTest.php | 27 ++++++++++--------- .../Mime/Tests/MessageConverterTest.php | 2 +- .../Mime/Tests/Part/MessagePartTest.php | 2 +- 7 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/Symfony/Component/Mailer/EventListener/EnvelopeListener.php b/src/Symfony/Component/Mailer/EventListener/EnvelopeListener.php index cbb3922a19a4..570a9e39551f 100644 --- a/src/Symfony/Component/Mailer/EventListener/EnvelopeListener.php +++ b/src/Symfony/Component/Mailer/EventListener/EnvelopeListener.php @@ -14,6 +14,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Message; /** * Manipulates the Envelope of a Message. @@ -43,6 +44,13 @@ public function onMessage(MessageEvent $event): void { if ($this->sender) { $event->getEnvelope()->setSender($this->sender); + + $message = $event->getMessage(); + if ($message instanceof Message) { + if (!$message->getHeaders()->has('Sender') && !$message->getHeaders()->has('From')) { + $message->getHeaders()->addMailboxHeader('Sender', $this->sender->getAddress()); + } + } } if ($this->recipients) { diff --git a/src/Symfony/Component/Mailer/Transport/AbstractTransport.php b/src/Symfony/Component/Mailer/Transport/AbstractTransport.php index 1bc3fa12a561..33f75fb3faa4 100644 --- a/src/Symfony/Component/Mailer/Transport/AbstractTransport.php +++ b/src/Symfony/Component/Mailer/Transport/AbstractTransport.php @@ -63,10 +63,6 @@ public function send(RawMessage $message, Envelope $envelope = null): ?SentMessa $envelope = $event->getEnvelope(); } - if (!$envelope->getRecipients()) { - return null; - } - $message = new SentMessage($message, $envelope); $this->doSend($message); diff --git a/src/Symfony/Component/Mime/Message.php b/src/Symfony/Component/Mime/Message.php index 5b4e67f1dbc5..94a49764e491 100644 --- a/src/Symfony/Component/Mime/Message.php +++ b/src/Symfony/Component/Mime/Message.php @@ -74,7 +74,10 @@ public function getPreparedHeaders(): Headers $headers = clone $this->headers; if (!$headers->has('From')) { - throw new LogicException('An email must have a "From" header.'); + if (!$headers->has('Sender')) { + throw new LogicException('An email must have a "From" or a "Sender" header.'); + } + $headers->addMailboxListHeader('From', [$headers->get('Sender')->getAddress()]); } $headers->addTextHeader('MIME-Version', '1.0'); @@ -119,8 +122,12 @@ public function toIterable(): iterable public function ensureValidity() { - if (!$this->headers->has('From')) { - throw new LogicException('An email must have a "From" header.'); + if (!$this->headers->has('To')) { + throw new LogicException('An email must have a "To" header.'); + } + + if (!$this->headers->has('From') && !$this->headers->has('Sender')) { + throw new LogicException('An email must have a "From" or a "Sender" header.'); } parent::ensureValidity(); @@ -133,7 +140,7 @@ public function generateMessageId(): string } elseif ($this->headers->has('From')) { $sender = $this->headers->get('From')->getAddresses()[0]; } else { - throw new LogicException('An email must have a "From" or a "Sender" header to compute a Messsage ID.'); + throw new LogicException('An email must have a "From" or a "Sender" header.'); } return bin2hex(random_bytes(16)).strstr($sender->getAddress(), '@'); diff --git a/src/Symfony/Component/Mime/Tests/Crypto/SMimeSignerTest.php b/src/Symfony/Component/Mime/Tests/Crypto/SMimeSignerTest.php index 0a86c3c90e1e..5522bc6f55cd 100644 --- a/src/Symfony/Component/Mime/Tests/Crypto/SMimeSignerTest.php +++ b/src/Symfony/Component/Mime/Tests/Crypto/SMimeSignerTest.php @@ -99,6 +99,7 @@ public function testSignedMessageWithBcc() { $message = (new Email()) ->date(new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->to('fabien@symfony.com') ->addBcc('fabien@symfony.com', 's.stok@rollerscapes.net') ->subject('I am your sign of fear') ->from('noreply@example.com') @@ -115,8 +116,9 @@ public function testSignedMessageWithAttachments() $message = new Email((new Headers()) ->addDateHeader('Date', new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) ->addMailboxListHeader('From', ['fabien@symfony.com']) + ->addMailboxListHeader('To', ['fabien@symfony.com']) ); - $message->html($content = 'html content '); + $message->html('html content '); $message->text('text content'); $message->attach(fopen(__DIR__.'/../Fixtures/mimetypes/test', 'r')); $message->attach(fopen(__DIR__.'/../Fixtures/mimetypes/test.gif', 'r'), 'test.gif'); diff --git a/src/Symfony/Component/Mime/Tests/EmailTest.php b/src/Symfony/Component/Mime/Tests/EmailTest.php index bfd30053af09..230df0791e15 100644 --- a/src/Symfony/Component/Mime/Tests/EmailTest.php +++ b/src/Symfony/Component/Mime/Tests/EmailTest.php @@ -251,62 +251,62 @@ public function testGenerateBody() $att = new DataPart($file = fopen(__DIR__.'/Fixtures/mimetypes/test', 'r')); $img = new DataPart($image = fopen(__DIR__.'/Fixtures/mimetypes/test.gif', 'r'), 'test.gif'); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->text('text content'); $this->assertEquals($text, $e->getBody()); $this->assertEquals('text content', $e->getTextBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->html('html content'); $this->assertEquals($html, $e->getBody()); $this->assertEquals('html content', $e->getHtmlBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->html('html content'); $e->text('text content'); $this->assertEquals(new AlternativePart($text, $html), $e->getBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->html('html content', 'iso-8859-1'); $e->text('text content', 'iso-8859-1'); $this->assertEquals('iso-8859-1', $e->getTextCharset()); $this->assertEquals('iso-8859-1', $e->getHtmlCharset()); $this->assertEquals(new AlternativePart(new TextPart('text content', 'iso-8859-1'), new TextPart('html content', 'iso-8859-1', 'html')), $e->getBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->attach($file); $e->text('text content'); $this->assertEquals(new MixedPart($text, $att), $e->getBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->attach($file); $e->html('html content'); $this->assertEquals(new MixedPart($html, $att), $e->getBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->attach($file); $this->assertEquals(new MixedPart($att), $e->getBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->html('html content'); $e->text('text content'); $e->attach($file); $this->assertEquals(new MixedPart(new AlternativePart($text, $html), $att), $e->getBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->html('html content'); $e->text('text content'); $e->attach($file); $e->attach($image, 'test.gif'); $this->assertEquals(new MixedPart(new AlternativePart($text, $html), $att, $img), $e->getBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->text('text content'); $e->attach($file); $e->attach($image, 'test.gif'); $this->assertEquals(new MixedPart($text, $att, $img), $e->getBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->html($content = 'html content '); $e->text('text content'); $e->attach($file); @@ -314,7 +314,7 @@ public function testGenerateBody() $fullhtml = new TextPart($content, 'utf-8', 'html'); $this->assertEquals(new MixedPart(new AlternativePart($text, $fullhtml), $att, $img), $e->getBody()); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->html($content = 'html content '); $e->text('text content'); $e->attach($file); @@ -334,7 +334,7 @@ public function testGenerateBody() fwrite($r, $content); rewind($r); - $e = (new Email())->from('me@example.com'); + $e = (new Email())->from('me@example.com')->to('you@example.com'); $e->html($r); // embedding the same image twice results in one image only in the email $e->embed($image, 'test.gif'); @@ -373,6 +373,7 @@ public function testSerialize() $e = new Email(); $e->from('fabien@symfony.com'); + $e->to('you@example.com'); $e->text($r); $e->html($r); $name = __DIR__.'/Fixtures/mimetypes/test'; diff --git a/src/Symfony/Component/Mime/Tests/MessageConverterTest.php b/src/Symfony/Component/Mime/Tests/MessageConverterTest.php index 6a7808624637..a0e71a08a941 100644 --- a/src/Symfony/Component/Mime/Tests/MessageConverterTest.php +++ b/src/Symfony/Component/Mime/Tests/MessageConverterTest.php @@ -21,7 +21,7 @@ class MessageConverterTest extends TestCase public function testToEmail() { $file = file_get_contents(__DIR__.'/Fixtures/mimetypes/test.gif'); - $email = (new Email())->from('fabien@symfony.com'); + $email = (new Email())->from('fabien@symfony.com')->to('you@example.com'); $this->assertSame($email, MessageConverter::toEmail($email)); $this->assertConversion((clone $email)->text('text content')); diff --git a/src/Symfony/Component/Mime/Tests/Part/MessagePartTest.php b/src/Symfony/Component/Mime/Tests/Part/MessagePartTest.php index 21a4eb03b129..2713d5bc079c 100644 --- a/src/Symfony/Component/Mime/Tests/Part/MessagePartTest.php +++ b/src/Symfony/Component/Mime/Tests/Part/MessagePartTest.php @@ -22,7 +22,7 @@ class MessagePartTest extends TestCase { public function testConstructor() { - $p = new MessagePart((new Email())->from('fabien@symfony.com')->text('content')); + $p = new MessagePart((new Email())->from('fabien@symfony.com')->to('you@example.com')->text('content')); $this->assertStringContainsString('content', $p->getBody()); $this->assertStringContainsString('content', $p->bodyToString()); $this->assertStringContainsString('content', implode('', iterator_to_array($p->bodyToIterable())));