Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save simtabi/b376beac3f98c61f2c00b6d7455be7fd to your computer and use it in GitHub Desktop.
Save simtabi/b376beac3f98c61f2c00b6d7455be7fd to your computer and use it in GitHub Desktop.
Add Custom Mail Driver to Laravel

How to add custom Mail Driver to Laravel

Tested on Laravel 5.8

Within the source code of laravel 5.8 at this time of writing, we have this following

<?php

namespace Illuminate\Support;
// use...

abstract class Manager
{
  //somewhere in the body ...
  
      /**
     * Register a custom driver creator Closure.
     *
     * @param  string    $driver
     * @param  \Closure  $callback
     * @return $this
     */
    public function extend($driver, Closure $callback)
    {
        $this->customCreators[$driver] = $callback;

        return $this;
    }
    
    // the rest of the code...
}

it means we can easily extend the driver using this manager class!

Create a MailDriver class

In this case I am using OutlookMailDriver, and since i am going to use the extend method from the existing manager, it expects a Closure therefore i make an invocable method that return a function.

<?php
declare(strict_types=1);

namespace App\Helpers\Drivers;


use App\Helpers\Transports\OutlookTransportManager;
use Illuminate\Mail\TransportManager;

class OutlookMailDriver
{
    public function __invoke(TransportManager $manager)
    {
        return function ($app) {
            $config = $app['config']->get('services.outlook', []);
            return new OutlookTransportManager($config);
        };
    }
}

The signature of your invocable may differ from mine

Create a CustomMailProvider that extend Illuminate\Mail\MailServiceProvider

I am going to override the registerSwiftTransport method yet calling its parent first to have it registered its expected Manager then I extend it with my custom Mail Driver.

<?php

namespace App\Providers;

use App\Helpers\Drivers\OutlookMailDriver;
use Illuminate\Mail\MailServiceProvider;
use Illuminate\Mail\TransportManager;

class CustomMailProvider extends MailServiceProvider
{
    /**
     * Register the Swift Transport instance.
     *
     * @return void
     */
    protected function registerSwiftTransport()
    {
        parent::registerSwiftTransport();
        
        $this->app->extend('swift.transport', function (TransportManager $transport) {
            $driver = 'outlook';
            $callback = new OutlookMailDriver();
            $transport->extend($driver, $callback($transport));
            return $transport;
        });
    }
}

Create a class that extends Illuminate\Mail\Transport\Transport

Since Illuminate\Mail\Transport\Transport is an abstract class therefore i need to have send method.

<?php
declare(strict_types=1);

namespace App\Helpers\Transports;

use Illuminate\Mail\Transport\Transport;
use Swift_Mime_SimpleMessage;

class OutlookTransportManager extends Transport
{

    public function __construct($config)
    {
        // do your whatever you need here
    }
    
    public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null)
    {
        logger('I am using custom outlook manager');
        // TODO: Implement send() method.
        return 0;
    }
}

Register the CustomMailProvider in your config/app.php

comment Illuminate\Mail\MailServiceProvider::class within your config, and register your own custom provider there

return [
    'providers' => [
        //...
        App\Providers\CustomMailProvider::class,
        //Illuminate\Mail\MailServiceProvider::class, // comment this out
    ],
];

Test

// somewhere in your route/web.php

Route::get('test', function () {
    Mail::to('[email protected]')->send(new \App\Mail\Test());
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment