Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating own mail provider for Laravel 5.4

Sometimes we have to integrate custom mail provider. But Laravel has a fixed list of them. Here they are:

  • SMTP
  • sendmail
  • ses
  • Mailgun
  • Mandrill
  • Sparkpost

Instructions for these drivers you can find in framework/src/Illuminate/Mail/TransportManager.php

The problem is that those instructions are fixed. Of course you can modify vendor-file but will be a dirty hack. So In the answer I'll provide some instruction how to implement your own custom mail driver in right way.

like image 852
Alex Slipknot Avatar asked Jul 04 '17 09:07

Alex Slipknot


1 Answers

First of all we have to create custom Transport for our mailer.

Our mailer will communicate with another server by some API interface. File bellow is a model so I've put it to my Model's folder. If you haven't separate folder for models you can just put the file into app directory.

Lets call it SmithTransport.php:

<?php 

use GuzzleHttp\ClientInterface;
use Illuminate\Mail\Transport\Transport;

class SmithTransport extends Transport
{
    protected $client;

    protected $key;

    protected $domain;

    protected $url;

    public function __construct(ClientInterface $client, $key, $domain)
    {
        $this->key = $key;
        $this->client = $client;
        $this->setDomain($domain);
    }

    public function send(Swift_Mime_Message $message, &$failedRecipients = null)
    {
        $this->beforeSendPerformed($message);

        $options = ['auth' => ['api', $this->key]];

        $message->setBcc([]);

        $from_email = '';
        $from_name = '';
        $to_email = '';
        $to_name = '';

        foreach ($message->getFrom() as $email => $name) {
            $from_email = $email;
            $from_name = $name;
        }

        foreach ($message->getTo() as $email => $name) {
            $to_email = $email;
            $to_name = $name;
        }

        $options['form_params'] = [
            'from_email' => $from_email,
            'from_name'  => $from_name,
            'to_email'   => $to_email,
            'to_name'    => $to_name,
            'subject'    => $message->getSubject(),
            'body'       => $message->getBody()
        ];

        return $this->client->post($this->url, $options);
    }

    public function getKey()
    {
        return $this->key;
    }

    public function setKey($key)
    {
        return $this->key = $key;
    }

    public function getDomain()
    {
        return $this->domain;
    }

    public function setDomain($domain)
    {
        $this->url = 'https://api.mymailer.com/send?key=' . $this->key;

        return $this->domain = $domain;
    }
}

Next step is extending TransportManager. Because we have to add instructions for our custom Transport.

So it will be SmithTransportManager.php in model's directory or in app directory if you haven't separate directory for models.

<?php

use Illuminate\Mail\TransportManager;

class SmithTransportManager extends TransportManager
{
    protected function createSmithDriver()
    {
        $config = $this->app['config']->get('services.smith', []);

        return new SmithTransport(
            $this->guggle($config),
            $config['secret'], $config['domain']
        );
    }

}

Next step is extending existing MailServiceProvider.

So our provider will be in app/Providers/MailServiceProvider.php

<?php namespace App\Providers;

use Illuminate\Mail\MailServiceProvider as MailProvider;

class MailServiceProvider extends MailProvider
{
    protected function registerSwiftTransport()
    {
        $this->app->singleton('swift.transport', function ($app) {
            return new \SmithTransportManager($app);
        });
    }

}

And the final step is modifying config files.

In the config/app.php

you have to remove (or comment line) standard Illuminate\Mail\MailServiceProvider::class,

And add App\Providers\MailServiceProvider::class, to the providers section.

In the config/services.php we have to add config getters:

'smith' => [
    'domain' => env('SMITH_DOMAIN'),
    'secret' => env('SMITH_SECRET'),
],

That's all! Hope it helps 'cause I didn't find any information in the docs of somewhere else about custom MailTransport.

like image 175
Alex Slipknot Avatar answered Nov 04 '22 01:11

Alex Slipknot