[Mailer] simplified the way TLS/SSL/StartTls work
This commit is contained in:
parent
bc79cfe003
commit
5b8c4676d0
@ -43,6 +43,11 @@ class SesTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'ses'),
|
||||||
|
true,
|
||||||
|
];
|
||||||
|
|
||||||
yield [
|
yield [
|
||||||
new Dsn('smtp', 'example.com'),
|
new Dsn('smtp', 'example.com'),
|
||||||
false,
|
false,
|
||||||
@ -84,13 +89,18 @@ class SesTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
new Dsn('smtp', 'ses', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
new Dsn('smtp', 'ses', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
||||||
new SesSmtpTransport(self::USER, self::PASSWORD, 'eu-west-1', $dispatcher, $logger),
|
new SesSmtpTransport(self::USER, self::PASSWORD, 'eu-west-1', $dispatcher, $logger),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'ses', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
||||||
|
new SesSmtpTransport(self::USER, self::PASSWORD, 'eu-west-1', $dispatcher, $logger),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unsupportedSchemeProvider(): iterable
|
public function unsupportedSchemeProvider(): iterable
|
||||||
{
|
{
|
||||||
yield [
|
yield [
|
||||||
new Dsn('foo', 'ses', self::USER, self::PASSWORD),
|
new Dsn('foo', 'ses', self::USER, self::PASSWORD),
|
||||||
'The "foo" scheme is not supported for mailer "ses". Supported schemes are: "api", "http", "smtp".',
|
'The "foo" scheme is not supported for mailer "ses". Supported schemes are: "api", "http", "smtp", "smtps".',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class SesSmtpTransport extends EsmtpTransport
|
|||||||
*/
|
*/
|
||||||
public function __construct(string $username, string $password, string $region = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
public function __construct(string $username, string $password, string $region = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
parent::__construct(sprintf('email-smtp.%s.amazonaws.com', $region ?: 'eu-west-1'), 587, 'tls', null, $dispatcher, $logger);
|
parent::__construct(sprintf('email-smtp.%s.amazonaws.com', $region ?: 'eu-west-1'), 587, true, null, $dispatcher, $logger);
|
||||||
|
|
||||||
$this->setUsername($username);
|
$this->setUsername($username);
|
||||||
$this->setPassword($password);
|
$this->setPassword($password);
|
||||||
|
@ -36,11 +36,11 @@ final class SesTransportFactory extends AbstractTransportFactory
|
|||||||
return new SesHttpTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger);
|
return new SesHttpTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('smtp' === $scheme) {
|
if ('smtp' === $scheme || 'smtps' === $scheme) {
|
||||||
return new SesSmtpTransport($user, $password, $region, $this->dispatcher, $this->logger);
|
return new SesSmtpTransport($user, $password, $region, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, ['api', 'http', 'smtp']);
|
throw new UnsupportedSchemeException($dsn, ['api', 'http', 'smtp', 'smtps']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function supports(Dsn $dsn): bool
|
public function supports(Dsn $dsn): bool
|
||||||
|
@ -22,6 +22,11 @@ class GmailTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'gmail'),
|
||||||
|
true,
|
||||||
|
];
|
||||||
|
|
||||||
yield [
|
yield [
|
||||||
new Dsn('smtp', 'example.com'),
|
new Dsn('smtp', 'example.com'),
|
||||||
false,
|
false,
|
||||||
@ -34,13 +39,18 @@ class GmailTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
new Dsn('smtp', 'gmail', self::USER, self::PASSWORD),
|
new Dsn('smtp', 'gmail', self::USER, self::PASSWORD),
|
||||||
new GmailSmtpTransport(self::USER, self::PASSWORD, $this->getDispatcher(), $this->getLogger()),
|
new GmailSmtpTransport(self::USER, self::PASSWORD, $this->getDispatcher(), $this->getLogger()),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'gmail', self::USER, self::PASSWORD),
|
||||||
|
new GmailSmtpTransport(self::USER, self::PASSWORD, $this->getDispatcher(), $this->getLogger()),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unsupportedSchemeProvider(): iterable
|
public function unsupportedSchemeProvider(): iterable
|
||||||
{
|
{
|
||||||
yield [
|
yield [
|
||||||
new Dsn('foo', 'gmail', self::USER, self::PASSWORD),
|
new Dsn('foo', 'gmail', self::USER, self::PASSWORD),
|
||||||
'The "foo" scheme is not supported for mailer "gmail". Supported schemes are: "smtp".',
|
'The "foo" scheme is not supported for mailer "gmail". Supported schemes are: "smtp", "smtps".',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class GmailSmtpTransport extends EsmtpTransport
|
|||||||
{
|
{
|
||||||
public function __construct(string $username, string $password, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
public function __construct(string $username, string $password, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
parent::__construct('smtp.gmail.com', 465, 'ssl', null, $dispatcher, $logger);
|
parent::__construct('smtp.gmail.com', 465, true, null, $dispatcher, $logger);
|
||||||
|
|
||||||
$this->setUsername($username);
|
$this->setUsername($username);
|
||||||
$this->setPassword($password);
|
$this->setPassword($password);
|
||||||
|
@ -23,11 +23,11 @@ final class GmailTransportFactory extends AbstractTransportFactory
|
|||||||
{
|
{
|
||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
if ('smtp' === $dsn->getScheme()) {
|
if ('smtp' === $dsn->getScheme() || 'smtps' === $dsn->getScheme()) {
|
||||||
return new GmailSmtpTransport($this->getUser($dsn), $this->getPassword($dsn), $this->dispatcher, $this->logger);
|
return new GmailSmtpTransport($this->getUser($dsn), $this->getPassword($dsn), $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, ['smtp']);
|
throw new UnsupportedSchemeException($dsn, ['smtp', 'smtps']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function supports(Dsn $dsn): bool
|
public function supports(Dsn $dsn): bool
|
||||||
|
@ -43,6 +43,11 @@ class MandrillTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'mandrill'),
|
||||||
|
true,
|
||||||
|
];
|
||||||
|
|
||||||
yield [
|
yield [
|
||||||
new Dsn('smtp', 'example.com'),
|
new Dsn('smtp', 'example.com'),
|
||||||
false,
|
false,
|
||||||
@ -69,13 +74,18 @@ class MandrillTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
new Dsn('smtp', 'mandrill', self::USER, self::PASSWORD),
|
new Dsn('smtp', 'mandrill', self::USER, self::PASSWORD),
|
||||||
new MandrillSmtpTransport(self::USER, self::PASSWORD, $dispatcher, $logger),
|
new MandrillSmtpTransport(self::USER, self::PASSWORD, $dispatcher, $logger),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'mandrill', self::USER, self::PASSWORD),
|
||||||
|
new MandrillSmtpTransport(self::USER, self::PASSWORD, $dispatcher, $logger),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unsupportedSchemeProvider(): iterable
|
public function unsupportedSchemeProvider(): iterable
|
||||||
{
|
{
|
||||||
yield [
|
yield [
|
||||||
new Dsn('foo', 'mandrill', self::USER),
|
new Dsn('foo', 'mandrill', self::USER),
|
||||||
'The "foo" scheme is not supported for mailer "mandrill". Supported schemes are: "api", "http", "smtp".',
|
'The "foo" scheme is not supported for mailer "mandrill". Supported schemes are: "api", "http", "smtp", "smtps".',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class MandrillSmtpTransport extends EsmtpTransport
|
|||||||
{
|
{
|
||||||
public function __construct(string $username, string $password, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
public function __construct(string $username, string $password, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
parent::__construct('smtp.mandrillapp.com', 587, 'tls', null, $dispatcher, $logger);
|
parent::__construct('smtp.mandrillapp.com', 587, true, null, $dispatcher, $logger);
|
||||||
|
|
||||||
$this->setUsername($username);
|
$this->setUsername($username);
|
||||||
$this->setPassword($password);
|
$this->setPassword($password);
|
||||||
|
@ -34,13 +34,13 @@ final class MandrillTransportFactory extends AbstractTransportFactory
|
|||||||
return new MandrillHttpTransport($user, $this->client, $this->dispatcher, $this->logger);
|
return new MandrillHttpTransport($user, $this->client, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('smtp' === $scheme) {
|
if ('smtp' === $scheme || 'smtps' === $scheme) {
|
||||||
$password = $this->getPassword($dsn);
|
$password = $this->getPassword($dsn);
|
||||||
|
|
||||||
return new MandrillSmtpTransport($user, $password, $this->dispatcher, $this->logger);
|
return new MandrillSmtpTransport($user, $password, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, ['api', 'http', 'smtp']);
|
throw new UnsupportedSchemeException($dsn, ['api', 'http', 'smtp', 'smtps']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function supports(Dsn $dsn): bool
|
public function supports(Dsn $dsn): bool
|
||||||
|
@ -43,6 +43,11 @@ class MailgunTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'mailgun'),
|
||||||
|
true,
|
||||||
|
];
|
||||||
|
|
||||||
yield [
|
yield [
|
||||||
new Dsn('smtp', 'example.com'),
|
new Dsn('smtp', 'example.com'),
|
||||||
false,
|
false,
|
||||||
@ -74,13 +79,18 @@ class MailgunTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
new Dsn('smtp', 'mailgun', self::USER, self::PASSWORD),
|
new Dsn('smtp', 'mailgun', self::USER, self::PASSWORD),
|
||||||
new MailgunSmtpTransport(self::USER, self::PASSWORD, null, $dispatcher, $logger),
|
new MailgunSmtpTransport(self::USER, self::PASSWORD, null, $dispatcher, $logger),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'mailgun', self::USER, self::PASSWORD),
|
||||||
|
new MailgunSmtpTransport(self::USER, self::PASSWORD, null, $dispatcher, $logger),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unsupportedSchemeProvider(): iterable
|
public function unsupportedSchemeProvider(): iterable
|
||||||
{
|
{
|
||||||
yield [
|
yield [
|
||||||
new Dsn('foo', 'mailgun', self::USER, self::PASSWORD),
|
new Dsn('foo', 'mailgun', self::USER, self::PASSWORD),
|
||||||
'The "foo" scheme is not supported for mailer "mailgun". Supported schemes are: "api", "http", "smtp".',
|
'The "foo" scheme is not supported for mailer "mailgun". Supported schemes are: "api", "http", "smtp", "smtps".',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class MailgunSmtpTransport extends EsmtpTransport
|
|||||||
{
|
{
|
||||||
public function __construct(string $username, string $password, string $region = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
public function __construct(string $username, string $password, string $region = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
parent::__construct('us' !== ($region ?: 'us') ? sprintf('smtp.%s.mailgun.org', $region) : 'smtp.mailgun.org', 465, 'ssl', null, $dispatcher, $logger);
|
parent::__construct('us' !== ($region ?: 'us') ? sprintf('smtp.%s.mailgun.org', $region) : 'smtp.mailgun.org', 465, true, null, $dispatcher, $logger);
|
||||||
|
|
||||||
$this->setUsername($username);
|
$this->setUsername($username);
|
||||||
$this->setPassword($password);
|
$this->setPassword($password);
|
||||||
|
@ -36,11 +36,11 @@ final class MailgunTransportFactory extends AbstractTransportFactory
|
|||||||
return new MailgunHttpTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger);
|
return new MailgunHttpTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('smtp' === $scheme) {
|
if ('smtp' === $scheme || 'smtps' === $scheme) {
|
||||||
return new MailgunSmtpTransport($user, $password, $region, $this->dispatcher, $this->logger);
|
return new MailgunSmtpTransport($user, $password, $region, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, ['api', 'http', 'smtp']);
|
throw new UnsupportedSchemeException($dsn, ['api', 'http', 'smtp', 'smtps']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function supports(Dsn $dsn): bool
|
public function supports(Dsn $dsn): bool
|
||||||
|
@ -37,6 +37,11 @@ class PostmarkTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'postmark'),
|
||||||
|
true,
|
||||||
|
];
|
||||||
|
|
||||||
yield [
|
yield [
|
||||||
new Dsn('smtp', 'example.com'),
|
new Dsn('smtp', 'example.com'),
|
||||||
false,
|
false,
|
||||||
@ -57,13 +62,18 @@ class PostmarkTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
new Dsn('smtp', 'postmark', self::USER),
|
new Dsn('smtp', 'postmark', self::USER),
|
||||||
new PostmarkSmtpTransport(self::USER, $dispatcher, $logger),
|
new PostmarkSmtpTransport(self::USER, $dispatcher, $logger),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'postmark', self::USER),
|
||||||
|
new PostmarkSmtpTransport(self::USER, $dispatcher, $logger),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unsupportedSchemeProvider(): iterable
|
public function unsupportedSchemeProvider(): iterable
|
||||||
{
|
{
|
||||||
yield [
|
yield [
|
||||||
new Dsn('foo', 'postmark', self::USER),
|
new Dsn('foo', 'postmark', self::USER),
|
||||||
'The "foo" scheme is not supported for mailer "postmark". Supported schemes are: "api", "smtp".',
|
'The "foo" scheme is not supported for mailer "postmark". Supported schemes are: "api", "smtp", "smtps".',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class PostmarkSmtpTransport extends EsmtpTransport
|
|||||||
{
|
{
|
||||||
public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
parent::__construct('smtp.postmarkapp.com', 587, 'tls', null, $dispatcher, $logger);
|
parent::__construct('smtp.postmarkapp.com', 587, true, null, $dispatcher, $logger);
|
||||||
|
|
||||||
$this->setUsername($id);
|
$this->setUsername($id);
|
||||||
$this->setPassword($id);
|
$this->setPassword($id);
|
||||||
|
@ -30,11 +30,11 @@ final class PostmarkTransportFactory extends AbstractTransportFactory
|
|||||||
return new PostmarkApiTransport($user, $this->client, $this->dispatcher, $this->logger);
|
return new PostmarkApiTransport($user, $this->client, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('smtp' === $scheme) {
|
if ('smtp' === $scheme || 'smtps' === $scheme) {
|
||||||
return new PostmarkSmtpTransport($user, $this->dispatcher, $this->logger);
|
return new PostmarkSmtpTransport($user, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, ['api', 'smtp']);
|
throw new UnsupportedSchemeException($dsn, ['api', 'smtp', 'smtps']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function supports(Dsn $dsn): bool
|
public function supports(Dsn $dsn): bool
|
||||||
|
@ -37,6 +37,11 @@ class SendgridTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'sendgrid'),
|
||||||
|
true,
|
||||||
|
];
|
||||||
|
|
||||||
yield [
|
yield [
|
||||||
new Dsn('smtp', 'example.com'),
|
new Dsn('smtp', 'example.com'),
|
||||||
false,
|
false,
|
||||||
@ -57,13 +62,18 @@ class SendgridTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
new Dsn('smtp', 'sendgrid', self::USER),
|
new Dsn('smtp', 'sendgrid', self::USER),
|
||||||
new SendgridSmtpTransport(self::USER, $dispatcher, $logger),
|
new SendgridSmtpTransport(self::USER, $dispatcher, $logger),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'sendgrid', self::USER),
|
||||||
|
new SendgridSmtpTransport(self::USER, $dispatcher, $logger),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unsupportedSchemeProvider(): iterable
|
public function unsupportedSchemeProvider(): iterable
|
||||||
{
|
{
|
||||||
yield [
|
yield [
|
||||||
new Dsn('foo', 'sendgrid', self::USER),
|
new Dsn('foo', 'sendgrid', self::USER),
|
||||||
'The "foo" scheme is not supported for mailer "sendgrid". Supported schemes are: "api", "smtp".',
|
'The "foo" scheme is not supported for mailer "sendgrid". Supported schemes are: "api", "smtp", "smtps".',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ class SendgridSmtpTransport extends EsmtpTransport
|
|||||||
{
|
{
|
||||||
public function __construct(string $key, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
public function __construct(string $key, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
parent::__construct('smtp.sendgrid.net', 465, 'ssl', null, $dispatcher, $logger);
|
parent::__construct('smtp.sendgrid.net', 465, true, null, $dispatcher, $logger);
|
||||||
|
|
||||||
$this->setUsername('apikey');
|
$this->setUsername('apikey');
|
||||||
$this->setPassword($key);
|
$this->setPassword($key);
|
||||||
|
@ -29,11 +29,11 @@ final class SendgridTransportFactory extends AbstractTransportFactory
|
|||||||
return new SendgridApiTransport($key, $this->client, $this->dispatcher, $this->logger);
|
return new SendgridApiTransport($key, $this->client, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('smtp' === $dsn->getScheme()) {
|
if ('smtp' === $dsn->getScheme() || 'smtps' === $dsn->getScheme()) {
|
||||||
return new SendgridSmtpTransport($key, $this->dispatcher, $this->logger);
|
return new SendgridSmtpTransport($key, $this->dispatcher, $this->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedSchemeException($dsn, ['api', 'smtp']);
|
throw new UnsupportedSchemeException($dsn, ['api', 'smtp', 'smtps']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function supports(Dsn $dsn): bool
|
public function supports(Dsn $dsn): bool
|
||||||
|
@ -4,6 +4,9 @@ CHANGELOG
|
|||||||
4.4.0
|
4.4.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* STARTTLS cannot be enabled anymore (it is used automatically if TLS is disabled and the server supports STARTTLS)
|
||||||
|
* [BC BREAK] Removed the `encryption` DSN option (use `smtps` instead)
|
||||||
|
* Added support for the `smtps` protocol (does the same as using `smtp` and port `465`)
|
||||||
* Added PHPUnit constraints
|
* Added PHPUnit constraints
|
||||||
* Added `MessageDataCollector`
|
* Added `MessageDataCollector`
|
||||||
* Added `MessageEvents` and `MessageLoggerListener` to allow collecting sent emails
|
* Added `MessageEvents` and `MessageLoggerListener` to allow collecting sent emails
|
||||||
|
@ -69,7 +69,7 @@ abstract class TransportFactoryTestCase extends TestCase
|
|||||||
$factory = $this->getFactory();
|
$factory = $this->getFactory();
|
||||||
|
|
||||||
$this->assertEquals($transport, $factory->create($dsn));
|
$this->assertEquals($transport, $factory->create($dsn));
|
||||||
if ('smtp' !== $dsn->getScheme()) {
|
if ('smtp' !== $dsn->getScheme() && 'smtps' !== $dsn->getScheme()) {
|
||||||
$this->assertStringMatchesFormat($dsn->getScheme().'://%S'.$dsn->getHost().'%S', $transport->getName());
|
$this->assertStringMatchesFormat($dsn->getScheme().'://%S'.$dsn->getHost().'%S', $transport->getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,11 @@ class EsmtpTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'example.com'),
|
||||||
|
true,
|
||||||
|
];
|
||||||
|
|
||||||
yield [
|
yield [
|
||||||
new Dsn('api', 'example.com'),
|
new Dsn('api', 'example.com'),
|
||||||
false,
|
false,
|
||||||
@ -33,19 +38,33 @@ class EsmtpTransportFactoryTest extends TransportFactoryTestCase
|
|||||||
$eventDispatcher = $this->getDispatcher();
|
$eventDispatcher = $this->getDispatcher();
|
||||||
$logger = $this->getLogger();
|
$logger = $this->getLogger();
|
||||||
|
|
||||||
$transport = new EsmtpTransport('example.com', 25, null, null, $eventDispatcher, $logger);
|
$transport = new EsmtpTransport('localhost', 25, false, null, $eventDispatcher, $logger);
|
||||||
|
|
||||||
yield [
|
yield [
|
||||||
new Dsn('smtp', 'example.com'),
|
new Dsn('smtp', 'localhost'),
|
||||||
$transport,
|
$transport,
|
||||||
];
|
];
|
||||||
|
|
||||||
$transport = new EsmtpTransport('example.com', 99, 'ssl', 'login', $eventDispatcher, $logger);
|
$transport = new EsmtpTransport('example.com', 99, true, 'login', $eventDispatcher, $logger);
|
||||||
$transport->setUsername(self::USER);
|
$transport->setUsername(self::USER);
|
||||||
$transport->setPassword(self::PASSWORD);
|
$transport->setPassword(self::PASSWORD);
|
||||||
|
|
||||||
yield [
|
yield [
|
||||||
new Dsn('smtp', 'example.com', self::USER, self::PASSWORD, 99, ['encryption' => 'ssl', 'auth_mode' => 'login']),
|
new Dsn('smtps', 'example.com', self::USER, self::PASSWORD, 99, ['auth_mode' => 'login']),
|
||||||
|
$transport,
|
||||||
|
];
|
||||||
|
|
||||||
|
$transport = new EsmtpTransport('example.com', 465, true, null, $eventDispatcher, $logger);
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtps', 'example.com'),
|
||||||
|
$transport,
|
||||||
|
];
|
||||||
|
|
||||||
|
$transport = new EsmtpTransport('example.com', 465, true, null, $eventDispatcher, $logger);
|
||||||
|
|
||||||
|
yield [
|
||||||
|
new Dsn('smtp', 'example.com', '', '', 465),
|
||||||
$transport,
|
$transport,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Mailer\Tests\Transport\Smtp;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
|
||||||
|
|
||||||
|
class EsmtpTransportTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testName()
|
||||||
|
{
|
||||||
|
$t = new EsmtpTransport();
|
||||||
|
$this->assertEquals('smtp://localhost', $t->getName());
|
||||||
|
|
||||||
|
$t = new EsmtpTransport('example.com');
|
||||||
|
if (\defined('OPENSSL_VERSION_NUMBER')) {
|
||||||
|
$this->assertEquals('smtps://example.com', $t->getName());
|
||||||
|
} else {
|
||||||
|
$this->assertEquals('smtp://example.com', $t->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
$t = new EsmtpTransport('example.com', 2525);
|
||||||
|
$this->assertEquals('smtp://example.com:2525', $t->getName());
|
||||||
|
|
||||||
|
$t = new EsmtpTransport('example.com', 0, true);
|
||||||
|
$this->assertEquals('smtps://example.com', $t->getName());
|
||||||
|
|
||||||
|
$t = new EsmtpTransport('example.com', 0, false);
|
||||||
|
$this->assertEquals('smtp://example.com', $t->getName());
|
||||||
|
|
||||||
|
$t = new EsmtpTransport('example.com', 466, true);
|
||||||
|
$this->assertEquals('smtps://example.com:466', $t->getName());
|
||||||
|
}
|
||||||
|
}
|
@ -20,9 +20,9 @@ class SmtpTransportTest extends TestCase
|
|||||||
public function testName()
|
public function testName()
|
||||||
{
|
{
|
||||||
$t = new SmtpTransport();
|
$t = new SmtpTransport();
|
||||||
$this->assertEquals('smtp://localhost:25', $t->getName());
|
$this->assertEquals('smtps://localhost', $t->getName());
|
||||||
|
|
||||||
$t = new SmtpTransport((new SocketStream())->setHost('127.0.0.1')->setPort(2525));
|
$t = new SmtpTransport((new SocketStream())->setHost('127.0.0.1')->setPort(2525)->disableTls());
|
||||||
$this->assertEquals('smtp://127.0.0.1:2525', $t->getName());
|
$this->assertEquals('smtp://127.0.0.1:2525', $t->getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@ class SocketStreamTest extends TestCase
|
|||||||
'cafile' => __FILE__,
|
'cafile' => __FILE__,
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
$s->setEncryption('ssl');
|
|
||||||
$s->setHost('smtp.gmail.com');
|
$s->setHost('smtp.gmail.com');
|
||||||
$s->setPort(465);
|
$s->setPort(465);
|
||||||
$s->initialize();
|
$s->initialize();
|
||||||
|
@ -31,7 +31,7 @@ class EsmtpTransport extends SmtpTransport
|
|||||||
private $password = '';
|
private $password = '';
|
||||||
private $authMode;
|
private $authMode;
|
||||||
|
|
||||||
public function __construct(string $host = 'localhost', int $port = 25, string $encryption = null, string $authMode = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
public function __construct(string $host = 'localhost', int $port = 0, bool $tls = null, string $authMode = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
parent::__construct(null, $dispatcher, $logger);
|
parent::__construct(null, $dispatcher, $logger);
|
||||||
|
|
||||||
@ -44,11 +44,23 @@ class EsmtpTransport extends SmtpTransport
|
|||||||
|
|
||||||
/** @var SocketStream $stream */
|
/** @var SocketStream $stream */
|
||||||
$stream = $this->getStream();
|
$stream = $this->getStream();
|
||||||
|
|
||||||
|
if (null === $tls) {
|
||||||
|
if (465 === $port) {
|
||||||
|
$tls = true;
|
||||||
|
} else {
|
||||||
|
$tls = \defined('OPENSSL_VERSION_NUMBER') && 0 === $port && 'localhost' !== $host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$tls) {
|
||||||
|
$stream->disableTls();
|
||||||
|
}
|
||||||
|
if (0 === $port) {
|
||||||
|
$port = $tls ? 465 : 25;
|
||||||
|
}
|
||||||
|
|
||||||
$stream->setHost($host);
|
$stream->setHost($host);
|
||||||
$stream->setPort($port);
|
$stream->setPort($port);
|
||||||
if (null !== $encryption) {
|
|
||||||
$stream->setEncryption($encryption);
|
|
||||||
}
|
|
||||||
if (null !== $authMode) {
|
if (null !== $authMode) {
|
||||||
$this->setAuthMode($authMode);
|
$this->setAuthMode($authMode);
|
||||||
}
|
}
|
||||||
@ -105,13 +117,15 @@ class EsmtpTransport extends SmtpTransport
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$capabilities = $this->getCapabilities($response);
|
||||||
|
|
||||||
/** @var SocketStream $stream */
|
/** @var SocketStream $stream */
|
||||||
$stream = $this->getStream();
|
$stream = $this->getStream();
|
||||||
if ($stream->isTLS()) {
|
if (!$stream->isTLS() && \defined('OPENSSL_VERSION_NUMBER') && \array_key_exists('STARTTLS', $capabilities)) {
|
||||||
$this->executeCommand("STARTTLS\r\n", [220]);
|
$this->executeCommand("STARTTLS\r\n", [220]);
|
||||||
|
|
||||||
if (!$stream->startTLS()) {
|
if (!$stream->startTLS()) {
|
||||||
throw new TransportException('Unable to connect with TLS encryption.');
|
throw new TransportException('Unable to connect with STARTTLS.');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -123,7 +137,6 @@ class EsmtpTransport extends SmtpTransport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$capabilities = $this->getCapabilities($response);
|
|
||||||
if (\array_key_exists('AUTH', $capabilities)) {
|
if (\array_key_exists('AUTH', $capabilities)) {
|
||||||
$this->handleAuth($capabilities['AUTH']);
|
$this->handleAuth($capabilities['AUTH']);
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,12 @@ final class EsmtpTransportFactory extends AbstractTransportFactory
|
|||||||
{
|
{
|
||||||
public function create(Dsn $dsn): TransportInterface
|
public function create(Dsn $dsn): TransportInterface
|
||||||
{
|
{
|
||||||
$encryption = $dsn->getOption('encryption');
|
$tls = 'smtps' === $dsn->getScheme() ? true : null;
|
||||||
$authMode = $dsn->getOption('auth_mode');
|
$authMode = $dsn->getOption('auth_mode');
|
||||||
$port = $dsn->getPort(25);
|
$port = $dsn->getPort(0);
|
||||||
$host = $dsn->getHost();
|
$host = $dsn->getHost();
|
||||||
|
|
||||||
$transport = new EsmtpTransport($host, $port, $encryption, $authMode, $this->dispatcher, $this->logger);
|
$transport = new EsmtpTransport($host, $port, $tls, $authMode, $this->dispatcher, $this->logger);
|
||||||
|
|
||||||
if ($user = $dsn->getUser()) {
|
if ($user = $dsn->getUser()) {
|
||||||
$transport->setUsername($user);
|
$transport->setUsername($user);
|
||||||
@ -42,6 +42,6 @@ final class EsmtpTransportFactory extends AbstractTransportFactory
|
|||||||
|
|
||||||
public function supports(Dsn $dsn): bool
|
public function supports(Dsn $dsn): bool
|
||||||
{
|
{
|
||||||
return 'smtp' === $dsn->getScheme();
|
return 'smtp' === $dsn->getScheme() || 'smtps' === $dsn->getScheme();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,13 @@ class SmtpTransport extends AbstractTransport
|
|||||||
public function getName(): string
|
public function getName(): string
|
||||||
{
|
{
|
||||||
if ($this->stream instanceof SocketStream) {
|
if ($this->stream instanceof SocketStream) {
|
||||||
return sprintf('smtp://%s:%d', $this->stream->getHost(), $this->stream->getPort());
|
$name = sprintf('smtp%s://%s', ($tls = $this->stream->isTLS()) ? 's' : '', $this->stream->getHost());
|
||||||
|
$port = $this->stream->getPort();
|
||||||
|
if (!(25 === $port || ($tls && 465 === $port))) {
|
||||||
|
$name .= ':'.$port;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprintf('smtp://sendmail');
|
return sprintf('smtp://sendmail');
|
||||||
|
@ -25,10 +25,9 @@ final class SocketStream extends AbstractStream
|
|||||||
{
|
{
|
||||||
private $url;
|
private $url;
|
||||||
private $host = 'localhost';
|
private $host = 'localhost';
|
||||||
private $protocol = 'tcp';
|
private $port = 465;
|
||||||
private $port = 25;
|
|
||||||
private $timeout = 15;
|
private $timeout = 15;
|
||||||
private $tls = false;
|
private $tls = true;
|
||||||
private $sourceIp;
|
private $sourceIp;
|
||||||
private $streamContextOptions = [];
|
private $streamContextOptions = [];
|
||||||
|
|
||||||
@ -72,18 +71,11 @@ final class SocketStream extends AbstractStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the encryption type (tls or ssl).
|
* Sets the TLS/SSL on the socket (disables STARTTLS).
|
||||||
*/
|
*/
|
||||||
public function setEncryption(string $encryption): self
|
public function disableTls(): self
|
||||||
{
|
{
|
||||||
$encryption = strtolower($encryption);
|
|
||||||
if ('tls' === $encryption) {
|
|
||||||
$this->protocol = 'tcp';
|
|
||||||
$this->tls = true;
|
|
||||||
} else {
|
|
||||||
$this->protocol = $encryption;
|
|
||||||
$this->tls = false;
|
$this->tls = false;
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -128,8 +120,8 @@ final class SocketStream extends AbstractStream
|
|||||||
public function initialize(): void
|
public function initialize(): void
|
||||||
{
|
{
|
||||||
$this->url = $this->host.':'.$this->port;
|
$this->url = $this->host.':'.$this->port;
|
||||||
if ($this->protocol) {
|
if ($this->tls) {
|
||||||
$this->url = $this->protocol.'://'.$this->url;
|
$this->url = 'ssl://'.$this->url;
|
||||||
}
|
}
|
||||||
$options = [];
|
$options = [];
|
||||||
if ($this->sourceIp) {
|
if ($this->sourceIp) {
|
||||||
@ -138,9 +130,8 @@ final class SocketStream extends AbstractStream
|
|||||||
if ($this->streamContextOptions) {
|
if ($this->streamContextOptions) {
|
||||||
$options = array_merge($options, $this->streamContextOptions);
|
$options = array_merge($options, $this->streamContextOptions);
|
||||||
}
|
}
|
||||||
if ($this->isTLS()) {
|
// do it unconditionnally as it will be used by STARTTLS as well if supported
|
||||||
$options['ssl']['crypto_method'] = $options['ssl']['crypto_method'] ?? STREAM_CRYPTO_METHOD_TLS_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
|
$options['ssl']['crypto_method'] = $options['ssl']['crypto_method'] ?? STREAM_CRYPTO_METHOD_TLS_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
|
||||||
}
|
|
||||||
$streamContext = stream_context_create($options);
|
$streamContext = stream_context_create($options);
|
||||||
|
|
||||||
set_error_handler(function ($type, $msg) {
|
set_error_handler(function ($type, $msg) {
|
||||||
|
Reference in New Issue
Block a user