This is an old revision of the document!
Yii 2 Email Tools
Setup Emailer (Swiftmailer)
Setup mailer in app/config/main.php
(or main-local.php
).
- Basic application:
app/config/web.php
app/config/console.php
- Advanced application:
common/config/main.php
.- NOTE: you can also find settings in:
environments/prod/common/config/main-local.php
environments/dev/common/config/main-local.php
return [ 'components' => [ ... 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', // Directory that contains the view files // for composing mail messages. Defaults to '@app/mail' 'viewPath' => '@common/mail', // Send all mail messages to a file by default. // The messages get stored locally under '@app/runtime/mail' 'useFileTransport' => true, //'fileTransportPath' => '@runtime/mail', // Send all mail messages as real emails. // Set 'useFileTransport' to false, // and configure a transport for the mailer. // 'useFileTransport' => false, //'transport' => [ // 'class' => 'Swift_SmtpTransport', // 'host' => 'localhost', // 'username' => 'username', // 'password' => 'password', // 'port' => '587', // 'encryption' => 'tls', //], ], ], ];
To send an email directly from a controller (no form/view):
public function sendMessage($srcMail, $srcName, $dstEmail, $subject, $textBody) { $success = Yii::$app->mailer->compose() ->setFrom([$srcMail => $srcName]) ->setTo($dstEmail) ->setSubject($subject) ->setTextBody($textBody) ->send(); return $success; }
To send an email with a form (view), you may use the following code in a controller. Eg: controller @app/controllers/SiteController
:
class SiteController extends \yii\web\Controller { /** * @inheritdoc */ public function behaviors() { return [ 'access' => [ 'class' => AccessControl::className(), 'rules' => [ //... [ // any user (authenticated or not) 'actions' => ['captcha', ...], 'allow' => true, ], ], ], ]; } //... private function sendMessage($srcMail, $srcName, $dstEmail, $subject, $textBody) { $success = Yii::$app->mailer->compose('contact/html' /* view */, ['contactForm' => $form] /* view params */) ->setFrom('from@domain.com') ->setTo($form->email) ->setSubject($form->subject) ->send(); return $success; }
View @app/views/site/contact
:
<?php use yii\helpers\Html; use yii\bootstrap\ActiveForm; use yii\captcha\Captcha; /* @var $this yii\web\View */ /* @var $form yii\bootstrap\ActiveForm */ /* @var $model app\models\ContactForm */ $this->title = 'Contact'; $this->params['breadcrumbs'][] = $this->title; ?> <div class="site-contact"> <h1><?= Html::encode($this->title) ?></h1> <?php if (Yii::$app->session->hasFlash('contactFormSubmitted')): ?> <div class="alert alert-success"> Thank you for contacting us. We will respond to you as soon as possible. </div> <p> Note that if you turn on the Yii debugger, you should be able to view the mail message on the mail panel of the debugger. <?php if (Yii::$app->mailer->useFileTransport): ?> Because the application is in development mode, the email is not sent but saved as a file under <tt><?= Yii::getAlias(Yii::$app->mailer->fileTransportPath) ?></tt>. Please configure the <tt>useFileTransport</tt> property of the <tt>mail</tt> application component to be false to enable email sending. <?php endif; ?> </p> <?php else: ?> <p> If you have business inquiries or other questions, please fill out the following form to contact us. Thank you. </p> <div class="row"> <div class="col-lg-5"> <?php $form = ActiveForm::begin(['id' => 'contact-form']); ?> <?= $form->field($model, 'name') ?> <?= $form->field($model, 'email') ?> <?= $form->field($model, 'subject') ?> <?= $form->field($model, 'body')->textArea(['rows' => 6]) ?> <!-- // To regenerate new captcha after each refresh, call getVerifyCode(). // See: http://www.yiiframework.com/forum/index.php/topic/17638-captcha-code-not-changing --> <?php $this->context->createAction('captcha')->getVerifyCode(true) ?> <?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [ 'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>', ]) ?> <div class="form-group"> <?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?> </div> <?php ActiveForm::end(); ?> </div> </div> <?php endif; ?> </div>
See also:
Email Model
Create model @app/models/Email
:
<?php namespace app\models; use Yii; use yii\base\Model; /** * Email is the model behind simple email messages. */ class Email extends Model { public $name; public $email; public $subject; public $body; //public $verifyCode; /** * @return array the validation rules. */ public function rules() { return [ // name, email, subject and body are required [['name', 'email', 'subject', 'body'], 'required'], // email has to be a valid email address ['email', 'email'], // verifyCode needs to be entered correctly //['verifyCode', 'captcha'], ]; } /** * @return array customized attribute labels */ public function attributeLabels() { return [ //'verifyCode' => 'Verification Code', ]; } /** * Sends an email to the specified email address using the information collected by this model. * @param string $dstEmail - the target email address * @return boolean whether the model passes validation */ public function sendMessage($dstEmail) { if ($this->validate()) { Yii::$app->mailer->compose() ->setTo($dstEmail) ->setFrom([$this->email => $this->name]) ->setSubject($this->subject) ->setTextBody($this->body) ->send(); return true; } else { return false; } } }
Console Email
Create a console action to email:
<?php //---------------------------------------------------------------------------------------- // Controller: /[console/controllers|command]/EmailNotificationController.php // Usage: // === Execute as a console script === // $ yii email-notification/send-email dstEmail=info@acme.com workOrderId=1 // //---------------------------------------------------------------------------------------- namespace app\commands; use Yii; use yii\console\Controller; use app\models\Email; use app\models\WorkOrder; use yii\helpers\Console; /** * */ class EmailNotificationController extends Controller { /** * This command send email message. * @param string $message the message to be echoed. */ public function actionSendEmail($dstEmail, $workOrderId) { defined('STDIN') or define('STDIN', fopen('php://stdin', 'r')); defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w')); // strip field name: dstEmail=info@acme.com if (stripos($dstEmail, '=') !== false) { $params['dstEmail'] = explode('=', $dstEmail); //, -1 /* last item */); $dstEmail = $params['dstEmail'][1]; } // strip field name: workOrderId=1 if (stripos($workOrderId, '=') !== false) { $params['workOrderId'] = explode('=', $workOrderId); //, -1 /* last item */); $workOrderId = $params['workOrderId'][1]; } $this->stdout("\n"); $this->stdout("Dest Email: " . $dstEmail . "\n", Console::BOLD); $this->stdout("Work Order: " . $workOrderId . "\n", Console::BOLD); $this->stdout("\n"); if (($workOrder = WorkOrder::findOne($workOrderId)) !== null) { $workOrderID = str_pad($workOrder->id, 6, "0", STR_PAD_LEFT); // Setup email data $model = new Email(); $model->name = Yii::$app->params['companyNameShort']; $model->email = Yii::$app->params['adminEmail']; $model->subject = "Work Order [{$workOrderID}]: {$workOrder->task->name}"; $model->body = "There is a new work order: \n" . "------------------------------------------------------------------\n" . "Work Order [{$workOrderID}]: {$workOrder->task->name}\n" . "Date: " . date("M-d-Y", strtotime($workOrder->date)) . "\n" . "Location: {$workOrder->property->name}\n" . "------------------------------------------------------------------\n\n" . "Details: \n{$workOrder->notes}\n"; //$model->verifyCode; $data['name'] = Yii::$app->params['companyNameShort']; $data['email'] = Yii::$app->params['adminEmail']; $data['subject'] = "Work Order [{$workOrderID}]: {$workOrder->task->name}"; $data['body'] = "There is a new work order: \n" . "Work Order [{$workOrderID}]: {$workOrder->task->name}\n" . "Date: " . date("M-d-Y", strtotime($workOrder->date)) . "\n" . "Location: {$workOrder->property->name}\n" . "Details: \n{$workOrder->notes}\n"; //$data['verifyCode'] = ''; // Send email //if ($model->load($data) && $model->sendMessage($dstEmail)) { //if ($model->load($data)) { if ($model->sendMessage($dstEmail)) { $this->stdout("--------------------------------------\n", Console::BOLD); $this->stdout("Email Notification Sent\n", Console::BOLD); $this->stdout("--------------------------------------\n", Console::BOLD); $this->stdout("Subject: " . $data['subject'] . "\n", Console::BOLD); $this->stdout("Message:\n" . $data['body'] . "\n", Console::BOLD); $this->stdout("--------------------------------------\n", Console::BOLD); $this->stdout("Mailer: ".print_r(Yii::$app->mailer, true)."\n", Console::BOLD); $this->stdout("--------------------------------------\n", Console::BOLD); return Controller::EXIT_CODE_NORMAL; } else { $this->stdout("Email Notification NOT Sent\n - Unable to post data for: Work Order ID " . $workOrderId . "\n", Console::BOLD); return Controller::EXIT_CODE_ERROR; } /*} else { //return $this->render('contact', [ // 'model' => $model, //]); //return $this->goHome(); // nothing to render $this->stdout("Email Notification NOT Sent\nUnable to load data:\n" . $data['subject'] . "\n" . $data['body'] . "\n", Console::BOLD); return Controller::EXIT_CODE_NORMAL; // nothing to render }*/ } else { $this->stdout("Email Notification NOT Sent\n - Work Order ID " . $workOrderId . " not found\n", Console::BOLD); return Controller::EXIT_CODE_ERROR; } } }
Running Console Action From CLI
Call console action from command line:
$ yii email-notification/send-email dstEmail=info@acme.com workOrderId=1
Running Console Action From View
Call console action from web view: @app/views/WorkOrder/view
... <?= Html::a(Yii::t('app', 'Notify by Email'), ['work-order/send-email', 'id' => $model->id], ['class' => 'btn btn-primary'] ) ?> ... Flash Alert Zone <div class="col-lg-12"> <?php if(Yii::$app->session->hasFlash('success')): ?> <div class="alert alert-success" role="alert"> <?= Yii::$app->session->getFlash('success'); ?> </div> <?php endif; ?> <?php if(Yii::$app->session->hasFlash('error')): ?> <div class="alert alert-danger" role="alert"> <?= Yii::$app->session->getFlash('error'); ?> </div> <?php endif; ?> </div>
@app/controllers/WorkOrderController
<?php namespace app\controllers; use Yii; use app\models\WorkOrder; use app\commands\EmailNotificationController; ... /** * WorkOrderController implements the CRUD actions for WorkOrder model. */ class WorkOrderController extends Controller { ... public function actionSendEmail($id) { // use app\commands\EmailNotificationController; $command = new EmailNotificationController("", ""); // "" values are a required placeholder $command->actionSendEmail(Yii::$app->params['taskAssigneeEmail'], $id); // $dstEmail, $workOrderId Yii::$app->session->setFlash('success', "Sent Email"); return $this->redirect(['view', 'id' => $id]); } }
Send PDF Attachment Through Email
Assuming you have created a PDF document using TCPDF, you can attach it to an email message as follows:
function sendEmail($model, $pdf, $filename) { // Setup email content $emailSubj = "Report by Email"; $emailBody = "Hi {$model->customer->contact}, \n\n"; $emailBody .= "Please see the included attachment.\n\n"; $emailBody .= "Sales Team"; // Attach PDF document as MIME multipart $attachment = $pdf->Output("{$filename}", 'S'); // document as a string // Create and send email message Yii::$app->mailer->compose() ->setFrom([Yii::$app->params['adminEmail'] => Yii::$app->params['companyName']]) ->setTo($model->customer->email) ->setBcc([ //Yii::$app->params['adminEmail'] => Yii::$app->params['companyNameShort'] . ' Support', Yii::$app->params['debugEmail'] => 'Debug Email' ]) ->setSubject($emailSubj) ->setTextBody($emailBody) ->attachContent($attachment, ['fileName' => $filename, 'contentType' => 'application/pdf']) ->send(); }