diff --git a/src/Symfony/Component/Mailer/CHANGELOG.md b/src/Symfony/Component/Mailer/CHANGELOG.md index f876701168c59..3816cc474948b 100644 --- a/src/Symfony/Component/Mailer/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * Add DSN param `retry_period` to override default email transport retry period * Add `Dsn::getBooleanOption()` * Add DSN param `source_ip` to allow binding to a (specific) IPv4 or IPv6 address. + * Add DSN param `require_tls` to enforce use of TLS/STARTTLS * Add `DkimSignedMessageListener`, `SmimeEncryptedMessageListener`, and `SmimeSignedMessageListener` 7.2 diff --git a/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportFactoryTest.php index 1fbb20ba22694..b43a9c8bbd362 100644 --- a/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportFactoryTest.php +++ b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportFactoryTest.php @@ -194,6 +194,18 @@ public static function createProvider(): iterable Dsn::fromString('smtps://:@example.com:465?source_ip=[2606:4700:20::681a:5fb]'), $transport, ]; + + $transport = new EsmtpTransport('example.com', 465, true, null, $logger); + $transport->setRequireTls(true); + + yield [ + new Dsn('smtps', 'example.com', '', '', 465, ['require_tls' => true]), + $transport, + ]; + yield [ + Dsn::fromString('smtps://:@example.com?require_tls=true'), + $transport, + ]; } public static function unsupportedSchemeProvider(): iterable diff --git a/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportTest.php index 9b4eacbf1b7f0..ae336939cda74 100644 --- a/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportTest.php +++ b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportTest.php @@ -297,6 +297,23 @@ public function testSocketTimeout() $stream->getCommands() ); } + + public function testRequireTls() + { + $stream = new DummyStream(); + $transport = new EsmtpTransport(stream: $stream); + $transport->setRequireTls(true); + + $message = new Email(); + $message->from('sender@example.org'); + $message->addTo('recipient@example.org'); + $message->text('.'); + + $this->expectException(TransportException::class); + $this->expectExceptionMessage('TLS required but neither TLS or STARTTLS are in use.'); + + $transport->send($message); + } } class CustomEsmtpTransport extends EsmtpTransport diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php b/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php index 3663dc6f5604c..1c332d677aaa1 100644 --- a/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php +++ b/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php @@ -33,6 +33,7 @@ class EsmtpTransport extends SmtpTransport private string $password = ''; private array $capabilities; private bool $autoTls = true; + private bool $requireTls = false; public function __construct(string $host = 'localhost', int $port = 0, ?bool $tls = null, ?EventDispatcherInterface $dispatcher = null, ?LoggerInterface $logger = null, ?AbstractStream $stream = null, ?array $authenticators = null) { @@ -116,6 +117,21 @@ public function isAutoTls(): bool return $this->autoTls; } + /** + * @return $this + */ + public function setRequireTls(bool $requireTls): static + { + $this->requireTls = $requireTls; + + return $this; + } + + public function isTlsRequired(): bool + { + return $this->requireTls; + } + public function setAuthenticators(array $authenticators): void { $this->authenticators = []; @@ -159,6 +175,7 @@ private function doEhloCommand(): string /** @var SocketStream $stream */ $stream = $this->getStream(); + $tlsStarted = $stream->isTls(); // WARNING: !$stream->isTLS() is right, 100% sure :) // if you think that the ! should be removed, read the code again // if doing so "fixes" your issue then it probably means your SMTP server behaves incorrectly or is wrongly configured @@ -169,10 +186,15 @@ private function doEhloCommand(): string throw new TransportException('Unable to connect with STARTTLS.'); } + $tlsStarted = true; $response = $this->executeCommand(\sprintf("EHLO %s\r\n", $this->getLocalDomain()), [250]); $this->capabilities = $this->parseCapabilities($response); } + if (!$tlsStarted && $this->isTlsRequired()) { + throw new TransportException('TLS required but neither TLS or STARTTLS are in use.'); + } + if (\array_key_exists('AUTH', $this->capabilities)) { $this->handleAuth($this->capabilities['AUTH']); } diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransportFactory.php b/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransportFactory.php index 17869353128af..acfa2c4ef2b1e 100644 --- a/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransportFactory.php +++ b/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransportFactory.php @@ -35,6 +35,7 @@ public function create(Dsn $dsn): TransportInterface $transport = new EsmtpTransport($host, $port, $tls, $this->dispatcher, $this->logger); $transport->setAutoTls($autoTls); + $transport->setRequireTls($dsn->getBooleanOption('require_tls')); /** @var SocketStream $stream */ $stream = $transport->getStream(); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy