feature #33424 [Mailer] Change the DSN semantics (fabpot)
This PR was merged into the 4.4 branch.
Discussion
----------
[Mailer] Change the DSN semantics
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | no
| New feature? | yes
| BC breaks? | yes
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass? | yes <!-- please add some, will be required by reviewers -->
| Fixed tickets | n/a
| License | MIT
| Doc PR | https://github.com/symfony/symfony-docs/pull/12258
I'm not very satisfied with the current DSNs for the Mailer. First, the scheme/protocol should use the provider name, then, there is no way to change the host, which would be nice to debug more easily (using a requestb.in service for instance).
Before:
```
smtp://USERNAME:PASSWORD@mailgun
http://KEY:DOMAIN@mailgun
```
After:
```
mailgun+smtp://USERNAME:PASSWORD@default
mailgun+http://KEY:DOMAIN@default
# New
mailgun+http://KEY:DOMAIN@somewhere.com:99
```
SMTP DSNs did not change, but the special sendmail one did:
Before:
```
smtp://sendmail
```
After:
```
sendmail+smtp://default
```
And for the `null` transport:
Before:
```
smtp://null
```
After:
```
null://null
```
Commits
-------
469c989697
[Mailer] Change the DSN semantics
This commit is contained in:
commit
378abfae04
@ -4,7 +4,7 @@ imports:
|
||||
|
||||
framework:
|
||||
mailer:
|
||||
dsn: 'smtp://null'
|
||||
dsn: 'null://null'
|
||||
envelope:
|
||||
sender: sender@example.org
|
||||
recipients:
|
||||
|
@ -0,0 +1,48 @@
|
||||
<?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\Bridge\Amazon\Tests\Transport;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesApiTransport;
|
||||
|
||||
class SesApiTransportTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransportData
|
||||
*/
|
||||
public function testToString(SesApiTransport $transport, string $expected)
|
||||
{
|
||||
$this->assertSame($expected, (string) $transport);
|
||||
}
|
||||
|
||||
public function getTransportData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
new SesApiTransport('ACCESS_KEY', 'SECRET_KEY'),
|
||||
'ses+api://ACCESS_KEY@email.eu-west-1.amazonaws.com',
|
||||
],
|
||||
[
|
||||
new SesApiTransport('ACCESS_KEY', 'SECRET_KEY', 'us-east-1'),
|
||||
'ses+api://ACCESS_KEY@email.us-east-1.amazonaws.com',
|
||||
],
|
||||
[
|
||||
(new SesApiTransport('ACCESS_KEY', 'SECRET_KEY'))->setHost('example.com'),
|
||||
'ses+api://ACCESS_KEY@example.com',
|
||||
],
|
||||
[
|
||||
(new SesApiTransport('ACCESS_KEY', 'SECRET_KEY'))->setHost('example.com')->setPort(99),
|
||||
'ses+api://ACCESS_KEY@example.com:99',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
<?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\Bridge\Amazon\Tests\Transport;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesHttpTransport;
|
||||
|
||||
class SesHttpTransportTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransportData
|
||||
*/
|
||||
public function testToString(SesHttpTransport $transport, string $expected)
|
||||
{
|
||||
$this->assertSame($expected, (string) $transport);
|
||||
}
|
||||
|
||||
public function getTransportData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
new SesHttpTransport('ACCESS_KEY', 'SECRET_KEY'),
|
||||
'ses+https://ACCESS_KEY@email.eu-west-1.amazonaws.com',
|
||||
],
|
||||
[
|
||||
new SesHttpTransport('ACCESS_KEY', 'SECRET_KEY', 'us-east-1'),
|
||||
'ses+https://ACCESS_KEY@email.us-east-1.amazonaws.com',
|
||||
],
|
||||
[
|
||||
(new SesHttpTransport('ACCESS_KEY', 'SECRET_KEY'))->setHost('example.com'),
|
||||
'ses+https://ACCESS_KEY@example.com',
|
||||
],
|
||||
[
|
||||
(new SesHttpTransport('ACCESS_KEY', 'SECRET_KEY'))->setHost('example.com')->setPort(99),
|
||||
'ses+https://ACCESS_KEY@example.com:99',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -29,28 +29,33 @@ class SesTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function supportsProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('api', 'ses'),
|
||||
new Dsn('ses+api', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('http', 'ses'),
|
||||
new Dsn('ses+https', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'ses'),
|
||||
new Dsn('ses', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'ses'),
|
||||
new Dsn('ses+smtp', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'example.com'),
|
||||
false,
|
||||
new Dsn('ses+smtps', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('ses+smtp', 'example.com'),
|
||||
true,
|
||||
];
|
||||
}
|
||||
|
||||
@ -61,37 +66,52 @@ class SesTransportFactoryTest extends TransportFactoryTestCase
|
||||
$logger = $this->getLogger();
|
||||
|
||||
yield [
|
||||
new Dsn('api', 'ses', self::USER, self::PASSWORD),
|
||||
new Dsn('ses+api', 'default', self::USER, self::PASSWORD),
|
||||
new SesApiTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('api', 'ses', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
||||
new Dsn('ses+api', 'default', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
||||
new SesApiTransport(self::USER, self::PASSWORD, 'eu-west-1', $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('http', 'ses', self::USER, self::PASSWORD),
|
||||
new Dsn('ses+api', 'example.com', self::USER, self::PASSWORD, 8080),
|
||||
(new SesApiTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger))->setHost('example.com')->setPort(8080),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('ses+https', 'default', self::USER, self::PASSWORD),
|
||||
new SesHttpTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('http', 'ses', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
||||
new Dsn('ses', 'default', self::USER, self::PASSWORD),
|
||||
new SesHttpTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('ses+https', 'example.com', self::USER, self::PASSWORD, 8080),
|
||||
(new SesHttpTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger))->setHost('example.com')->setPort(8080),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('ses+https', 'default', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
||||
new SesHttpTransport(self::USER, self::PASSWORD, 'eu-west-1', $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'ses', self::USER, self::PASSWORD),
|
||||
new Dsn('ses+smtp', 'default', self::USER, self::PASSWORD),
|
||||
new SesSmtpTransport(self::USER, self::PASSWORD, null, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'ses', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
||||
new Dsn('ses+smtp', 'default', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
||||
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 Dsn('ses+smtps', 'default', self::USER, self::PASSWORD, null, ['region' => 'eu-west-1']),
|
||||
new SesSmtpTransport(self::USER, self::PASSWORD, 'eu-west-1', $dispatcher, $logger),
|
||||
];
|
||||
}
|
||||
@ -99,15 +119,15 @@ class SesTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function unsupportedSchemeProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('foo', 'ses', self::USER, self::PASSWORD),
|
||||
'The "foo" scheme is not supported for mailer "ses". Supported schemes are: "api", "http", "smtp", "smtps".',
|
||||
new Dsn('ses+foo', 'default', self::USER, self::PASSWORD),
|
||||
'The "ses+foo" scheme is not supported. Supported schemes for mailer "ses" are: "ses", "ses+api", "ses+https", "ses+smtp", "ses+smtps".',
|
||||
];
|
||||
}
|
||||
|
||||
public function incompleteDsnProvider(): iterable
|
||||
{
|
||||
yield [new Dsn('smtp', 'ses', self::USER)];
|
||||
yield [new Dsn('ses+smtp', 'default', self::USER)];
|
||||
|
||||
yield [new Dsn('smtp', 'ses', null, self::PASSWORD)];
|
||||
yield [new Dsn('ses+smtp', 'default', null, self::PASSWORD)];
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
class SesApiTransport extends AbstractApiTransport
|
||||
{
|
||||
private const ENDPOINT = 'https://email.%region%.amazonaws.com';
|
||||
private const HOST = 'email.%region%.amazonaws.com';
|
||||
|
||||
private $accessKey;
|
||||
private $secretKey;
|
||||
@ -45,7 +45,7 @@ class SesApiTransport extends AbstractApiTransport
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('api://%s@ses?region=%s', $this->accessKey, $this->region);
|
||||
return sprintf('ses+api://%s@%s', $this->accessKey, $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||
@ -53,8 +53,7 @@ class SesApiTransport extends AbstractApiTransport
|
||||
$date = gmdate('D, d M Y H:i:s e');
|
||||
$auth = sprintf('AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=HmacSHA256,Signature=%s', $this->accessKey, $this->getSignature($date));
|
||||
|
||||
$endpoint = str_replace('%region%', $this->region, self::ENDPOINT);
|
||||
$response = $this->client->request('POST', $endpoint, [
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint(), [
|
||||
'headers' => [
|
||||
'X-Amzn-Authorization' => $auth,
|
||||
'Date' => $date,
|
||||
@ -72,6 +71,11 @@ class SesApiTransport extends AbstractApiTransport
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function getEndpoint(): ?string
|
||||
{
|
||||
return ($this->host ?: str_replace('%region%', $this->region, self::HOST)).($this->port ? ':'.$this->port : '');
|
||||
}
|
||||
|
||||
private function getSignature(string $string): string
|
||||
{
|
||||
return base64_encode(hash_hmac('sha256', $string, $this->secretKey, true));
|
||||
|
@ -24,7 +24,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
class SesHttpTransport extends AbstractHttpTransport
|
||||
{
|
||||
private const ENDPOINT = 'https://email.%region%.amazonaws.com';
|
||||
private const HOST = 'email.%region%.amazonaws.com';
|
||||
|
||||
private $accessKey;
|
||||
private $secretKey;
|
||||
@ -44,7 +44,7 @@ class SesHttpTransport extends AbstractHttpTransport
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('http://%s@ses?region=%s', $this->accessKey, $this->region);
|
||||
return sprintf('ses+https://%s@%s', $this->accessKey, $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendHttp(SentMessage $message): ResponseInterface
|
||||
@ -52,8 +52,7 @@ class SesHttpTransport extends AbstractHttpTransport
|
||||
$date = gmdate('D, d M Y H:i:s e');
|
||||
$auth = sprintf('AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=HmacSHA256,Signature=%s', $this->accessKey, $this->getSignature($date));
|
||||
|
||||
$endpoint = str_replace('%region%', $this->region, self::ENDPOINT);
|
||||
$response = $this->client->request('POST', $endpoint, [
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint(), [
|
||||
'headers' => [
|
||||
'X-Amzn-Authorization' => $auth,
|
||||
'Date' => $date,
|
||||
@ -73,6 +72,11 @@ class SesHttpTransport extends AbstractHttpTransport
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function getEndpoint(): ?string
|
||||
{
|
||||
return ($this->host ?: str_replace('%region%', $this->region, self::HOST)).($this->port ? ':'.$this->port : '');
|
||||
}
|
||||
|
||||
private function getSignature(string $string): string
|
||||
{
|
||||
return base64_encode(hash_hmac('sha256', $string, $this->secretKey, true));
|
||||
|
@ -27,24 +27,26 @@ final class SesTransportFactory extends AbstractTransportFactory
|
||||
$user = $this->getUser($dsn);
|
||||
$password = $this->getPassword($dsn);
|
||||
$region = $dsn->getOption('region');
|
||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||
$port = $dsn->getPort();
|
||||
|
||||
if ('api' === $scheme) {
|
||||
return new SesApiTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger);
|
||||
if ('ses+api' === $scheme) {
|
||||
return (new SesApiTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port);
|
||||
}
|
||||
|
||||
if ('http' === $scheme) {
|
||||
return new SesHttpTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger);
|
||||
if ('ses+https' === $scheme || 'ses' === $scheme) {
|
||||
return (new SesHttpTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port);
|
||||
}
|
||||
|
||||
if ('smtp' === $scheme || 'smtps' === $scheme) {
|
||||
if ('ses+smtp' === $scheme || 'ses+smtps' === $scheme) {
|
||||
return new SesSmtpTransport($user, $password, $region, $this->dispatcher, $this->logger);
|
||||
}
|
||||
|
||||
throw new UnsupportedSchemeException($dsn, ['api', 'http', 'smtp', 'smtps']);
|
||||
throw new UnsupportedSchemeException($dsn, 'ses', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return 'ses' === $dsn->getHost();
|
||||
return ['ses', 'ses+api', 'ses+https', 'ses+smtp', 'ses+smtps'];
|
||||
}
|
||||
}
|
||||
|
@ -18,30 +18,40 @@ class GmailTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function supportsProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('smtp', 'gmail'),
|
||||
new Dsn('gmail', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'gmail'),
|
||||
new Dsn('gmail+smtp', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'example.com'),
|
||||
false,
|
||||
new Dsn('gmail+smtps', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('gmail+smtp', 'example.com'),
|
||||
true,
|
||||
];
|
||||
}
|
||||
|
||||
public function createProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('smtp', 'gmail', self::USER, self::PASSWORD),
|
||||
new Dsn('gmail', 'default', self::USER, self::PASSWORD),
|
||||
new GmailSmtpTransport(self::USER, self::PASSWORD, $this->getDispatcher(), $this->getLogger()),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'gmail', self::USER, self::PASSWORD),
|
||||
new Dsn('gmail+smtp', 'default', self::USER, self::PASSWORD),
|
||||
new GmailSmtpTransport(self::USER, self::PASSWORD, $this->getDispatcher(), $this->getLogger()),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('gmail+smtps', 'default', self::USER, self::PASSWORD),
|
||||
new GmailSmtpTransport(self::USER, self::PASSWORD, $this->getDispatcher(), $this->getLogger()),
|
||||
];
|
||||
}
|
||||
@ -49,15 +59,15 @@ class GmailTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function unsupportedSchemeProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('foo', 'gmail', self::USER, self::PASSWORD),
|
||||
'The "foo" scheme is not supported for mailer "gmail". Supported schemes are: "smtp", "smtps".',
|
||||
new Dsn('gmail+foo', 'default', self::USER, self::PASSWORD),
|
||||
'The "gmail+foo" scheme is not supported. Supported schemes for mailer "gmail" are: "gmail", "gmail+smtp", "gmail+smtps".',
|
||||
];
|
||||
}
|
||||
|
||||
public function incompleteDsnProvider(): iterable
|
||||
{
|
||||
yield [new Dsn('smtp', 'gmail', self::USER)];
|
||||
yield [new Dsn('gmail+smtp', 'default', self::USER)];
|
||||
|
||||
yield [new Dsn('smtp', 'gmail', null, self::PASSWORD)];
|
||||
yield [new Dsn('gmail+smtp', 'default', null, self::PASSWORD)];
|
||||
}
|
||||
}
|
||||
|
@ -23,15 +23,15 @@ final class GmailTransportFactory extends AbstractTransportFactory
|
||||
{
|
||||
public function create(Dsn $dsn): TransportInterface
|
||||
{
|
||||
if ('smtp' === $dsn->getScheme() || 'smtps' === $dsn->getScheme()) {
|
||||
if (\in_array($dsn->getScheme(), $this->getSupportedSchemes())) {
|
||||
return new GmailSmtpTransport($this->getUser($dsn), $this->getPassword($dsn), $this->dispatcher, $this->logger);
|
||||
}
|
||||
|
||||
throw new UnsupportedSchemeException($dsn, ['smtp', 'smtps']);
|
||||
throw new UnsupportedSchemeException($dsn, 'gmail', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return 'gmail' === $dsn->getHost();
|
||||
return ['gmail', 'gmail+smtp', 'gmail+smtps'];
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
<?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\Bridge\Mailchimp\Tests\Transport;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillApiTransport;
|
||||
|
||||
class MandrillApiTransportTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransportData
|
||||
*/
|
||||
public function testToString(MandrillApiTransport $transport, string $expected)
|
||||
{
|
||||
$this->assertSame($expected, (string) $transport);
|
||||
}
|
||||
|
||||
public function getTransportData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
new MandrillApiTransport('KEY'),
|
||||
'mandrill+api://mandrillapp.com',
|
||||
],
|
||||
[
|
||||
(new MandrillApiTransport('KEY'))->setHost('example.com'),
|
||||
'mandrill+api://example.com',
|
||||
],
|
||||
[
|
||||
(new MandrillApiTransport('KEY'))->setHost('example.com')->setPort(99),
|
||||
'mandrill+api://example.com:99',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?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\Bridge\Mailchimp\Tests\Transport;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillHttpTransport;
|
||||
|
||||
class MandrillHttpTransportTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransportData
|
||||
*/
|
||||
public function testToString(MandrillHttpTransport $transport, string $expected)
|
||||
{
|
||||
$this->assertSame($expected, (string) $transport);
|
||||
}
|
||||
|
||||
public function getTransportData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
new MandrillHttpTransport('KEY'),
|
||||
'mandrill+https://mandrillapp.com',
|
||||
],
|
||||
[
|
||||
(new MandrillHttpTransport('KEY'))->setHost('example.com'),
|
||||
'mandrill+https://example.com',
|
||||
],
|
||||
[
|
||||
(new MandrillHttpTransport('KEY'))->setHost('example.com')->setPort(99),
|
||||
'mandrill+https://example.com:99',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -29,28 +29,33 @@ class MandrillTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function supportsProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('api', 'mandrill'),
|
||||
new Dsn('mandrill', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('http', 'mandrill'),
|
||||
new Dsn('mandrill+api', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'mandrill'),
|
||||
new Dsn('mandrill+https', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'mandrill'),
|
||||
new Dsn('mandrill+smtp', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'example.com'),
|
||||
false,
|
||||
new Dsn('mandrill+smtps', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('mandrill+smtp', 'example.com'),
|
||||
true,
|
||||
];
|
||||
}
|
||||
|
||||
@ -61,22 +66,37 @@ class MandrillTransportFactoryTest extends TransportFactoryTestCase
|
||||
$logger = $this->getLogger();
|
||||
|
||||
yield [
|
||||
new Dsn('api', 'mandrill', self::USER),
|
||||
new Dsn('mandrill+api', 'default', self::USER),
|
||||
new MandrillApiTransport(self::USER, $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('http', 'mandrill', self::USER),
|
||||
new Dsn('mandrill+api', 'example.com', self::USER, '', 8080),
|
||||
(new MandrillApiTransport(self::USER, $client, $dispatcher, $logger))->setHost('example.com')->setPort(8080),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('mandrill', 'default', self::USER),
|
||||
new MandrillHttpTransport(self::USER, $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'mandrill', self::USER, self::PASSWORD),
|
||||
new Dsn('mandrill+https', 'default', self::USER),
|
||||
new MandrillHttpTransport(self::USER, $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('mandrill+https', 'example.com', self::USER, '', 8080),
|
||||
(new MandrillHttpTransport(self::USER, $client, $dispatcher, $logger))->setHost('example.com')->setPort(8080),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('mandrill+smtp', 'default', self::USER, self::PASSWORD),
|
||||
new MandrillSmtpTransport(self::USER, self::PASSWORD, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'mandrill', self::USER, self::PASSWORD),
|
||||
new Dsn('mandrill+smtps', 'default', self::USER, self::PASSWORD),
|
||||
new MandrillSmtpTransport(self::USER, self::PASSWORD, $dispatcher, $logger),
|
||||
];
|
||||
}
|
||||
@ -84,15 +104,15 @@ class MandrillTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function unsupportedSchemeProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('foo', 'mandrill', self::USER),
|
||||
'The "foo" scheme is not supported for mailer "mandrill". Supported schemes are: "api", "http", "smtp", "smtps".',
|
||||
new Dsn('mandrill+foo', 'default', self::USER),
|
||||
'The "mandrill+foo" scheme is not supported. Supported schemes for mailer "mandrill" are: "mandrill", "mandrill+api", "mandrill+https", "mandrill+smtp", "mandrill+smtps".',
|
||||
];
|
||||
}
|
||||
|
||||
public function incompleteDsnProvider(): iterable
|
||||
{
|
||||
yield [new Dsn('api', 'mandrill')];
|
||||
yield [new Dsn('mandrill+api', 'default')];
|
||||
|
||||
yield [new Dsn('smtp', 'mandrill', self::USER)];
|
||||
yield [new Dsn('mandrill+smtp', 'default', self::USER)];
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
class MandrillApiTransport extends AbstractApiTransport
|
||||
{
|
||||
private const ENDPOINT = 'https://mandrillapp.com/api/1.0/messages/send.json';
|
||||
private const HOST = 'mandrillapp.com';
|
||||
|
||||
private $key;
|
||||
|
||||
@ -38,12 +38,12 @@ class MandrillApiTransport extends AbstractApiTransport
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('api://mandrill');
|
||||
return sprintf('mandrill+api://%s', $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||
{
|
||||
$response = $this->client->request('POST', self::ENDPOINT, [
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/api/1.0/messages/send.json', [
|
||||
'json' => $this->getPayload($email, $envelope),
|
||||
]);
|
||||
|
||||
@ -59,6 +59,11 @@ class MandrillApiTransport extends AbstractApiTransport
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function getEndpoint(): ?string
|
||||
{
|
||||
return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : '');
|
||||
}
|
||||
|
||||
private function getPayload(Email $email, SmtpEnvelope $envelope): array
|
||||
{
|
||||
$payload = [
|
||||
|
@ -24,7 +24,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
class MandrillHttpTransport extends AbstractHttpTransport
|
||||
{
|
||||
private const ENDPOINT = 'https://mandrillapp.com/api/1.0/messages/send-raw.json';
|
||||
private const HOST = 'mandrillapp.com';
|
||||
private $key;
|
||||
|
||||
public function __construct(string $key, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||
@ -36,13 +36,13 @@ class MandrillHttpTransport extends AbstractHttpTransport
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('http://mandrill');
|
||||
return sprintf('mandrill+https://%s', $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendHttp(SentMessage $message): ResponseInterface
|
||||
{
|
||||
$envelope = $message->getEnvelope();
|
||||
$response = $this->client->request('POST', self::ENDPOINT, [
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/api/1.0/messages/send-raw.json', [
|
||||
'json' => [
|
||||
'key' => $this->key,
|
||||
'to' => $this->stringifyAddresses($envelope->getRecipients()),
|
||||
@ -62,4 +62,9 @@ class MandrillHttpTransport extends AbstractHttpTransport
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function getEndpoint(): ?string
|
||||
{
|
||||
return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : '');
|
||||
}
|
||||
}
|
||||
|
@ -25,26 +25,28 @@ final class MandrillTransportFactory extends AbstractTransportFactory
|
||||
{
|
||||
$scheme = $dsn->getScheme();
|
||||
$user = $this->getUser($dsn);
|
||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||
$port = $dsn->getPort();
|
||||
|
||||
if ('api' === $scheme) {
|
||||
return new MandrillApiTransport($user, $this->client, $this->dispatcher, $this->logger);
|
||||
if ('mandrill+api' === $scheme) {
|
||||
return (new MandrillApiTransport($user, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port);
|
||||
}
|
||||
|
||||
if ('http' === $scheme) {
|
||||
return new MandrillHttpTransport($user, $this->client, $this->dispatcher, $this->logger);
|
||||
if ('mandrill+https' === $scheme || 'mandrill' === $scheme) {
|
||||
return (new MandrillHttpTransport($user, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port);
|
||||
}
|
||||
|
||||
if ('smtp' === $scheme || 'smtps' === $scheme) {
|
||||
if ('mandrill+smtp' === $scheme || 'mandrill+smtps' === $scheme) {
|
||||
$password = $this->getPassword($dsn);
|
||||
|
||||
return new MandrillSmtpTransport($user, $password, $this->dispatcher, $this->logger);
|
||||
}
|
||||
|
||||
throw new UnsupportedSchemeException($dsn, ['api', 'http', 'smtp', 'smtps']);
|
||||
throw new UnsupportedSchemeException($dsn, 'mandrill', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return 'mandrill' === $dsn->getHost();
|
||||
return ['mandrill', 'mandrill+api', 'mandrill+https', 'mandrill+smtp', 'mandrill+smtps'];
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
<?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\Bridge\Mailgun\Tests\Transport;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunApiTransport;
|
||||
|
||||
class MailgunApiTransportTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransportData
|
||||
*/
|
||||
public function testToString(MailgunApiTransport $transport, string $expected)
|
||||
{
|
||||
$this->assertSame($expected, (string) $transport);
|
||||
}
|
||||
|
||||
public function getTransportData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
new MailgunApiTransport('ACCESS_KEY', 'DOMAIN'),
|
||||
'mailgun+api://api.mailgun.net?domain=DOMAIN',
|
||||
],
|
||||
[
|
||||
new MailgunApiTransport('ACCESS_KEY', 'DOMAIN', 'us-east-1'),
|
||||
'mailgun+api://api.us-east-1.mailgun.net?domain=DOMAIN',
|
||||
],
|
||||
[
|
||||
(new MailgunApiTransport('ACCESS_KEY', 'DOMAIN'))->setHost('example.com'),
|
||||
'mailgun+api://example.com?domain=DOMAIN',
|
||||
],
|
||||
[
|
||||
(new MailgunApiTransport('ACCESS_KEY', 'DOMAIN'))->setHost('example.com')->setPort(99),
|
||||
'mailgun+api://example.com:99?domain=DOMAIN',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
<?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\Bridge\Mailgun\Tests\Transport;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunHttpTransport;
|
||||
|
||||
class MailgunHttpTransportTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransportData
|
||||
*/
|
||||
public function testToString(MailgunHttpTransport $transport, string $expected)
|
||||
{
|
||||
$this->assertSame($expected, (string) $transport);
|
||||
}
|
||||
|
||||
public function getTransportData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
new MailgunHttpTransport('ACCESS_KEY', 'DOMAIN'),
|
||||
'mailgun+https://api.mailgun.net?domain=DOMAIN',
|
||||
],
|
||||
[
|
||||
new MailgunHttpTransport('ACCESS_KEY', 'DOMAIN', 'us-east-1'),
|
||||
'mailgun+https://api.us-east-1.mailgun.net?domain=DOMAIN',
|
||||
],
|
||||
[
|
||||
(new MailgunHttpTransport('ACCESS_KEY', 'DOMAIN'))->setHost('example.com'),
|
||||
'mailgun+https://example.com?domain=DOMAIN',
|
||||
],
|
||||
[
|
||||
(new MailgunHttpTransport('ACCESS_KEY', 'DOMAIN'))->setHost('example.com')->setPort(99),
|
||||
'mailgun+https://example.com:99?domain=DOMAIN',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -29,28 +29,33 @@ class MailgunTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function supportsProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('api', 'mailgun'),
|
||||
new Dsn('mailgun+api', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('http', 'mailgun'),
|
||||
new Dsn('mailgun', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'mailgun'),
|
||||
new Dsn('mailgun+https', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'mailgun'),
|
||||
new Dsn('mailgun+smtp', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'example.com'),
|
||||
false,
|
||||
new Dsn('mailgun+smtps', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('mailgun+smtp', 'example.com'),
|
||||
true,
|
||||
];
|
||||
}
|
||||
|
||||
@ -61,27 +66,42 @@ class MailgunTransportFactoryTest extends TransportFactoryTestCase
|
||||
$logger = $this->getLogger();
|
||||
|
||||
yield [
|
||||
new Dsn('api', 'mailgun', self::USER, self::PASSWORD),
|
||||
new Dsn('mailgun+api', 'default', self::USER, self::PASSWORD),
|
||||
new MailgunApiTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('api', 'mailgun', self::USER, self::PASSWORD, null, ['region' => 'eu']),
|
||||
new Dsn('mailgun+api', 'default', self::USER, self::PASSWORD, null, ['region' => 'eu']),
|
||||
new MailgunApiTransport(self::USER, self::PASSWORD, 'eu', $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('http', 'mailgun', self::USER, self::PASSWORD),
|
||||
new Dsn('mailgun+api', 'example.com', self::USER, self::PASSWORD, 8080),
|
||||
(new MailgunApiTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger))->setHost('example.com')->setPort(8080),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('mailgun', 'default', self::USER, self::PASSWORD),
|
||||
new MailgunHttpTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'mailgun', self::USER, self::PASSWORD),
|
||||
new Dsn('mailgun+https', 'default', self::USER, self::PASSWORD),
|
||||
new MailgunHttpTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('mailgun+https', 'example.com', self::USER, self::PASSWORD, 8080),
|
||||
(new MailgunHttpTransport(self::USER, self::PASSWORD, null, $client, $dispatcher, $logger))->setHost('example.com')->setPort(8080),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('mailgun+smtp', 'default', self::USER, self::PASSWORD),
|
||||
new MailgunSmtpTransport(self::USER, self::PASSWORD, null, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'mailgun', self::USER, self::PASSWORD),
|
||||
new Dsn('mailgun+smtps', 'default', self::USER, self::PASSWORD),
|
||||
new MailgunSmtpTransport(self::USER, self::PASSWORD, null, $dispatcher, $logger),
|
||||
];
|
||||
}
|
||||
@ -89,15 +109,15 @@ class MailgunTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function unsupportedSchemeProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('foo', 'mailgun', self::USER, self::PASSWORD),
|
||||
'The "foo" scheme is not supported for mailer "mailgun". Supported schemes are: "api", "http", "smtp", "smtps".',
|
||||
new Dsn('mailgun+foo', 'default', self::USER, self::PASSWORD),
|
||||
'The "mailgun+foo" scheme is not supported. Supported schemes for mailer "mailgun" are: "mailgun", "mailgun+api", "mailgun+https", "mailgun+smtp", "mailgun+smtps".',
|
||||
];
|
||||
}
|
||||
|
||||
public function incompleteDsnProvider(): iterable
|
||||
{
|
||||
yield [new Dsn('api', 'mailgun', self::USER)];
|
||||
yield [new Dsn('mailgun+api', 'default', self::USER)];
|
||||
|
||||
yield [new Dsn('api', 'mailgun', null, self::PASSWORD)];
|
||||
yield [new Dsn('mailgun+api', 'default', null, self::PASSWORD)];
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
class MailgunApiTransport extends AbstractApiTransport
|
||||
{
|
||||
private const ENDPOINT = 'https://api.%region_dot%mailgun.net/v3/%domain%/messages';
|
||||
private const HOST = 'api.%region_dot%mailgun.net';
|
||||
|
||||
private $key;
|
||||
private $domain;
|
||||
@ -43,7 +43,7 @@ class MailgunApiTransport extends AbstractApiTransport
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('api://%s@mailgun?region=%s', $this->domain, $this->region);
|
||||
return sprintf('mailgun+api://%s?domain=%s', $this->getEndpoint(), $this->domain);
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||
@ -54,8 +54,8 @@ class MailgunApiTransport extends AbstractApiTransport
|
||||
$headers[] = $header->toString();
|
||||
}
|
||||
|
||||
$endpoint = str_replace(['%domain%', '%region_dot%'], [urlencode($this->domain), 'us' !== ($this->region ?: 'us') ? $this->region.'.' : ''], self::ENDPOINT);
|
||||
$response = $this->client->request('POST', $endpoint, [
|
||||
$endpoint = str_replace('%domain%', urlencode($this->domain), $this->getEndpoint()).'/v3/%domain%/messages';
|
||||
$response = $this->client->request('POST', 'https://'.$endpoint, [
|
||||
'auth_basic' => 'api:'.$this->key,
|
||||
'headers' => $headers,
|
||||
'body' => $body->bodyToIterable(),
|
||||
@ -137,4 +137,11 @@ class MailgunApiTransport extends AbstractApiTransport
|
||||
|
||||
return [$attachments, $inlines, $html];
|
||||
}
|
||||
|
||||
private function getEndpoint(): ?string
|
||||
{
|
||||
$host = $this->host ?: str_replace('%region_dot%', 'us' !== ($this->region ?: 'us') ? $this->region.'.' : '', self::HOST);
|
||||
|
||||
return $host.($this->port ? ':'.$this->port : '');
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
class MailgunHttpTransport extends AbstractHttpTransport
|
||||
{
|
||||
private const ENDPOINT = 'https://api.%region_dot%mailgun.net/v3/%domain%/messages.mime';
|
||||
private const HOST = 'api.%region_dot%mailgun.net';
|
||||
|
||||
private $key;
|
||||
private $domain;
|
||||
private $region;
|
||||
@ -42,7 +43,7 @@ class MailgunHttpTransport extends AbstractHttpTransport
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('http://%s@mailgun?region=%s', $this->domain, $this->region);
|
||||
return sprintf('mailgun+https://%s?domain=%s', $this->getEndpoint(), $this->domain);
|
||||
}
|
||||
|
||||
protected function doSendHttp(SentMessage $message): ResponseInterface
|
||||
@ -55,8 +56,9 @@ class MailgunHttpTransport extends AbstractHttpTransport
|
||||
foreach ($body->getPreparedHeaders()->all() as $header) {
|
||||
$headers[] = $header->toString();
|
||||
}
|
||||
$endpoint = str_replace(['%domain%', '%region_dot%'], [urlencode($this->domain), 'us' !== ($this->region ?: 'us') ? $this->region.'.' : ''], self::ENDPOINT);
|
||||
$response = $this->client->request('POST', $endpoint, [
|
||||
|
||||
$endpoint = str_replace('%domain%', urlencode($this->domain), $this->getEndpoint()).'/v3/%domain%/messages.mime';
|
||||
$response = $this->client->request('POST', 'https://'.$endpoint, [
|
||||
'auth_basic' => 'api:'.$this->key,
|
||||
'headers' => $headers,
|
||||
'body' => $body->bodyToIterable(),
|
||||
@ -70,4 +72,11 @@ class MailgunHttpTransport extends AbstractHttpTransport
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function getEndpoint(): ?string
|
||||
{
|
||||
$host = $this->host ?: str_replace('%region_dot%', 'us' !== ($this->region ?: 'us') ? $this->region.'.' : '', self::HOST);
|
||||
|
||||
return $host.($this->port ? ':'.$this->port : '');
|
||||
}
|
||||
}
|
||||
|
@ -27,24 +27,26 @@ final class MailgunTransportFactory extends AbstractTransportFactory
|
||||
$user = $this->getUser($dsn);
|
||||
$password = $this->getPassword($dsn);
|
||||
$region = $dsn->getOption('region');
|
||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||
$port = $dsn->getPort();
|
||||
|
||||
if ('api' === $scheme) {
|
||||
return new MailgunApiTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger);
|
||||
if ('mailgun+api' === $scheme) {
|
||||
return (new MailgunApiTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port);
|
||||
}
|
||||
|
||||
if ('http' === $scheme) {
|
||||
return new MailgunHttpTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger);
|
||||
if ('mailgun+https' === $scheme || 'mailgun' === $scheme) {
|
||||
return (new MailgunHttpTransport($user, $password, $region, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port);
|
||||
}
|
||||
|
||||
if ('smtp' === $scheme || 'smtps' === $scheme) {
|
||||
if ('mailgun+smtp' === $scheme || 'mailgun+smtps' === $scheme) {
|
||||
return new MailgunSmtpTransport($user, $password, $region, $this->dispatcher, $this->logger);
|
||||
}
|
||||
|
||||
throw new UnsupportedSchemeException($dsn, ['api', 'http', 'smtp', 'smtps']);
|
||||
throw new UnsupportedSchemeException($dsn, 'mailgun', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return 'mailgun' === $dsn->getHost();
|
||||
return ['mailgun', 'mailgun+api', 'mailgun+https', 'mailgun+smtp', 'mailgun+smtps'];
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
<?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\Bridge\Postmark\Tests\Transport;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkApiTransport;
|
||||
|
||||
class PostmarkApiTransportTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransportData
|
||||
*/
|
||||
public function testToString(PostmarkApiTransport $transport, string $expected)
|
||||
{
|
||||
$this->assertSame($expected, (string) $transport);
|
||||
}
|
||||
|
||||
public function getTransportData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
new PostmarkApiTransport('KEY'),
|
||||
'postmark+api://api.postmarkapp.com',
|
||||
],
|
||||
[
|
||||
(new PostmarkApiTransport('KEY'))->setHost('example.com'),
|
||||
'postmark+api://example.com',
|
||||
],
|
||||
[
|
||||
(new PostmarkApiTransport('KEY'))->setHost('example.com')->setPort(99),
|
||||
'postmark+api://example.com:99',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -28,23 +28,28 @@ class PostmarkTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function supportsProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('api', 'postmark'),
|
||||
new Dsn('postmark+api', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'postmark'),
|
||||
new Dsn('postmark', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'postmark'),
|
||||
new Dsn('postmark+smtp', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'example.com'),
|
||||
false,
|
||||
new Dsn('postmark+smtps', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('postmark+smtp', 'example.com'),
|
||||
true,
|
||||
];
|
||||
}
|
||||
|
||||
@ -54,17 +59,27 @@ class PostmarkTransportFactoryTest extends TransportFactoryTestCase
|
||||
$logger = $this->getLogger();
|
||||
|
||||
yield [
|
||||
new Dsn('api', 'postmark', self::USER),
|
||||
new Dsn('postmark+api', 'default', self::USER),
|
||||
new PostmarkApiTransport(self::USER, $this->getClient(), $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'postmark', self::USER),
|
||||
new Dsn('postmark+api', 'example.com', self::USER, '', 8080),
|
||||
(new PostmarkApiTransport(self::USER, $this->getClient(), $dispatcher, $logger))->setHost('example.com')->setPort(8080),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('postmark', 'default', self::USER),
|
||||
new PostmarkSmtpTransport(self::USER, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'postmark', self::USER),
|
||||
new Dsn('postmark+smtp', 'default', self::USER),
|
||||
new PostmarkSmtpTransport(self::USER, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('postmark+smtps', 'default', self::USER),
|
||||
new PostmarkSmtpTransport(self::USER, $dispatcher, $logger),
|
||||
];
|
||||
}
|
||||
@ -72,13 +87,13 @@ class PostmarkTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function unsupportedSchemeProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('foo', 'postmark', self::USER),
|
||||
'The "foo" scheme is not supported for mailer "postmark". Supported schemes are: "api", "smtp", "smtps".',
|
||||
new Dsn('postmark+foo', 'default', self::USER),
|
||||
'The "postmark+foo" scheme is not supported. Supported schemes for mailer "postmark" are: "postmark", "postmark+api", "postmark+smtp", "postmark+smtps".',
|
||||
];
|
||||
}
|
||||
|
||||
public function incompleteDsnProvider(): iterable
|
||||
{
|
||||
yield [new Dsn('api', 'postmark')];
|
||||
yield [new Dsn('postmark+api', 'default')];
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
class PostmarkApiTransport extends AbstractApiTransport
|
||||
{
|
||||
private const ENDPOINT = 'http://api.postmarkapp.com/email';
|
||||
private const HOST = 'api.postmarkapp.com';
|
||||
|
||||
private $key;
|
||||
|
||||
@ -38,12 +38,12 @@ class PostmarkApiTransport extends AbstractApiTransport
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('api://postmark');
|
||||
return sprintf('postmark+api://%s', $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||
{
|
||||
$response = $this->client->request('POST', self::ENDPOINT, [
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/email', [
|
||||
'headers' => [
|
||||
'Accept' => 'application/json',
|
||||
'X-Postmark-Server-Token' => $this->key,
|
||||
@ -111,4 +111,9 @@ class PostmarkApiTransport extends AbstractApiTransport
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
private function getEndpoint(): ?string
|
||||
{
|
||||
return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : '');
|
||||
}
|
||||
}
|
||||
|
@ -26,19 +26,22 @@ final class PostmarkTransportFactory extends AbstractTransportFactory
|
||||
$scheme = $dsn->getScheme();
|
||||
$user = $this->getUser($dsn);
|
||||
|
||||
if ('api' === $scheme) {
|
||||
return new PostmarkApiTransport($user, $this->client, $this->dispatcher, $this->logger);
|
||||
if ('postmark+api' === $scheme) {
|
||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||
$port = $dsn->getPort();
|
||||
|
||||
return (new PostmarkApiTransport($user, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port);
|
||||
}
|
||||
|
||||
if ('smtp' === $scheme || 'smtps' === $scheme) {
|
||||
if ('postmark+smtp' === $scheme || 'postmark+smtps' === $scheme || 'postmark' === $scheme) {
|
||||
return new PostmarkSmtpTransport($user, $this->dispatcher, $this->logger);
|
||||
}
|
||||
|
||||
throw new UnsupportedSchemeException($dsn, ['api', 'smtp', 'smtps']);
|
||||
throw new UnsupportedSchemeException($dsn, 'postmark', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return 'postmark' === $dsn->getHost();
|
||||
return ['postmark', 'postmark+api', 'postmark+smtp', 'postmark+smtps'];
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,32 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
|
||||
class SendgridApiTransportTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransportData
|
||||
*/
|
||||
public function testToString(SendgridApiTransport $transport, string $expected)
|
||||
{
|
||||
$this->assertSame($expected, (string) $transport);
|
||||
}
|
||||
|
||||
public function getTransportData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
new SendgridApiTransport('KEY'),
|
||||
'sendgrid+api://api.sendgrid.com',
|
||||
],
|
||||
[
|
||||
(new SendgridApiTransport('KEY'))->setHost('example.com'),
|
||||
'sendgrid+api://example.com',
|
||||
],
|
||||
[
|
||||
(new SendgridApiTransport('KEY'))->setHost('example.com')->setPort(99),
|
||||
'sendgrid+api://example.com:99',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function testSend()
|
||||
{
|
||||
$email = new Email();
|
||||
|
@ -28,23 +28,28 @@ class SendgridTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function supportsProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('api', 'sendgrid'),
|
||||
new Dsn('sendgrid+api', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'sendgrid'),
|
||||
new Dsn('sendgrid', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'sendgrid'),
|
||||
new Dsn('sendgrid+smtp', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'example.com'),
|
||||
false,
|
||||
new Dsn('sendgrid+smtps', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('sendgrid+smtp', 'example.com'),
|
||||
true,
|
||||
];
|
||||
}
|
||||
|
||||
@ -54,17 +59,27 @@ class SendgridTransportFactoryTest extends TransportFactoryTestCase
|
||||
$logger = $this->getLogger();
|
||||
|
||||
yield [
|
||||
new Dsn('api', 'sendgrid', self::USER),
|
||||
new Dsn('sendgrid+api', 'default', self::USER),
|
||||
new SendgridApiTransport(self::USER, $this->getClient(), $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'sendgrid', self::USER),
|
||||
new Dsn('sendgrid+api', 'example.com', self::USER, '', 8080),
|
||||
(new SendgridApiTransport(self::USER, $this->getClient(), $dispatcher, $logger))->setHost('example.com')->setPort(8080),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('sendgrid', 'default', self::USER),
|
||||
new SendgridSmtpTransport(self::USER, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtps', 'sendgrid', self::USER),
|
||||
new Dsn('sendgrid+smtp', 'default', self::USER),
|
||||
new SendgridSmtpTransport(self::USER, $dispatcher, $logger),
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('sendgrid+smtps', 'default', self::USER),
|
||||
new SendgridSmtpTransport(self::USER, $dispatcher, $logger),
|
||||
];
|
||||
}
|
||||
@ -72,13 +87,13 @@ class SendgridTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function unsupportedSchemeProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('foo', 'sendgrid', self::USER),
|
||||
'The "foo" scheme is not supported for mailer "sendgrid". Supported schemes are: "api", "smtp", "smtps".',
|
||||
new Dsn('sendgrid+foo', 'sendgrid', self::USER),
|
||||
'The "sendgrid+foo" scheme is not supported. Supported schemes for mailer "sendgrid" are: "sendgrid", "sendgrid+api", "sendgrid+smtp", "sendgrid+smtps".',
|
||||
];
|
||||
}
|
||||
|
||||
public function incompleteDsnProvider(): iterable
|
||||
{
|
||||
yield [new Dsn('api', 'sendgrid')];
|
||||
yield [new Dsn('sendgrid+api', 'default')];
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
class SendgridApiTransport extends AbstractApiTransport
|
||||
{
|
||||
private const ENDPOINT = 'https://api.sendgrid.com/v3/mail/send';
|
||||
private const HOST = 'api.sendgrid.com';
|
||||
|
||||
private $key;
|
||||
|
||||
@ -39,12 +39,12 @@ class SendgridApiTransport extends AbstractApiTransport
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('api://sendgrid');
|
||||
return sprintf('sendgrid+api://%s', $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||
{
|
||||
$response = $this->client->request('POST', self::ENDPOINT, [
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/v3/mail/send', [
|
||||
'json' => $this->getPayload($email, $envelope),
|
||||
'auth_bearer' => $this->key,
|
||||
]);
|
||||
@ -136,4 +136,9 @@ class SendgridApiTransport extends AbstractApiTransport
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
private function getEndpoint(): ?string
|
||||
{
|
||||
return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : '');
|
||||
}
|
||||
}
|
||||
|
@ -25,19 +25,22 @@ final class SendgridTransportFactory extends AbstractTransportFactory
|
||||
{
|
||||
$key = $this->getUser($dsn);
|
||||
|
||||
if ('api' === $dsn->getScheme()) {
|
||||
return new SendgridApiTransport($key, $this->client, $this->dispatcher, $this->logger);
|
||||
if ('sendgrid+api' === $dsn->getScheme()) {
|
||||
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
|
||||
$port = $dsn->getPort();
|
||||
|
||||
return (new SendgridApiTransport($key, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port);
|
||||
}
|
||||
|
||||
if ('smtp' === $dsn->getScheme() || 'smtps' === $dsn->getScheme()) {
|
||||
if ('sendgrid+smtp' === $dsn->getScheme() || 'sendgrid+smtps' === $dsn->getScheme() || 'sendgrid' === $dsn->getScheme()) {
|
||||
return new SendgridSmtpTransport($key, $this->dispatcher, $this->logger);
|
||||
}
|
||||
|
||||
throw new UnsupportedSchemeException($dsn, ['api', 'smtp', 'smtps']);
|
||||
throw new UnsupportedSchemeException($dsn, 'sendgrid', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return 'sendgrid' === $dsn->getHost();
|
||||
return ['sendgrid', 'sendgrid+api', 'sendgrid+smtp', 'sendgrid+smtps'];
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ use Symfony\Component\Mailer\Transport\Dsn;
|
||||
*/
|
||||
class UnsupportedSchemeException extends LogicException
|
||||
{
|
||||
public function __construct(Dsn $dsn, array $supported)
|
||||
public function __construct(Dsn $dsn, string $name, array $supported)
|
||||
{
|
||||
parent::__construct(sprintf('The "%s" scheme is not supported for mailer "%s". Supported schemes are: "%s".', $dsn->getScheme(), $dsn->getHost(), implode('", "', $supported)));
|
||||
parent::__construct(sprintf('The "%s" scheme is not supported. Supported schemes for mailer "%s" are: "%s".', $dsn->getScheme(), $name, implode('", "', $supported)));
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ abstract class TransportFactoryTestCase extends TestCase
|
||||
$factory = $this->getFactory();
|
||||
|
||||
$this->assertEquals($transport, $factory->create($dsn));
|
||||
if ('smtp' !== $dsn->getScheme() && 'smtps' !== $dsn->getScheme()) {
|
||||
if (false !== strpos('smtp', $dsn->getScheme())) {
|
||||
$this->assertStringMatchesFormat($dsn->getScheme().'://%S'.$dsn->getHost().'%S', (string) $transport);
|
||||
}
|
||||
}
|
||||
|
@ -27,29 +27,16 @@ class NullTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function supportsProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('smtp', 'null'),
|
||||
new Dsn('null', ''),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'example.com'),
|
||||
false,
|
||||
];
|
||||
}
|
||||
|
||||
public function createProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('smtp', 'null'),
|
||||
new Dsn('null', 'null'),
|
||||
new NullTransport($this->getDispatcher(), $this->getLogger()),
|
||||
];
|
||||
}
|
||||
|
||||
public function unsupportedSchemeProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('foo', 'null'),
|
||||
'The "foo" scheme is not supported for mailer "null". Supported schemes are: "smtp".',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,6 @@ class NullTransportTest extends TestCase
|
||||
public function testToString()
|
||||
{
|
||||
$t = new NullTransport();
|
||||
$this->assertEquals('smtp://null', (string) $t);
|
||||
$this->assertEquals('null://', (string) $t);
|
||||
}
|
||||
}
|
||||
|
@ -27,20 +27,15 @@ class SendmailTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function supportsProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('smtp', 'sendmail'),
|
||||
new Dsn('sendmail+smtp', 'default'),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'example.com'),
|
||||
false,
|
||||
];
|
||||
}
|
||||
|
||||
public function createProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('smtp', 'sendmail'),
|
||||
new Dsn('sendmail+smtp', 'default'),
|
||||
new SendmailTransport(null, $this->getDispatcher(), $this->getLogger()),
|
||||
];
|
||||
}
|
||||
@ -48,8 +43,8 @@ class SendmailTransportFactoryTest extends TransportFactoryTestCase
|
||||
public function unsupportedSchemeProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
new Dsn('http', 'sendmail'),
|
||||
'The "http" scheme is not supported for mailer "sendmail". Supported schemes are: "smtp".',
|
||||
new Dsn('sendmail+http', 'default'),
|
||||
'The "sendmail+http" scheme is not supported. Supported schemes for mailer "sendmail" are: "sendmail", "sendmail+smtp".',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ class EsmtpTransportFactoryTest extends TransportFactoryTestCase
|
||||
$transport = new EsmtpTransport('example.com', 465, true, $eventDispatcher, $logger);
|
||||
|
||||
yield [
|
||||
new Dsn('smtp', 'example.com', '', '', 465),
|
||||
new Dsn('smtps', 'example.com', '', '', 465),
|
||||
$transport,
|
||||
];
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
abstract class AbstractHttpTransport extends AbstractTransport
|
||||
{
|
||||
protected $host;
|
||||
protected $port;
|
||||
protected $client;
|
||||
|
||||
public function __construct(HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
|
||||
@ -40,6 +42,26 @@ abstract class AbstractHttpTransport extends AbstractTransport
|
||||
parent::__construct($dispatcher, $logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setHost(?string $host)
|
||||
{
|
||||
$this->host = $host;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setPort(?int $port)
|
||||
{
|
||||
$this->port = $port;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
abstract protected function doSendHttp(SentMessage $message): ResponseInterface;
|
||||
|
||||
protected function doSend(SentMessage $message): void
|
||||
|
@ -32,6 +32,13 @@ abstract class AbstractTransportFactory implements TransportFactoryInterface
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
{
|
||||
return \in_array($dsn->getScheme(), $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
abstract protected function getSupportedSchemes(): array;
|
||||
|
||||
protected function getUser(Dsn $dsn): string
|
||||
{
|
||||
$user = $dsn->getUser();
|
||||
|
@ -26,6 +26,6 @@ final class NullTransport extends AbstractTransport
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'smtp://null';
|
||||
return 'null://';
|
||||
}
|
||||
}
|
||||
|
@ -20,15 +20,15 @@ final class NullTransportFactory extends AbstractTransportFactory
|
||||
{
|
||||
public function create(Dsn $dsn): TransportInterface
|
||||
{
|
||||
if ('smtp' === $dsn->getScheme()) {
|
||||
if ('null' === $dsn->getScheme()) {
|
||||
return new NullTransport($this->dispatcher, $this->logger);
|
||||
}
|
||||
|
||||
throw new UnsupportedSchemeException($dsn, ['smtp']);
|
||||
throw new UnsupportedSchemeException($dsn, 'null', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return 'null' === $dsn->getHost();
|
||||
return ['null'];
|
||||
}
|
||||
}
|
||||
|
@ -20,15 +20,15 @@ final class SendmailTransportFactory extends AbstractTransportFactory
|
||||
{
|
||||
public function create(Dsn $dsn): TransportInterface
|
||||
{
|
||||
if ('smtp' === $dsn->getScheme()) {
|
||||
if ('sendmail+smtp' === $dsn->getScheme() || 'sendmail' === $dsn->getScheme()) {
|
||||
return new SendmailTransport(null, $this->dispatcher, $this->logger);
|
||||
}
|
||||
|
||||
throw new UnsupportedSchemeException($dsn, ['smtp']);
|
||||
throw new UnsupportedSchemeException($dsn, 'sendmail', $this->getSupportedSchemes());
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return 'sendmail' === $dsn->getHost();
|
||||
return ['sendmail', 'sendmail+smtp'];
|
||||
}
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ final class EsmtpTransportFactory extends AbstractTransportFactory
|
||||
return $transport;
|
||||
}
|
||||
|
||||
public function supports(Dsn $dsn): bool
|
||||
protected function getSupportedSchemes(): array
|
||||
{
|
||||
return 'smtp' === $dsn->getScheme() || 'smtps' === $dsn->getScheme();
|
||||
return ['smtp', 'smtps'];
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user