How to use database for mail settings in Laravel

后端 未结 4 785
伪装坚强ぢ
伪装坚强ぢ 2021-02-06 15:51

I\'d like to keep users away from editing configuration files, so I\'ve made web interface in admin panel for setting up Mail server, username, password, port, encryption.. I w

相关标签:
4条回答
  • 2021-02-06 16:31

    To archive this I created CustomMailServiceProvider by extending Illuminate\Mail\MailServiceProvider so as to overwrite this method:

    protected function registerSwiftTransport(){
        $this->app['swift.transport'] = $this->app->share(function($app)
        {
        return new TransportManager($app);
        });
    }
    

    Here is the complete solution

    1. I created CustomMailServiceProvider.php in app\Providers

    namespace App\Providers;
    
    use Illuminate\Mail\MailServiceProvider;
    use App\Customs\CustomTransportManager;
    
    class CustomMailServiceProvider extends MailServiceProvider{
    
        protected function registerSwiftTransport(){
            $this->app['swift.transport'] = $this->app->share(function($app)
            {
                return new CustomTransportManager($app);
            });
        }
    }
    
    1. I created CustomTransportManager.php in app/customs directory - NB: app/customs directory doesn't exist in default laravel 5 directory structure, I created it

    namespace App\Customs;
    
    use Illuminate\Mail\TransportManager;
    use App\Models\Setting; //my models are located in app\models
    
    class CustomTransportManager extends TransportManager {
    
        /**
         * Create a new manager instance.
         *
         * @param  \Illuminate\Foundation\Application  $app
         * @return void
         */
        public function __construct($app)
        {
            $this->app = $app;
    
            if( $settings = Setting::all() ){
    
                $this->app['config']['mail'] = [
                    'driver'        => $settings->mail_driver,
                    'host'          => $settings->mail_host,
                    'port'          => $settings->mail_port,
                    'from'          => [
                    'address'   => $settings->mail_from_address,
                    'name'      => $settings->mail_from_name
                    ],
                    'encryption'    => $settings->mail_encryption,
                    'username'      => $settings->mail_username,
                    'password'      => $settings->mail_password,
                    'sendmail'      => $settings->mail_sendmail,
                    'pretend'       => $settings->mail_pretend
               ];
           }
    
        }
    }
    
    1. And finally, I replaced 'Illuminate\Mail\MailServiceProvider', in config/app.php with 'App\Providers\CustomMailServiceProvider',
    0 讨论(0)
  • 2021-02-06 16:45

    I configured as mentioned, however got the following error. While I tried your code found that from Laravel 5.4 share method is deprecated and instead informed to use singleton.

    Call to undefined method Illuminate\Foundation\Application::share()

    here is the below method using singleton instead using share method:

    protected function registerSwiftTransport(){
        $this->app->singleton('swift.transport', function ($app){
            return new CustomTransportManager($app);
        });
    }
    
    0 讨论(0)
  • 2021-02-06 16:47

    @DigitLimit , method share() has been dropped since Laravel 5.4. I had to work-around this problem using other methods, and I am not sure they are perfect. Here is my registerSwiftTransport() method in CustomMailServiceProvider class.

    Firstly, we need to determine if code is not executed while calling app through command line: "if(strpos(php_sapi_name(), 'cli') === false)". If we don't check that and don't prevent setting new params in this case, Artisan will throw us errors in command line. Secondly, we need to get settings from database somehow. I did it using my method getSettingValue(), where first argument is setting key, and second argument is default value if setting is not found. As you see, I assigned settings to $this->app['config']['mail']. After that, I used singleton() method:

    protected function registerSwiftTransport(){
        if (strpos(php_sapi_name(), 'cli') === false) {
           $this->app['config']['mail'] = [
            'driver'        => Setting::getSettingValue('mail_driver', '****'),
            'host'          => Setting::getSettingValue('mail_host', '****'),
            'port'          => Setting::getSettingValue('mail_port', 25),
            'from'          => [
                'address'   => Setting::getSettingValue('mail_from_address', '****'),
                'name'      => Setting::getSettingValue('mail_from_name', '****'),
            ],
            'encryption'    => Setting::getSettingValue('mail_encryption', '***'),
            'username'      => Setting::getSettingValue('mail_username', '****'),
            'password'      => Setting::getSettingValue('mail_password', '****'),
         ];
       }
    
       $this->app->singleton('swift.transport', function ($app) { 
           return new Illuminate\Mail\TransportManager($app);
       });
    }
    
    0 讨论(0)
  • I have added

    $this->app['config']['services'] = [
            'mailgun' => [
                'domain' => $settings->mailgun_domain,
                'secret' => $settings->mailgun_secret,
            ]
            ];   
    

    to CustomTransportManager __construct() to include mailgun API credentials that I'm using as mailing service

    0 讨论(0)
提交回复
热议问题