Laravel 5.3 change mail configuration dynamically

If you are developing CMS software or a SaaS product, your customers needs to set their mail sending credentials for sending mails from their system. By default, you can set mail configuration to .env file.

But if your customer don’t have access to .env file and command line to execute artisan config:clear command, they need to change credentials from their panel. Here is an example:

I store these values at database. So, i need to change mail config before sending email. But, Laravel’s

config()->set('mail',$values);

doesn’t work. Because, SwiftMailer instance registers when compiling Service Providers with default parameters which are coming from .env file. So, there is two option for override this instance.

1- Create new Swift_Mailer instance and set it before sending email.

<?php
$swiftMailer = new Swift_Mailer();
//do your configuration with swift mailer
Mail::setSwiftMailer($swiftMailer);
Mail::to('mail')
->send();

But, i do not use this metod. I don’t want to fight with SwiftMailer’s configuration. And also, it’s bad architect. It stand againts Dependency Injection.

2- Override MailService Provider

It has 3 step to set-up.

a) Create AppManagerMailTransportManager. (You can use your namespace.) In this file, we will get mail configuration from database (or wherever you save) and will set to laravel’s config.

<?php
/**
 * @author Guven Atbakan
 */

namespace AppManager;

use AppModulesSettingServiceSettingService;
use IlluminateMailTransportManager;

class MailTransportManager extends TransportManager
{
    public function __construct(IlluminateFoundationApplication $app)
    {
        $settings = []; //get your settings from somewhere

        /
            $this->setDefaultDriver('smtp');
            $this->app['config']['mail'] = [
                'driver' => 'smtp',
                'host' => $settings['mailHost'] ?? 'smtp.yandex.net',
                'port' => $settings['mailPort'] ?? 465,
                'from' => [
                    'address' => $settings['mailFromAddress'] ?? '',
                    'name' => $settings['mailFromName'] ?? '',
                ],
                'encryption' => 'tls',
                'username' => $settings['mailUsername'] ?? '-',
                'password' => $settings['mailPassword'] ?? '-',
                'sendmail' => $settings['mailSendmailPath'] ?? '/usr/sbin/sendmail -bs',
                'pretend' => false,
            ];

            config()->set('mail', $this->app['config']['mail']);
            //i'm not sure if its necessary.
    }
}

b) Create AppProvidersCustomMailServiceProvider. In this file, we will tell  to swift mailer, use our MailTransportManager.

<?php

namespace AppProviders;

use AppManagerMailTransportManager;
use IlluminateMailMailServiceProvider;

class CustomMailServiceProvider extends MailServiceProvider
{
    protected function registerSwiftTransport()
    {
        $this->app['swift.transport'] = $this->app->share(function ($app) {
            return new MailTransportManager($app);
        });
    }
}

 

c) By using config/app.php, we will disable default MailServiceProvider and register our CustomMailServiceProvider. It’s easy.

<?php
//IlluminateMailMailServiceProvider::class,
AppProvidersCustomMailServiceProvider::class,

3 Comments

  1. Gecenin 00:30 ‘unda araştırıyordum teşekkürler, en azından Türkçe olsaydı daha iyi olurdu İngilizce İngilizce arattık :)

    • Ara ara böyle ingilizce yazma isteği geliyor bana. Yazı yazarak ingilizcemi geliştirmeye çalışıyorum :)

Leave a Reply to batuhanCancel Reply

Your email address will not be published. Required fields are marked *