mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-04 10:42:23 +00:00
Store server IPs in one form (no brackets, short lower-case IPv6) and write each address in the form its context needs: - URLs and host:port (Sentinel, database URLs, SFTP backup download, DNS servers, SMTP, webhook base URLs, links, health checks) get brackets through formatHostForUrl(). - Traefik Host() rules use the address without brackets, so IPv6 domains no longer return 404; saved labels are fixed at deploy. Caddy keeps the brackets. - SSH keeps the plain address. - Hetzner gives an IPv6 /64 network; IPv6-only servers now get the server address (prefix::1) instead of the unusable prefix::64. - sslip labels, registry image names with an IPv6 host, the API domain list, allowlist matching and duplicate checks handle IPv6. A migration normalizes stored IPv6 server addresses, repairs Hetzner servers saved as ::64 that are not reachable, and adds brackets to saved Sentinel URLs.
146 lines
4.7 KiB
PHP
146 lines
4.7 KiB
PHP
<?php
|
|
|
|
use App\Support\SmtpTransportFactory;
|
|
use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
|
|
|
|
function smtpSettings(array $overrides = []): object
|
|
{
|
|
return (object) array_merge([
|
|
'smtp_host' => 'smtp.example.com',
|
|
'smtp_port' => 25,
|
|
'smtp_encryption' => 'none',
|
|
'smtp_username' => 'user',
|
|
'smtp_password' => 'secret',
|
|
'smtp_timeout' => null,
|
|
], $overrides);
|
|
}
|
|
|
|
it('disables opportunistic STARTTLS when encryption is none', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(smtpSettings([
|
|
'smtp_encryption' => 'none',
|
|
]));
|
|
|
|
expect($transport->isAutoTls())->toBeFalse()
|
|
->and($transport->getStream())->toBeInstanceOf(SocketStream::class)
|
|
->and($transport->getStream()->isTLS())->toBeFalse();
|
|
});
|
|
|
|
it('does not issue STARTTLS for the issue 5877 anonymous port 25 relay', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(smtpSettings([
|
|
'smtp_encryption' => 'none',
|
|
'smtp_port' => 25,
|
|
'smtp_username' => '',
|
|
'smtp_password' => '',
|
|
]));
|
|
|
|
expect($transport->isAutoTls())->toBeFalse()
|
|
->and($transport->getStream()->isTLS())->toBeFalse()
|
|
->and($transport->getStream()->getPort())->toBe(25)
|
|
->and($transport->getUsername())->toBe('')
|
|
->and($transport->getPassword())->toBe('');
|
|
});
|
|
|
|
it('does not enable implicit TLS on port 465 when encryption is none', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(smtpSettings([
|
|
'smtp_encryption' => 'none',
|
|
'smtp_port' => 465,
|
|
]));
|
|
|
|
expect($transport->isAutoTls())->toBeFalse()
|
|
->and($transport->getStream()->isTLS())->toBeFalse();
|
|
});
|
|
|
|
it('keeps opportunistic STARTTLS when encryption is starttls', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(smtpSettings([
|
|
'smtp_encryption' => 'starttls',
|
|
]));
|
|
|
|
expect($transport->isAutoTls())->toBeTrue()
|
|
->and($transport->getStream()->isTLS())->toBeFalse();
|
|
});
|
|
|
|
it('uses implicit TLS when encryption is tls', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(smtpSettings([
|
|
'smtp_encryption' => 'tls',
|
|
'smtp_port' => 465,
|
|
]));
|
|
|
|
expect($transport->isAutoTls())->toBeTrue()
|
|
->and($transport->getStream()->isTLS())->toBeTrue();
|
|
});
|
|
|
|
it('infers implicit TLS on port 465 when encryption is null', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(smtpSettings([
|
|
'smtp_encryption' => null,
|
|
'smtp_port' => 465,
|
|
]));
|
|
|
|
expect($transport->getStream()->isTLS())->toBeTrue();
|
|
});
|
|
|
|
it('applies a configured SMTP timeout to the transport stream', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(smtpSettings([
|
|
'smtp_timeout' => 15,
|
|
]));
|
|
|
|
expect($transport->getStream()->getTimeout())->toBe(15.0);
|
|
});
|
|
|
|
it('applies the configured ehlo domain to the transport', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(
|
|
smtpSettings(['smtp_ehlo_domain' => 'team.example.com']),
|
|
'instance.example.com'
|
|
);
|
|
|
|
expect($transport->getLocalDomain())->toBe('team.example.com');
|
|
});
|
|
|
|
it('falls back to the instance ehlo domain for legacy smtp settings', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(
|
|
smtpSettings(),
|
|
'instance.example.com'
|
|
);
|
|
|
|
expect($transport->getLocalDomain())->toBe('instance.example.com');
|
|
});
|
|
|
|
it('maps none encryption to laravel mailer options that disable auto tls', function () {
|
|
expect(SmtpTransportFactory::mailerOptions(smtpSettings([
|
|
'smtp_encryption' => 'none',
|
|
])))->toBe([
|
|
'scheme' => 'smtp',
|
|
'encryption' => null,
|
|
'auto_tls' => '0',
|
|
]);
|
|
});
|
|
|
|
it('maps encryption to laravel mailer options', function (?string $mode, ?string $scheme, ?string $encryption) {
|
|
expect(SmtpTransportFactory::mailerOptions(smtpSettings([
|
|
'smtp_encryption' => $mode,
|
|
])))->toBe([
|
|
'scheme' => $scheme,
|
|
'encryption' => $encryption,
|
|
'auto_tls' => $mode === 'none' ? '0' : '',
|
|
]);
|
|
})->with([
|
|
'none' => ['none', 'smtp', null],
|
|
'starttls' => ['starttls', 'smtp', null],
|
|
'tls' => ['tls', 'smtps', 'tls'],
|
|
'unset' => [null, null, null],
|
|
]);
|
|
|
|
it('brackets an IPv6 smtp host', function (string $host) {
|
|
$transport = SmtpTransportFactory::fromSettings(smtpSettings(['smtp_host' => $host]));
|
|
|
|
expect($transport->getStream()->getHost())->toBe('[2001:db8::25]');
|
|
})->with([
|
|
'raw' => '2001:db8::25',
|
|
'bracketed' => '[2001:db8::25]',
|
|
]);
|
|
|
|
it('keeps a hostname smtp host unchanged', function () {
|
|
$transport = SmtpTransportFactory::fromSettings(smtpSettings(['smtp_host' => 'smtp.example.com']));
|
|
|
|
expect($transport->getStream()->getHost())->toBe('smtp.example.com');
|
|
});
|