From f4254e6f5e74406ca7cbcd1606d0dd3c2032d0c7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 31 May 2019 16:32:37 +0300 Subject: [PATCH] [Mailer] fixed the possibility to set a From header from MessageListener --- .../Component/Mailer/DelayedSmtpEnvelope.php | 105 ++++++++++++++++++ src/Symfony/Component/Mailer/SmtpEnvelope.php | 39 +------ .../Mailer/Tests/SmtpEnvelopeTest.php | 7 +- .../Mailer/Transport/AbstractTransport.php | 3 +- 4 files changed, 112 insertions(+), 42 deletions(-) create mode 100644 src/Symfony/Component/Mailer/DelayedSmtpEnvelope.php diff --git a/src/Symfony/Component/Mailer/DelayedSmtpEnvelope.php b/src/Symfony/Component/Mailer/DelayedSmtpEnvelope.php new file mode 100644 index 000000000000..95356fd9e350 --- /dev/null +++ b/src/Symfony/Component/Mailer/DelayedSmtpEnvelope.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer; + +use Symfony\Component\Mailer\Exception\InvalidArgumentException; +use Symfony\Component\Mailer\Exception\LogicException; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\RawMessage; + +/** + * @author Fabien Potencier + * + * @experimental in 4.3 + * + * @internal + */ +final class DelayedSmtpEnvelope extends SmtpEnvelope +{ + private $senderSet = false; + private $recipientsSet = false; + private $message; + + public function __construct(RawMessage $message) + { + if (!$message instanceof Message) { + // FIXME: parse the raw message to create the envelope? + throw new InvalidArgumentException(sprintf('Unable to create an SmtpEnvelope from a "%s" message.', RawMessage::class)); + } + + $this->message = $message; + } + + public function setSender(Address $sender): void + { + parent::setSender($sender); + + $this->senderSet = true; + } + + public function getSender(): Address + { + if ($this->senderSet) { + return parent::getSender(); + } + + return self::getSenderFromHeaders($this->message->getHeaders()); + } + + public function setRecipients(array $recipients): void + { + parent::setRecipients($recipients); + + $this->recipientsSet = parent::getRecipients(); + } + + /** + * @return Address[] + */ + public function getRecipients(): array + { + if ($this->recipientsSet) { + return parent::getRecipients(); + } + + return self::getRecipientsFromHeaders($this->message->getHeaders()); + } + + private static function getRecipientsFromHeaders(Headers $headers): array + { + $recipients = []; + foreach (['to', 'cc', 'bcc'] as $name) { + foreach ($headers->getAll($name) as $header) { + $recipients = array_merge($recipients, $header->getAddresses()); + } + } + + return $recipients; + } + + private static function getSenderFromHeaders(Headers $headers): Address + { + if ($return = $headers->get('Return-Path')) { + return $return->getAddress(); + } + if ($sender = $headers->get('Sender')) { + return $sender->getAddress(); + } + if ($from = $headers->get('From')) { + return $from->getAddresses()[0]; + } + + throw new LogicException('Unable to determine the sender of the message.'); + } +} diff --git a/src/Symfony/Component/Mailer/SmtpEnvelope.php b/src/Symfony/Component/Mailer/SmtpEnvelope.php index 6a41027305c1..7f1458d0f8bd 100644 --- a/src/Symfony/Component/Mailer/SmtpEnvelope.php +++ b/src/Symfony/Component/Mailer/SmtpEnvelope.php @@ -12,10 +12,7 @@ namespace Symfony\Component\Mailer; use Symfony\Component\Mailer\Exception\InvalidArgumentException; -use Symfony\Component\Mailer\Exception\LogicException; use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Header\Headers; -use Symfony\Component\Mime\Message; use Symfony\Component\Mime\NamedAddress; use Symfony\Component\Mime\RawMessage; @@ -40,14 +37,7 @@ public function __construct(Address $sender, array $recipients) public static function create(RawMessage $message): self { - if ($message instanceof Message) { - $headers = $message->getHeaders(); - - return new self(self::getSenderFromHeaders($headers), self::getRecipientsFromHeaders($headers)); - } - - // FIXME: parse the raw message to create the envelope? - throw new InvalidArgumentException(sprintf('Unable to create an SmtpEnvelope from a "%s" message.', RawMessage::class)); + return new DelayedSmtpEnvelope($message); } public function setSender(Address $sender): void @@ -84,31 +74,4 @@ public function getRecipients(): array { return $this->recipients; } - - private static function getRecipientsFromHeaders(Headers $headers): array - { - $recipients = []; - foreach (['to', 'cc', 'bcc'] as $name) { - foreach ($headers->getAll($name) as $header) { - $recipients = array_merge($recipients, $header->getAddresses()); - } - } - - return $recipients; - } - - private static function getSenderFromHeaders(Headers $headers): Address - { - if ($return = $headers->get('Return-Path')) { - return $return->getAddress(); - } - if ($sender = $headers->get('Sender')) { - return $sender->getAddress(); - } - if ($from = $headers->get('From')) { - return $from->getAddresses()[0]; - } - - throw new LogicException('Unable to determine the sender of the message.'); - } } diff --git a/src/Symfony/Component/Mailer/Tests/SmtpEnvelopeTest.php b/src/Symfony/Component/Mailer/Tests/SmtpEnvelopeTest.php index 4e0c17f5e838..6bc24bdf2f0b 100644 --- a/src/Symfony/Component/Mailer/Tests/SmtpEnvelopeTest.php +++ b/src/Symfony/Component/Mailer/Tests/SmtpEnvelopeTest.php @@ -72,12 +72,13 @@ public function testSenderFromHeaders() $this->assertEquals('from@symfony.com', $e->getSender()->getAddress()); } - public function testSenderFromHeadersWithoutData() + public function testSenderFromHeadersWithoutFrom() { - $this->expectException(\LogicException::class); $headers = new Headers(); $headers->addMailboxListHeader('To', ['from@symfony.com']); - SmtpEnvelope::create(new Message($headers)); + $e = SmtpEnvelope::create($message = new Message($headers)); + $message->getHeaders()->addMailboxListHeader('From', ['from@symfony.com']); + $this->assertEquals('from@symfony.com', $e->getSender()->getAddress()); } public function testRecipientsFromHeaders() diff --git a/src/Symfony/Component/Mailer/Transport/AbstractTransport.php b/src/Symfony/Component/Mailer/Transport/AbstractTransport.php index deebd538f5e7..748743fa8a30 100644 --- a/src/Symfony/Component/Mailer/Transport/AbstractTransport.php +++ b/src/Symfony/Component/Mailer/Transport/AbstractTransport.php @@ -15,6 +15,7 @@ use Psr\Log\NullLogger; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Mailer\DelayedSmtpEnvelope; use Symfony\Component\Mailer\Event\MessageEvent; use Symfony\Component\Mailer\Exception\TransportException; use Symfony\Component\Mailer\SentMessage; @@ -62,7 +63,7 @@ public function send(RawMessage $message, SmtpEnvelope $envelope = null): ?SentM $envelope = clone $envelope; } else { try { - $envelope = SmtpEnvelope::create($message); + $envelope = new DelayedSmtpEnvelope($message); } catch (\Exception $e) { throw new TransportException('Cannot send message without a valid envelope.', 0, $e); }