Skip to content

Instantly share code, notes, and snippets.

@j0um
Last active July 17, 2020 10:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save j0um/27df29e165a1c1e0634a8dee2122db99 to your computer and use it in GitHub Desktop.
Save j0um/27df29e165a1c1e0634a8dee2122db99 to your computer and use it in GitHub Desktop.
Adding support for Mailgun's parameters to Laravel

Adding support for Mailgun's parameters to Laravel.

This gist is about adding support for Mailgun's parameters (o:tag, o:testmode, etc..) to your application.

Override.

  1. Add these files to your Laravel project :

    • app/Mail/TransportManager.php
    • app/Mail/Transport/MailgunTransport.php
    • app/Providers/MailServiceProvider.php
  2. In app.php, replace the line Illuminate\Mail\MailServiceProvider::class, with App\Providers\MailServiceProvider::class,

Test.

  • You can test your options using the provided command app/Console/Commands/MailgunParameterTest.php
  • Add the following line to the $command array in app/Console/Kernel.php : MailgunParameterTest::class,
  • Run the test in console : php artisan test:mailgun-parameter-test --to=%yourEmailAddressHere%
  • Have a look at your Mailgun Logs and your should see a "Test delievered" entry! :)

Profit!

# app/Console/Commands/MailgunParameterTest.php
<?php
namespace App\Console\Commands;
use App\Mail\Transport\MailgunTransport;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailer;
use Illuminate\Mail\Message;
/**
* Class MailgunParameterTest
* @package App\Console\Commands
*/
class MailgunParameterTest extends Command
{
/** @var string */
protected $signature = 'test:mailgun-parameter-test {--to=}';
/** @var string */
protected $description = 'This command contains code blocks to be tested.';
/** @var Mailer */
protected $mailer;
/**
* MailgunParameterTest constructor.
* @param Mailer $mailer
* @param Mailable $mailable
*/
public function __construct(Mailer $mailer)
{
parent::__construct();
$this->mailer = $mailer;
}
/**
* Execute the console command.
*/
public function handle()
{
/** @var MailgunTransport $transport */
$transport = $this->mailer->getSwiftMailer()->getTransport();
$transport->setOptions([
'o:tag' => 'This is a tag.',
'o:testmode' => 'yes'
]);
$email = $this->option('to');
$this->mailer->raw("This is a test", function ($message) use ($email) {
/** @var Message $message */
$message
->subject("Testing")
->to($email);
});
}
}
# app/Mail/Transport/MailgunTransport.php
<?php
namespace App\Mail\Transport;
/**
* Class MailgunTransport
* @package App\Mail\Transport
*
* @description This override adds support to Mailgun's options.
*/
class MailgunTransport extends \Illuminate\Mail\Transport\MailgunTransport {
/** @var array */
protected $options = [];
/**
* @param \Swift_Mime_SimpleMessage $message
* @param null $failedRecipients
* @param array $options
* @return int
*/
public function send(\Swift_Mime_SimpleMessage $message, &$failedRecipients = null, $options = [])
{
$this->beforeSendPerformed($message);
$to = $this->getTo($message);
$message->setBcc([]);
$payload = $this->payload($message, $to);
// Support for mailgun's options is added here.
foreach ($this->options as $key => $value) {
$payload['multipart'][] = [
'name' => $key,
'contents' => $value
];
}
$this->client->post($this->url, $payload);
$this->sendPerformed($message);
return $this->numberOfRecipients($message);
}
/**
* @param array $options
* @return $this
*/
public function setOptions($options) {
$this->options = $options;
return $this;
}
}
# app/Providers/MailServiceProvider.php
<?php
namespace App\Providers;
use App\Mail\TransportManager;
/**
* Class MailServiceProvider
* @package App\Providers
*
* @description The point of this override is to make sure SwiftMailer use our
* implementation of MailgunTransport.
*/
class MailServiceProvider extends \Illuminate\Mail\MailServiceProvider
{
/**
* Register the Swift Mailer instance.
*
* @return void
*/
public function registerSwiftMailer()
{
$this->registerSwiftTransport();
// Once we have the transporter registered, we will register the actual Swift
// mailer instance, passing in the transport instances, which allows us to
// override this transporter instances during app start-up if necessary.
$this->app->singleton('swift.mailer', function ($app) {
if ($domain = $app->make('config')->get('mail.domain')) {
\Swift_DependencyContainer::getInstance()
->register('mime.idgenerator.idright')
->asValue($domain);
}
return new \Swift_Mailer($app['swift.transport']->driver());
});
}
/**
* Register the Swift Transport instance.
*
* @return void
*/
protected function registerSwiftTransport()
{
$this->app->singleton('swift.transport', function ($app) {
return new TransportManager($app);
});
}
}
# app/Mail/TransportManager.php
<?php
namespace App\Mail;
use App\Mail\Transport\MailgunTransport;
/**
* Class TransportManager
* @package App\Mail
*
* @description Switches Laravel's MailgunTransport to ours which adds
* functionalities.
*/
class TransportManager extends \Illuminate\Mail\TransportManager
{
/**
* Create an instance of the Mailgun Swift Transport driver.
*
* @return MailgunTransport
*/
protected function createMailgunDriver()
{
$config = $this->app['config']->get('services.mailgun', []);
return new MailgunTransport(
$this->guzzle($config),
$config['secret'], $config['domain']
);
}
}
@mdeprezzo
Copy link

mdeprezzo commented Jun 11, 2019

Hi @j0um,
can i use it with markdown email and mailable class ?

@j0um
Copy link
Author

j0um commented Jun 11, 2019 via email

@j0um
Copy link
Author

j0um commented Jun 11, 2019

@mdeprezzo Yes this is what it's meant for! :)

@mdeprezzo
Copy link

mdeprezzo commented Jun 11, 2019

Ok, i've some cache to clear.

But how can i use with mailable. I mean, inside command test, there's only an example with mailer right?

i tried something like that:

Mail::to('email@example.com')
  ->send(new MailableEmail, null, ['o:tag' => 'test'])

but on mailgun log, there are no tags reported

@mdeprezzo
Copy link

@j0um I still need your help 💃

@riyuk
Copy link

riyuk commented Jul 8, 2019

If you use a mailable Class (like Mail::to(...)->send(new ClassName())) you don't need this.
You can simply build the Mailgun Tags in your class build method:

// Within public function build() in your Mail/Classname.php
$this->withSwiftMessage(function($message) {
            /**
             * @var $message \Swift_Message
             */
            $message->getHeaders()->addTextHeader('X-Mailgun-Tag', 'tagname');
        });

@mdeprezzo
Copy link

@riyuk already did thanks, anyway!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment