diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Http/Api/MailgunTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Http/Api/MailgunTransport.php index dc047c2e87..9e61ee4dcd 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Http/Api/MailgunTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Http/Api/MailgunTransport.php @@ -27,15 +27,17 @@ use Symfony\Contracts\HttpClient\HttpClientInterface; */ class MailgunTransport extends AbstractApiTransport { - private const ENDPOINT = 'https://api.mailgun.net/v3/%domain%/messages'; + private const ENDPOINT = 'https://api.%region_dot%mailgun.net/v3/%domain%/messages'; private $key; private $domain; + private $region; - public function __construct(string $key, string $domain, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + public function __construct(string $key, string $domain, string $region = null, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) { $this->key = $key; $this->domain = $domain; + $this->region = $region; parent::__construct($client, $dispatcher, $logger); } @@ -48,7 +50,7 @@ class MailgunTransport extends AbstractApiTransport $headers[] = $header->toString(); } - $endpoint = str_replace('%domain%', urlencode($this->domain), self::ENDPOINT); + $endpoint = str_replace(['%domain%', '%region_dot%'], [urlencode($this->domain), 'us' !== ($this->region ?: 'us') ? $this->region.'.' : ''], self::ENDPOINT); $response = $this->client->request('POST', $endpoint, [ 'auth_basic' => 'api:'.$this->key, 'headers' => $headers, diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Http/MailgunTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Http/MailgunTransport.php index 2d3fe15a08..913ed705d9 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Http/MailgunTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Http/MailgunTransport.php @@ -27,14 +27,16 @@ use Symfony\Contracts\HttpClient\HttpClientInterface; */ class MailgunTransport extends AbstractHttpTransport { - private const ENDPOINT = 'https://api.mailgun.net/v3/%domain%/messages.mime'; + private const ENDPOINT = 'https://api.%region_dot%mailgun.net/v3/%domain%/messages.mime'; private $key; private $domain; + private $region; - public function __construct(string $key, string $domain, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + public function __construct(string $key, string $domain, string $region = null, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) { $this->key = $key; $this->domain = $domain; + $this->region = $region; parent::__construct($client, $dispatcher, $logger); } @@ -49,7 +51,7 @@ class MailgunTransport extends AbstractHttpTransport foreach ($body->getPreparedHeaders()->getAll() as $header) { $headers[] = $header->toString(); } - $endpoint = str_replace('%domain%', urlencode($this->domain), self::ENDPOINT); + $endpoint = str_replace(['%domain%', '%region_dot%'], [urlencode($this->domain), 'us' !== ($this->region ?: 'us') ? $this->region.'.' : ''], self::ENDPOINT); $response = $this->client->request('POST', $endpoint, [ 'auth_basic' => 'api:'.$this->key, 'headers' => $headers, diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Smtp/MailgunTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Smtp/MailgunTransport.php index 105ab46ecd..c288a46bdd 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Smtp/MailgunTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Smtp/MailgunTransport.php @@ -22,9 +22,9 @@ use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; */ class MailgunTransport extends EsmtpTransport { - public function __construct(string $username, string $password, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + public function __construct(string $username, string $password, string $region = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) { - parent::__construct('smtp.mailgun.org', 465, 'ssl', null, $dispatcher, $logger); + parent::__construct('us' !== ($region ?: 'us') ? sprintf('smtp.%s.mailgun.org', $region) : 'smtp.mailgun.org', 465, 'ssl', null, $dispatcher, $logger); $this->setUsername($username); $this->setPassword($password); diff --git a/src/Symfony/Component/Mailer/Tests/TransportTest.php b/src/Symfony/Component/Mailer/Tests/TransportTest.php index 0d1f143262..a12aae4830 100644 --- a/src/Symfony/Component/Mailer/Tests/TransportTest.php +++ b/src/Symfony/Component/Mailer/Tests/TransportTest.php @@ -23,7 +23,9 @@ use Symfony\Component\Mailer\Bridge\Sendgrid; use Symfony\Component\Mailer\Exception\InvalidArgumentException; use Symfony\Component\Mailer\Exception\LogicException; use Symfony\Component\Mailer\Transport; +use Symfony\Component\Mime\Email; use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\HttpClient\ResponseInterface; class TransportTest extends TestCase { @@ -106,6 +108,15 @@ class TransportTest extends TestCase $this->assertEquals('pa$s', $transport->getPassword()); $this->assertProperties($transport, $dispatcher, $logger); + $transport = Transport::fromDsn('smtp://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun', $dispatcher, null, $logger); + $this->assertEquals('smtp.mailgun.org', $transport->getStream()->getHost()); + + $transport = Transport::fromDsn('smtp://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun?region=eu', $dispatcher, null, $logger); + $this->assertEquals('smtp.eu.mailgun.org', $transport->getStream()->getHost()); + + $transport = Transport::fromDsn('smtp://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun?region=us', $dispatcher, null, $logger); + $this->assertEquals('smtp.mailgun.org', $transport->getStream()->getHost()); + $client = $this->createMock(HttpClientInterface::class); $transport = Transport::fromDsn('http://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun', $dispatcher, $client, $logger); $this->assertInstanceOf(Mailgun\Http\MailgunTransport::class, $transport); @@ -115,6 +126,25 @@ class TransportTest extends TestCase 'client' => $client, ]); + $response = $this->createMock(ResponseInterface::class); + $response->expects($this->any())->method('getStatusCode')->willReturn(200); + $message = (new Email())->from('me@me.com')->to('you@you.com')->subject('hello')->text('Hello you'); + + $client = $this->createMock(HttpClientInterface::class); + $client->expects($this->once())->method('request')->with('POST', 'https://api.mailgun.net/v3/pa%24s/messages.mime')->willReturn($response); + $transport = Transport::fromDsn('http://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun', $dispatcher, $client, $logger); + $transport->send($message); + + $client = $this->createMock(HttpClientInterface::class); + $client->expects($this->once())->method('request')->with('POST', 'https://api.eu.mailgun.net/v3/pa%24s/messages.mime')->willReturn($response); + $transport = Transport::fromDsn('http://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun?region=eu', $dispatcher, $client, $logger); + $transport->send($message); + + $client = $this->createMock(HttpClientInterface::class); + $client->expects($this->once())->method('request')->with('POST', 'https://api.mailgun.net/v3/pa%24s/messages.mime')->willReturn($response); + $transport = Transport::fromDsn('http://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun?region=us', $dispatcher, $client, $logger); + $transport->send($message); + $transport = Transport::fromDsn('api://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun', $dispatcher, $client, $logger); $this->assertInstanceOf(Mailgun\Http\Api\MailgunTransport::class, $transport); $this->assertProperties($transport, $dispatcher, $logger, [ @@ -123,6 +153,21 @@ class TransportTest extends TestCase 'client' => $client, ]); + $client = $this->createMock(HttpClientInterface::class); + $client->expects($this->once())->method('request')->with('POST', 'https://api.mailgun.net/v3/pa%24s/messages')->willReturn($response); + $transport = Transport::fromDsn('api://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun', $dispatcher, $client, $logger); + $transport->send($message); + + $client = $this->createMock(HttpClientInterface::class); + $client->expects($this->once())->method('request')->with('POST', 'https://api.eu.mailgun.net/v3/pa%24s/messages')->willReturn($response); + $transport = Transport::fromDsn('api://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun?region=eu', $dispatcher, $client, $logger); + $transport->send($message); + + $client = $this->createMock(HttpClientInterface::class); + $client->expects($this->once())->method('request')->with('POST', 'https://api.mailgun.net/v3/pa%24s/messages')->willReturn($response); + $transport = Transport::fromDsn('api://'.urlencode('u$er').':'.urlencode('pa$s').'@mailgun?region=us', $dispatcher, $client, $logger); + $transport->send($message); + $this->expectException(LogicException::class); Transport::fromDsn('foo://mailgun'); } diff --git a/src/Symfony/Component/Mailer/Transport.php b/src/Symfony/Component/Mailer/Transport.php index 326452ede9..ad5ea86462 100644 --- a/src/Symfony/Component/Mailer/Transport.php +++ b/src/Symfony/Component/Mailer/Transport.php @@ -101,13 +101,13 @@ class Transport } if ('smtp' === $parsedDsn['scheme']) { - return new Mailgun\Smtp\MailgunTransport($user, $pass, $dispatcher, $logger); + return new Mailgun\Smtp\MailgunTransport($user, $pass, $query['region'] ?? null, $dispatcher, $logger); } if ('http' === $parsedDsn['scheme']) { - return new Mailgun\Http\MailgunTransport($user, $pass, $client, $dispatcher, $logger); + return new Mailgun\Http\MailgunTransport($user, $pass, $query['region'] ?? null, $client, $dispatcher, $logger); } if ('api' === $parsedDsn['scheme']) { - return new Mailgun\Http\Api\MailgunTransport($user, $pass, $client, $dispatcher, $logger); + return new Mailgun\Http\Api\MailgunTransport($user, $pass, $query['region'] ?? null, $client, $dispatcher, $logger); } throw new LogicException(sprintf('The "%s" scheme is not supported for mailer "%s".', $parsedDsn['scheme'], $parsedDsn['host'])); diff --git a/src/Symfony/Component/Mailer/composer.json b/src/Symfony/Component/Mailer/composer.json index b9852124f1..91bfb1031d 100644 --- a/src/Symfony/Component/Mailer/composer.json +++ b/src/Symfony/Component/Mailer/composer.json @@ -26,7 +26,7 @@ "symfony/amazon-mailer": "^4.3", "symfony/google-mailer": "^4.3", "symfony/http-client-contracts": "^1.1", - "symfony/mailgun-mailer": "^4.3", + "symfony/mailgun-mailer": "^4.3.2", "symfony/mailchimp-mailer": "^4.3", "symfony/postmark-mailer": "^4.3", "symfony/sendgrid-mailer": "^4.3"