Yii2 mail catcher [duplicate] - yii2

This question already has an answer here:
Override Yii2 Swiftmailer Recipient
(1 answer)
Closed 5 years ago.
During the development and testing, I want the Yii2 mailer (swiftmailer) not to send emails to actual addresses, but replace it with developers` emails. Is there any setting in config to do it?

Just set the useFileTransport to true in component configuration for the development environment and all emails will not be sent but will be saved as files so you can easily test everything.

You should set configs for prod and dev environment.
Path for dev config (if you have advanced application template): yourProject/environments/dev/common/config/main-local.php and for prod: yourProject/environments/prod/common/config/main-local.php.
You may use EmailTarget class for logs.
Example of config for dev environment to reach the clue:
return [
'bootstrap' => ['log'],
'components' => [
...
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '#common/mail',
'useFileTransport' => true,//set this property to false to send mails to real email addresses
//comment the following array to send mail using php's mail function
],
'log' => [
'targets' =>
[
[
'class' => 'yii\log\EmailTarget',
'levels' => ['error'],
'except' => ['yii\web\HttpException:404'],
'message' => [
'to' => ['example#mail.ru'],
'from' => ['yourproject#mail.ru'],
'subject' => ' Errors ',
]
],
],
],
],
];
And similarly for prod environment but with different emails.
If you don't want to use EmailTarget class you may just set your emails for dev in params config here: yourProject/environments/dev/common/config/params-local.php.
And path for prod: yourProject/environments/prod/common/config/params-local.php
Params config example:
return [
'sendToEmails' => ['email1#mail.ru', 'email2#mail.ru']
];
And then you may use the variable in your code this way: Yii::$app->params['sendToEmails'] to get the array of emails to send messages to.
Don't forget to do php init command in your project after compliting your configs.
You may see the detailed docs about environments here.

Related

YII2 - In test, send email nowhere

I have a test and live environment. In test, I don't ever want to send the mailer mails. I have the mailer setup as a component in web.php like this
'mailer' => [
'class' => 'nickcv\mandrill\Mailer',
'apikey' => 'xxxxxxxxxxxxxxxxxxxx',
'useMandrillTemplates' => true,
'templateLanguage' => nickcv\mandrill\Mailer::LANGUAGE_HANDLEBARS,
],
Is there a way to set up the mailer component so it sends nowhere?
Thanks in advance.
Because mailer you are using extends yii\mail\BaseMailer you can simply set its $useFileTransport to true and the mail will be saved in file instead.
'mailer' => [
'class' => 'nickcv\mandrill\Mailer',
'apikey' => 'xxxxxxxxxxxxxxxxxxxx',
'useMandrillTemplates' => true,
'templateLanguage' => nickcv\mandrill\Mailer::LANGUAGE_HANDLEBARS,
'useFileTransport' => true,
],
Another option is creating a mock of mailer and using it instead of real mailer.
If you use codeception framework and its Yii2 module, the mailer component should be replaced automatically if you have email part enabled in codeception configs.
======== Configure Apache to send the emails from localhost code ========
Changes for C:\xampp\php\php.ini file:
search for [mail function]:
[mail function]
SMTP=localhost to SMTP=smtp.gmail.com
smtp_port=587
sendmail_from=me#example.com to sendmail_from=your email address
sendmail_path = "\"C:\xampp\sendmail\sendmail.exe\" -t"
mail.add_x_header=Off
mail.log = syslog
Changes for C:\xampp\sendmail\sendmail.ini:
search for [sendmail]:
smtp_server=smtp.gmail.com
smtp_port=587
smtp_ssl=auto
error_logfile=error.log
debug_logfile=debug.log
auth_username=same as "sendmail_from" in php.ini file
auth_password=generated password for the email account
force_sender= same as "auth_username" in this file
=========== mailer component in Yii application ===============
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// 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' => 'your email address (for testing on localhost use same as in ini files)',
'password' => 'generated password',
'port' => 587,
'encryption' => 'tls',
],
], //end of mailer
Actually, I think it would be nice to receive somewhere your test emails for debugging and QA.
Personally, in dev environment, I would recommend setting up and configuring mailhog
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '#common/mail',
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'localhost',
'port' => '1025',
],
],
It is straightforward to install following the steps described here: https://github.com/mailhog/MailHog
You can then go to http://localhost:8025 and see your inbox

Yii2-usuario: Debugging on transport layer

I cannot send emails out in Yii2-usuario, e.g. when a password recovery is requested. Email is not working at all.
There is just a flash message saying
Unable to send recovery message to the user
I think that this is a transport problem. There are tons of things that can go wrong here: firewall issues, tls-/security-settings, self-signed certificates, wrong ports, hostname-typos, ...
How to debug transport layer? How to enable debugging to trace connection to the email service?
Found the error. In config/web.php the mailer was configured as:
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'useFileTransport' => false,
'viewPath' => '#app/mail',
'htmlLayout' => 'layouts/main-html',
'textLayout' => 'layouts/main-text',
instead of
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'useFileTransport' => false,
'viewPath' => '#app/mail',
'htmlLayout' => '#app/mail/layouts/main-html',
'textLayout' => '#app/mail/layouts/main-text',
The layout paths were wrong. So the Mailer could not render the messages and failed sending out emails since Yii2-usuario uses formatted emails.
Everything works now.

Yii2 SwiftMailer .eml files created but with wrong names & file_put_contents Permission denied

The problem is when I'm trying to "send" the email it's failing with the message
file_put_contents(/some/path//frontend/runtime/debug/mail/20180413-165142-0679-0633.eml):
failed to open stream: Permission denied
The file is being created but with a slightly different name, for example 20180413-165142-0666-8857.eml (I can see it by time). I have no idea what is going on. Any suggestions?
Config file is simple:
common/main-local.php
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '#common/mail',
// 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,
],
And sending by this:
Yii::$app->mailer->compose('order', ['order' => $this])
->setTo(Yii::$app->params['adminEmail'])
->setFrom(Yii::$app->params['adminEmail'])
->setSubject('New order #' . $this->id)
->send();
And 'adminEmail' => 'admin#example.com',
Thanks for your attention.

How do I solve it this error HTTP 400 - Unable to verify your data submission in Yii2?

My Yii 2 application was progressing well until I received an unusual error bout a bad HTTP request.
HTTP 400 Unable to verify your data Submission.
I have looked it up and much of the literature indicates the cause being due to a CSRF issue. However, the CSRF components are all in place within the HTML head section and the hidden field is submitting the correct token.
Additional Info
Yii version = 2.0.12 App Basic
PHP version = 5.6
OS = Ubuntu
I have disabled all the security firmware of the host but I still get the error. Please help the site is in Prod already and I can not find how to solve this many thanks in advance.
web/config/main.php
$config = [
'components' => [
'session' => ['class' => 'yii\web\DbSession'],
'request' => [
'cookieValidationKey' => 'AAOSL2no3kbkJwRA4CNwDuB5g5T5_58t',
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
'user' => [
'identityClass' => 'app\models\User',
'enableAutoLogin' => true,
],
'errorHandler' => ['errorAction' => 'site/error'],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => $db,
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
],
'params' => $params,
];
if (YII_ENV_DEV) {
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
//'allowedIPs' => ['127.0.0.1', '::1'],
];
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
//'allowedIPs' => ['127.0.0.1', '::1'],
];
}
return $config;
As per Change Logs, BugFix and Enhancement related to CSRF cookie.
2.0.13 November 03, 2017 updates include
Bug #14542: Ensured only ASCII characters are in CSRF cookie value since binary data causes issues with ModSecurity and some browsers (samdark)
Enh #14087: Added yii\web\View::registerCsrfMetaTags() method that registers CSRF tags dynamically ensuring that caching doesn't interfere (RobinKamps).
2.0.14 February 18, 2018 updates include
Bug #15317: Regenerate CSRF token if an empty value is given
Enh #15496: (CVE-2018-6009): CSRF token is now regenerated on changing identity (samdark, rhertogh)(sammousa)
So update your framework to the latest version 2.0.14 use composer update via terminal inside your project root, once updated make sure you have the
<?= Html::csrfMetaTags () ?>
inside the <head> tag of the layout file you are using either main.php or any other custom name.
If still persist you can disable it for the specific action inside the beforeAction
public function beforeAction($action)
{
if ($action->id == 'action-name') {
$this->enableCsrfValidation = false;
}
return parent::beforeAction($action);
}
or for a specific controller by adding
public $enableCsrfValidation = false;
Add <?= Html::csrfMetaTags() ?> in your view, or add in layout(main.php)

Yii2 advanced accessing frontend from backend using alias

I trying to access frontend/web from backend menu using alias
yii:yii2 advanced
webserver : XAMPP
IDE:net beans
codes I modified:
C:\xampp\htdocs\advanced\common\config\aliases.php
Yii::setAlias('fronthome', dirname(dirname(__DIR__)) . '/frontend/web/');
C:\xampp\htdocs\advanced\backend\views\layouts\main.php
if (Yii::$app->user->isGuest) {
$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
$menuItems[] = ['label' => 'fronthome', 'url' => Yii::getAlias('#fronthome')];
but when accessing "fronthome" menu via backend menu; browser was returning the url:
http://localhost/advanced/backend/web/C:/xampp/htdocs/advanced/frontend/web
what i wanted browser to give:
http://localhost/advanced/frontend/web/
can some one please put some light... I searched but there was no elegant solution which I could find via alias.
Thanks
I got it working by making the below change
C:\xampp\htdocs\advanced\common\config\aliases.php
Yii::setAlias('fronthome', dirname(dirname(__DIR__)) . '/frontend/web/');
to
Yii::setAlias('fronthome', '../../frontend/web/');
As the links in the comments are outdated here is a snippet from the Yii2 docs:
Creating links from backend to frontend
Often it's required to create links from the backend application to the frontend application. Since the frontend application may contain its own URL manager rules you need to duplicate that for the backend application by naming it differently:
return [
'components' => [
'urlManager' => [
// here is your normal backend url manager config
],
'urlManagerFrontend' => [
// here is your frontend URL manager config
],
],
];
//After it is done, you can get an URL pointing to frontend like the following:
echo Yii::$app->urlManagerFrontend->createUrl(...);
current link to copy of relevant doc: https://yii2-framework.readthedocs.io/en/stable/guide/tutorial-advanced-app/
The way I have implemented this is to add a switch to my backend/config/bootstrap.php
switch (YII_ENV) {
case 'dev':
$frontend = 'https://my-domain.lan/';
break;
case 'test':
$frontend = 'https://my-domain.test/';
break;
case 'prod':
$frontend = 'https://my-domain.com/';
break;
}
and then in my backend/config/main.php I added the following
'urlManagerFrontend' => [
'class' => UrlManager::className(),
'enablePrettyUrl' => true,
'showScriptName' => false,
'baseUrl' => $frontend,
'rules' => [
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
]
],
and then where I want to use the frontend link:
echo Html::a('link',Yii::$app->urlManagerFrontend->createUrl('controller/view'))
Try using params.php
Add a key on params.php on your common/config folder
'frontendUrl' => 'http://frontendUrl/',
Then you could access it anywhere on your view by:
<?= Yii::$app->params['frontendUrl'] ?>
Hope this helps :)