Để giúp ứng dụng hay website tiếp cận đến gần hơn với người dùng thì việc gửi mail thông báo hay chạy một chiến dịch nào đó là điều không thể thiếu. Yii2 đã hỗ trợ soạn thảo và gửi email thông qua một tiện ích mở rộng được cài đặt sẵn là yii2-swiftmailer.

Cấu hình gửi mail

Để cấu hinh gửi mail chung cho cả backend hay frontend trong yii2 advanced thì các đồng dev cần điều chỉnh các thông số sau trong common/config/main-local.php

return [
    //....
    'components' => [
        'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            'useFileTransport' => false,
            'transport' => [
                'class' => 'Swift_SmtpTransport',
                'encryption' => 'tls',
                'host' => 'your_mail_server_host',
                'port' => 'your_smtp_port',
                'username' => 'your_username',
                'password' => 'your_password',
            ],             
        ],
    ],
];

Ở đây tại hạ ví dụ sẽ gửi mail thông qua host của google sẽ cấu hình như sau 

return [
    //....
    'components' => [
        'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            'viewPath' => '@common/mail',
            'useFileTransport' => false,
            'transport' => [
                'class' => 'Swift_SmtpTransport',
                'encryption' => 'tls',
                'host' => 'smtp.gmail.com',
                'port' => '587',
                'username' => '[email protected]',
                'password' => 'mật khẩu của emai anh em đã tạo',
            ],             
        ],
    ],
];

Gửi mail

Sau khi đã cấu hình xong, tại hạ sẽ tạo 1 action sendMail trong SiteController với nội dung như sau

<?php
namespace frontend\controllers;

use Yii;
use yii\base\InvalidArgumentException;
use yii\web\BadRequestHttpException;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;

/**
 * Site controller
 */
class SiteController extends Controller
{
    //...............

    public function actionSendmail(){
        Yii::$app->mailer->compose() // Sử dụng nếu có template
        ->setFrom('[email protected]') // Mail sẽ gửi đi
        ->setTo('[email protected]') // Mail sẽ nhận
        ->setSubject('Demo gửi mail trong Yii2') // tiêu đề mail
        ->setHtmlBody('<b>Nội dung gửi mail trong Yii2</b>') // Nội dung mail dạng Html nếu không muốn dùng html thì có thể thay thế bằng setTextBody('Nội dung gửi mail trong Yii2') để chỉ hiển thị text
        ->send();
    }
}

Lưu ý* : Các đồng dev nếu sử dụng gmail thì cần phải mở các chế độ bảo mật để có thể truy cập email trong quá trình gửi. Anh em đồng dev truy cập vào https://www.google.com/settings/security/lesssecureapps và https://accounts.google.com/b/0/UnlockCaptcha để tắt hết bảo mật đi nhé =)) thì mới dùng để test gửi mail được.

Sau đó các đồng dev chạy Url http://localhost/advanced/site/sendmail trên trình duyệt và kiểm tra hòm thư xem nhận được thư không nhé. Ở đây tai hạ đã nhận được email trong hòm thư [email protected]

yii2 sendmail

yii2 sendmail

OK, đó là gửi 1 mail đơn lẻ, nếu các đồng dev gửi nhiều mail 1 lúc thì đổi lại code như sau 

Ví dụ ở đây tại hạ muốn gửi cho 2 email là [email protected] và v[email protected]

<?php
namespace frontend\controllers;

use Yii;
use yii\base\InvalidArgumentException;
use yii\web\BadRequestHttpException;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;

/**
 * Site controller
 */
class SiteController extends Controller
{
    //...............

    public function actionSendmail(){
        $messages = [];
        $users = [
                    '[email protected]',
                    '[email protected]'
                ];
        foreach ($users as $user) {
            $messages[] = Yii::$app->mailer->compose()
            ->setFrom('[email protected]')
            ->setTo($user)
            ->setSubject('Demo gửi multi mail trong Yii2')
            ->setHtmlBody('<b>Nội dung gửi multi mail trong Yii2</b>');
        }
        Yii::$app->mailer->sendMultiple($messages);
    }
}

Và kết quả là 

yii2 sendmail

Gửi mail với mẫu có sẵn

Để tiện cho việc không phải thay đổi nội dung mỗi khi gửi một chiến dịch mail nào đó thì Yii2 đã cung cấp cho các đồng dev xây dựng các template email thông qua thư mục mail trong common. Ví dụ ở đây tại hạ sẽ tạo 1 template là register để thông báo đăng ký tài khoản thành công như sau

Trong thư mục mail, tại hạ tạo 1 file là register.php như sau

yii2 sendmail

Tiếp đó tại hạ sửa lại action Sendmail 

<?php
namespace frontend\controllers;

use Yii;
use yii\base\InvalidArgumentException;
use yii\web\BadRequestHttpException;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;

/**
 * Site controller
 */
class SiteController extends Controller
{
    //...............

    public function actionSendmail(){
        Yii::$app->mailer->compose('register',['name' => 'Voi xanh']) // giống như render view từ controller, tham số đầu là view/template, tham số thứ 2 là data được truyền ra view để hiển thị
            ->setFrom('[email protected]')
            ->setTo('[email protected]')
            ->setSubject('Đăng ký tài khoản thành công')
            ->send();
    }
}

Và kết quả có được

yii2 sendmail

Ngoài ra, các đồng dev có thể tùy chỉnh kiểu muốn gửi dạng text hoặc html cho template có sẵn như sau

Yii::$app->mailer->compose([
    'html' => 'contact-html', // là file contact-html.php trong common/mail
    'text' => 'contact-text', // là file contact-text.php trong common/mail
]);

Gửi mail với file đính kèm 

Để gửi mail với file đính kèm các đồng dev sử dụng đoạn mã sau

$message = Yii::$app->mailer->compose();

// attach file from local file system
$message->attach('/path/to/source/file.pdf');

// create attachment on-the-fly
$message->attachContent('Attachment content', ['fileName' => 'attach.txt', 'contentType' => 'text/plain']);

Ví dụ ở đây tại hạ có 1 file là voixanh.doc đặt ở ngoài cùng của thư mục dự án 

yii2 sendmail

Trong phần actionSendmail tại hạ đổi lại như sau

public function actionSendmail(){

        Yii::$app->mailer->compose()
            ->setFrom('[email protected]')
            ->setTo('[email protected]')
            ->setSubject('Đăng ký tài khoản thành công')
            ->attach(dirname(dirname(__DIR__)).'/voixanh.docx') // dirname(dirname(__DIR__)) -> /var/www/html/advanced
            ->attachContent('Attachment content', ['fileName' => 'voixanh.docx', 'contentType' => 'text/plain'])
            ->send();
    }

và kết quả nhận được 

yii2 sendmail

Tổng kết 

Trên đây tại hạ đã giới thiệu cho các đồng dev các gửi mail trong Yii2 như thế nào, trong các bài biết sắp tới tại hạ sẽ demo thêm về việc sử dụng các service mail bên thứ 3 khác như SES AWS, Mail Gun, Sendgrid .... để anh em đồng dev được tiếp cận thêm. Mặc dù việc gửi mail được là 1 chuyện nhưng làm thế nào để giảm tải cho server khi có nhiều email cần phải được gửi thì lại là chuyện khác. Tại hạ sẽ đề cập tới việc sử dụng các Queue Service để nhận và phân phối các mail tới đích để giảm tải cho server ở bài tiếp sau nhé. Bài viết còn nhiều thiếu sót mong anh em đồng dev thông cảm. Cảm ơn đã ghé đọc!