10000 [Mailer] [Smtp] Add DSN param to enforce TLS/STARTTLS · symfony/symfony@9243f56 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9243f56

< 8000 a class="Box-sc-g0xbh4-0 fyKNMY Box-sc-g0xbh4-0 fyKNMY prc-Button-ButtonBase-c50BI prc-Link-Link-85e08" style="--button-color:fg.default" type="button" href="/symfony/symfony/tree/9243f56fb93bf817cf5ded92e99a2e89fe5593f1" data-loading="false" data-size="medium" data-variant="default" aria-describedby=":R3abab:-loading-announcement">Browse files
committed
[Mailer] [Smtp] Add DSN param to enforce TLS/STARTTLS
Adds 'require_tls' param which can be set to true to enforce the use of TLS/STARTTLS within the ESMTP transport.
1 parent dfcc142 commit 9243f56

File tree

5 files changed

+57
-0
lines changed

5 files changed

+57
-0
lines changed

src/Symfony/Component/Mailer/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Add DSN param `retry_period` to override default email transport retry period
8+
* Add DSN param `require_tls` to enforce use of TLS/STARTTLS
89

910
7.2
1011
---

src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportFactoryTest.php

+12
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,18 @@ public static function createProvider(): iterable
180180
Dsn::fromString('smtp://:@example.com:465?auto_tls=false'),
181181
$transport,
182182
];
183+
184+
$transport = new EsmtpTransport('example.com', 465, true, null, $logger);
185+
$transport->setRequireTls(true);
186+
187+
yield [
188+
new Dsn('smtps', 'example.com', '', '', 465, ['require_tls' => true]),
189+
$transport,
190+
];
191+
yield [
192+
Dsn::fromString('smtps://:@example.com?require_tls=true'),
193+
$transport,
194+
];
183195
}
184196

185197
public static function unsupportedSchemeProvider(): iterable

src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportTest.php

+19
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,25 @@ public function testSocketTimeout()
297297
$stream->getCommands()
298298
);
299299
}
300+
301+
public function testRequireTls()
302+
{
303+
$stream = new DummyStream();
304+
$transport = new EsmtpTransport(stream: $stream);
305+
$transport->setRequireTls(true);
306+
307+
$message = new Email();
308+
$message->from('sender@example.org');
309+
$message->addTo('recipient@example.org');
310+
$message->text('.');
311+
312+
try {
313+
$transport->send($message);
314+
$this->fail('Symfony\Component\Mailer\Exception\TransportException to be thrown');
315+
} catch (TransportException $e) {
316+
$this->assertStringStartsWith('TLS required but neither TLS or STARTTLS are in use.', $e->getMessage());
317+
}
318+
}
300319
}
301320

302321
class CustomEsmtpTransport extends EsmtpTransport

src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php

+21
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class EsmtpTransport extends SmtpTransport
3333
private string $password = '';
3434
private array $capabilities;
3535
private bool $autoTls = true;
36+
private bool $requireTls = false;
3637

3738
public function __construct(string $host = 'localhost', int $port = 0, ?bool $tls = null, ?EventDispatcherInterface $dispatcher = null, ?LoggerInterface $logger = null, ?AbstractStream $stream = null, ?array $authenticators = null)
3839
{
@@ -116,6 +117,20 @@ public function isAutoTls(): bool
116117
return $this->autoTls;
117118
}
118119

120+
/**
121+
* @return $this
122+
*/
123+
public function setRequireTls(bool $requireTls): static
124+
{
125+
$this->requireTls = $requireTls;
126+
return $this;
127+
}
128+
129+
public function isTlsRequired(): bool
130+
{
131+
return $this->requireTls;
132+
}
133+
119134
public function setAuthenticators(array $authenticators): void
120135
{
121136
$this->authenticators = [];
@@ -159,6 +174,7 @@ private function doEhloCommand(): string
159174

160175
/** @var SocketStream $stream */
161176
$stream = $this->getStream();
177+
$tlsStarted = $stream->isTls();
162178
// WARNING: !$stream->isTLS() is right, 100% sure :)
163179
// if you think that the ! should be removed, read the code again
164180
// if doing so "fixes" your issue then it probably means your SMTP server behaves incorrectly or is wrongly configured
@@ -169,10 +185,15 @@ private function doEhloCommand(): string
169185
throw new TransportException('Unable to connect with STARTTLS.');
170186
}
171187

188+
$tlsStarted = true;
172189
$response = $this->executeCommand(\sprintf("EHLO %s\r\n", $this->getLocalDomain()), [250]);
173190
$this->capabilities = $this->parseCapabilities($response);
174191
}
175192

193+
if (!$tlsStarted && $this->isTlsRequired()) {
194+
throw new TransportException('TLS required but neither TLS or STARTTLS are in use.');
195+
}
196+
176197
if (\array_key_exists('AUTH', $this->capabilities)) {
177198
$this->handleAuth($this->capabilities['AUTH']);
178199
}

src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransportFactory.php

+4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ public function create(Dsn $dsn): TransportInterface
7575
$transport->setPingThreshold((int) $pingThreshold);
7676
}
7777

78+
if (null !== ($tlsRequired = $dsn->getOption('require_tls'))) {
79+
$transport->setRequireTls((bool) $tlsRequired);
80+
}
81+
7882
return $transport;
7983
}
8084

0 commit comments

Comments
 (0)
0