Recently Mailgun added a new feature which let users choose a new zone for better latency, the European zone.
This zone uses a new URL which differs from this one:
https://github.com/laravel/framework/blob/919eff201844db5c106145248cc02ac1ad671f31/src/Illuminate/Mail/Transport/MailgunTransport.php#L164
The new URL is: https://api.eu.mailgun.net/v3/{domain}/messages.mime
If someone is facing the same problem I solved it by extending the default Mailgun transport behaviour.
<?php
namespace App\Mail\Transports;
use GuzzleHttp\ClientInterface;
use Illuminate\Mail\Transport\MailgunTransport;
class ExtendedMailgunTransport extends MailgunTransport
{
private $zone;
public function __construct(ClientInterface $client, string $key, string $domain, string $zone)
{
$this->setZone($zone);
parent::__construct($client, $key, $domain);
}
private function setZone(string $zone)
{
$this->zone = $zone;
}
/**
* Set the domain being used by the transport.
*
* @param string $domain
* @return string
*/
public function setDomain($domain)
{
$this->url = 'https://api.mailgun.net/v3/' . $domain . '/messages.mime';
if ($this->zone === 'EU') {
$this->url = 'https://api.eu.mailgun.net/v3/' . $domain . '/messages.mime';
}
return $this->domain = $domain;
}
}
<?php
namespace App\Mail\Transports;
use Illuminate\Mail\TransportManager;
class CustomTransportManager extends TransportManager
{
public function createMailgunDriver() {
$config = $this->app['config']->get('services.mailgun', []);
return new ExtendedMailgunTransport(
$this->guzzle($config),
$config['secret'], $config['domain'], $config['zone']
);
}
}
<?php
namespace App\Mail\Transports;
class MailServiceProvider extends \Illuminate\Mail\MailServiceProvider
{
public function registerSwiftTransport()
{
if ($this->app['config']['mail.driver'] == 'mailgun') {
$this->app->singleton('swift.transport', function ($app) {
return new CustomTransportManager($app);
});
} else {
parent::registerSwiftTransport();
}
}
}
And in config/app.php override the default MailServiceProvider with the new one
//Illuminate\Mail\MailServiceProvider::class,
\App\Mail\Transports\MailServiceProvider::class,
Add 'zone' to config/service.php
'mailgun' => [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
'zone' => env('MAILGUN_ZONE', 'USA'),
],
And finally in your .env file add
MAILGUN_ZONE=EU
Might not be the best way to solve the issue, but it's working for me.
Thanks for sharing that. See https://github.com/laravel/framework/pull/24994.
See #25010 as well.
Most helpful comment
If someone is facing the same problem I solved it by extending the default Mailgun transport behaviour.
And in config/app.php override the default MailServiceProvider with the new one
Add 'zone' to config/service.php
And finally in your .env file add
MAILGUN_ZONE=EUMight not be the best way to solve the issue, but it's working for me.