70 lines
3.1 KiB
PHP
70 lines
3.1 KiB
PHP
<?php
|
|
|
|
use App\Services\Mail\MailTlsPolicy;
|
|
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
|
|
|
|
/**
|
|
* The single place that decides what "ssl", "tls", and "none" mean on the
|
|
* wire. MailboxTransport (real sends) and MailboxTester (the test-send
|
|
* button) used to each re-derive the "ssl, or port 465 ⇒ implicit TLS" half
|
|
* of this on their own — this table is what replaces both copies, so it is
|
|
* pinned down here independently of either caller.
|
|
*/
|
|
it('maps a stored encryption choice and port to the three EsmtpTransport switches', function (
|
|
string $encryption,
|
|
int $port,
|
|
bool $implicit,
|
|
bool $autoTls,
|
|
bool $requireTls,
|
|
) {
|
|
$policy = MailTlsPolicy::for($encryption, $port);
|
|
|
|
expect($policy->implicit)->toBe($implicit)
|
|
->and($policy->autoTls)->toBe($autoTls)
|
|
->and($policy->requireTls)->toBe($requireTls);
|
|
})->with([
|
|
// encryption, port, implicit, autoTls, requireTls
|
|
|
|
// 'ssl' is implicit TLS from the first byte, on any port — unchanged
|
|
// from before this fix.
|
|
'ssl on the submission port' => ['ssl', 587, true, true, true],
|
|
'ssl on the SMTPS port' => ['ssl', 465, true, true, true],
|
|
|
|
// Port 465 forces implicit TLS regardless of the stored encryption
|
|
// setting, exactly as before this fix: a server listening there speaks
|
|
// TLS from byte one and will not answer a plaintext EHLO, so a
|
|
// mismatched setting must not turn into a hang.
|
|
'tls on the SMTPS port defers to the port' => ['tls', 465, true, true, true],
|
|
'none on the SMTPS port defers to the port' => ['none', 465, true, true, true],
|
|
|
|
// 'tls' is the fix: STARTTLS is REQUIRED, not merely attempted. autoTls
|
|
// must stay on too, or the STARTTLS upgrade requireTls checks for would
|
|
// never be attempted in the first place.
|
|
'tls on the submission port' => ['tls', 587, false, true, true],
|
|
'tls on a custom port' => ['tls', 2525, false, true, true],
|
|
|
|
// 'none' is the other half of the fix: no implicit wrap, and autoTls
|
|
// OFF — otherwise a server that happens to offer STARTTLS would still
|
|
// silently upgrade despite the operator's explicit choice.
|
|
'none on the submission port' => ['none', 587, false, false, false],
|
|
'none on a custom port' => ['none', 2525, false, false, false],
|
|
|
|
// Blank or unrecognised values (a legacy row predating the in:tls,ssl,none
|
|
// validation, or one that decoded to something unexpected) fall to the
|
|
// same shape as 'none': no implicit wrap, no silent upgrade, no
|
|
// spurious failure for a value nobody explicitly chose as 'tls'.
|
|
'blank falls back to the none shape' => ['', 587, false, false, false],
|
|
'garbage falls back to the none shape' => ['garbage', 587, false, false, false],
|
|
]);
|
|
|
|
it('applies autoTls and requireTls to an already-built transport', function () {
|
|
$transport = new EsmtpTransport('mail.example.test', 587, false);
|
|
|
|
$policy = MailTlsPolicy::for('tls', 587);
|
|
$returned = $policy->apply($transport);
|
|
|
|
expect($returned)->toBe($transport) // fluent — the caller chains straight through
|
|
->and($transport->isAutoTls())->toBeTrue()
|
|
->and($transport->isTlsRequired())->toBeTrue();
|
|
});
|