Search code examples
yii2swiftmaileryii2-basic-app

Update swiftmailer configuration based on user input


I need to update SwiftMailer configuration based on user input, particularly, the user may decide to send emails using SMTP protocol or store them locally (in an specific filesystem's folder). The user will use a view to decide the option, then the controller catch the decision and update a session var. The current approach is to read that session var from config/web.php and then choose the appropriate configuration.

I am not sure whether web.php is loaded just once during the application execution, in fact I can not check if the session is active and then get the info from the var. I'm not sure what approach may be the appropriate one.

This is my config/web.php:

<?php
use yii\web\Session;

$params = require __DIR__ . '/params.php';
$db = require __DIR__ . '/db.php';
$session = Yii::$app->session;
if($session->isActive){
    $mailTransport = Yii::app()->session->get('emailtransport');    
}
else{ //session is not started
    $mailTransport = 'local';
}

if($mailTransport=='local'){
    $config = [
    'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'aliases' => [
        '@bower' => '@vendor/bower-asset',
        '@npm'   => '@vendor/npm-asset',
    ],
    'components' => [
        'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'cookieValidationKey' => 'a4ARdWYauHJ-UEAvVfagzk0LTyT_KEuZ',
        ],
        'cache' => [
            'class' => 'yii\caching\FileCache',
        ],
        'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
        ],
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
        'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            'viewPath' => '@app/mail',
            'htmlLayout' => 'layouts/main-html', //template to Send Emails Html based
            'textLayout' => 'layouts/main-text', //template to Send Emails text based
            'messageConfig' => [
               'charset' => 'UTF-8',
               'from' => ['[email protected]' => 'OK Premiun Clients'],
             ], //end of messageConfig
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
            //'useFileTransport' => false,
            'transport' => [
            'class' => 'Swift_SmtpTransport',
            'host' => 'smtp.gmail.com',
            'username' => '[email protected]',
            'password' => "password",
            'port' => '465',
            'encryption' => 'ssl',
          ],
        ],
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
        'db' => $db,
        /*
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
            ],
        ],
        */
    ],
    'params' => $params,
];
}//end of if loop
else{
    $config = [
    'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'aliases' => [
        '@bower' => '@vendor/bower-asset',
        '@npm'   => '@vendor/npm-asset',
    ],
    'components' => [
        'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'cookieValidationKey' => 'a4ARdWYauHJ-UEAvVfagzk0LTyT_KEuZ',
        ],
        'cache' => [
            'class' => 'yii\caching\FileCache',
        ],
        'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
        ],
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
        'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            'viewPath' => '@app/mail',
            'htmlLayout' => 'layouts/main-html', //template to Send Emails Html based
            'textLayout' => 'layouts/main-text', //template to Send Emails text based
            'messageConfig' => [
               'charset' => 'UTF-8',
               'from' => ['[email protected]' => 'OK Premiun Clients'],
             ], //end of messageConfig
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => false,
            'transport' => [
            'class' => 'Swift_SmtpTransport',
            'host' => 'smtp.gmail.com',
            'username' => '[email protected]',
            'password' => "password",
            'port' => '465',
            'encryption' => 'ssl',
          ],
        ],
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
        'db' => $db,
        /*
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
            ],
        ],
        */
    ],
    'params' => $params,
];
}//end of if else loop

Because the session is never reached on web.php the emails are always stored locally.


Solution

  • What you are trying to do requires you to instantiate the yii\swiftmailer\Mailer class from within your code and set the transport by calling setTransport(), rather than using it via defining under the components in the config file.

    I will give you an example where i will use the smtp.gmail.com as the host for the transport and send an email

    public function actionTest(){
    
        //instantiate the mailer
        $mailer = new \yii\swiftmailer\Mailer(
            [
                'useFileTransport' => false
            ]
        );
    
        //set the transport params
        $mailer->setTransport(
            [
                'class' => 'Swift_SmtpTransport',
                'host' => 'smtp.gmail.com',
                'username' => 'username',
                'password' => 'password',
                'port' => '587',
                'encryption' => 'tls'
            ]
        );
    
        //to email 
        $to = "[email protected]";
    
        //email subject
        $subject = "this is a test mail";
    
        //email body 
        $body ="Some body text for email";
    
        //send the email
        $mailer->compose()->setTo($to)->setFrom(
            [
                '[email protected]' => 'Site Support'
            ]
        )->setTextBody($body)->setSubject($subject)->send();
    }