官方文档地址:http://www.yiichina.com/doc/guide/2.0/tutorial-mailing。
昨晚在CSDN写了这篇博客,明明保存成功了,但是实际上却是搞丢了!这令我很郁闷,还是回到iteye这个虽然多年没更新过,但是可以传小附件,代码格式化也不错的博客。
做产品或项目时,我们很多时候需要给客户发邮件。比如密码重置、各种通知。
那么yii2.0自带的yii2-swiftmailer扩展当属我用过的最完美的扩展了。
不得不承认,虽然yii2.0在视图里穿插各种php代码令我崩溃,但它的设计模式的确令人咋舌,各类工具也是非常齐全。
官方文档能让我们看到这个扩展的基本用法,还是中文版的,所以我就不重复描述了。
我要说的是,在工作中,我们应该尽量抽象好这些接口,给项目或产品提供更通用、易懂、与底层无关的接口。比如这个发信的扩展,通过我们进行一层抽象,产品中调用我们适配好的接口,既可以不用关注“yii2-swiftmailer扩展”的使用方法,另外万一扩展不靠谱,我们还可以在接口中随时替换它,而不会影响到产品中的所有代码。
其实即使Yii的数据库操作,我们都可以扩展,没有做不到,只有我们想不到。
步骤一、在mail.php中(生产环境的配置,注意mail-local.php是测试环境才用到的配置)的componets数组中增加:
'class' => 'yii\swiftmailer\Mailer',
'useFileTransport' => false, //这句一定有,false发送邮件,true只是生成邮件在runtime文件夹下,不发邮件
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'smtp.163.com', //每种邮箱的host配置不一样
'username' => 'xxxx',
'password' => 'xxxx',
'port' => '25',
// 'encryption' => 'tls',
],
'messageConfig' => [
'charset' => 'UTF-8',
'from' => ['xxx@163.com' => '发件人姓名'],
],
],
步骤二、common中创建目录(就是windows中的文件夹)libs(这个名称是自定义的,也可以叫helper),libs中创建文件Email.php,其内容如下:
<?php
/**
* 利用Yii自带的swiftmailer发邮件,支持多人发送
* 可以利用模板发送,也可以发送纯文本或HTML,但只能3选1
* 优先级为纯文本>HTML>模板发送
*/
namespace common\libs;
class Email {
public static function sendEmail($option = []) {
$default = [
'text' => '',
'html' => '',
'tpl' => [
],
'subject' => '测试邮件',
'to' => [
],
'attachFiles' => [
],
];
$option = array_merge($default, $option);
$mail = \Yii::$app->mailer;
if ($option['text']) {
$mail = $mail->compose();
$mail->setTextBody($option['text']);
} else if ($option['html']) {
$mail = $mail->compose();
$mail->setHtmlBody($option['html']);
} else if ($option['tpl']) {
$mail = $mail->compose($option['tpl']['file'], $option['tpl']['var']);
} else {
return ['code' => 0, 'msg' => '参数有误!'];
}
$mail->setSubject($option['subject']);
foreach ($option['attachFiles'] as $fileAbsPath) {
$mail->attach($fileAbsPath);
}
$mail->setBcc($option['to']); // 密送,批量发送时,收件人看到邮件的收件人只写了自己
try {
$res = $mail->send();
if ($res) {
return ['code' => 0, 'msg' => '邮件发送成功!'];
} else {
var_dump($res);exit;
return ['code' => -1, 'msg' => '邮件发送失败:' . $mail->error()];
}
} catch (Swift_ConnectionException $e) {
return ['code' => -2, 'msg' => '邮件发送失败:' . $e->getMessage()];
}
}
}
第三步、可以在各种控制器、模型层里调用了。注意一下,MVC模式开发,复杂业务逻辑都应该放到Model层,我这里只是实例而已。在SiteController.php中新增如下Action:
public function actionEmail() {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$option = [
// 'text' => '测试纯文本邮件',
'html' => '<font color=red>测试HTML</font>',
'tpl' => [
'file' => 'email_tpl.html',
'var' => [
'name' => '丁华能',
],
],
'subject' => '测试HTML',
'to' => [
'xxx@qq.com' => 'dhn',
// 'xxx@163.com' => 'dhn163',
],
'attachFiles' => [
// \Yii::getAlias('@webroot') . '/uploads/test.docx',
],
];
$res = \common\libs\Email::sendEmail($option);
return $res;
}
步骤四、在SiteController.php的上层目录controllers所在的同级目录中创建目录mail/layouts,layouts中创建文件html.php(默认布局,跟main.php如出一辙):
<?php $this->beginPage()?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?=Yii::$app->charset?>" />
<?php $this->head()?>
</head>
<body>
<?php $this->beginBody()?>
<?=$content?>
<div class="footer">丁华能</div>
<?php $this->endBody()?>
</body>
</html>
<?php $this->endPage()?>
步骤五、在mail中创建email_tpl.html(yii渲染html是可以的,只要在render中带上后缀名):
<style type="text/css">
.red {color: red;}
</style>
<div class="red">
这是一封来自<?=$name?>的邮件。
</div>
一切OK,访问相应的网址,就能看到json返回,如果成功,去收件箱看邮件吧,另外,配置的发件人的发件箱也能看到。
注意:bcc在邮件的smtp协议中规定的是密送功能,比如邮件你需要通知到你的所有客户,但这些客户之间毫无联系,那么你不能发一封邮件,让大家都看到一长串的收件人。这就需要用到密送。如果是企业内部,则应该用抄送功能(信件中,所有收件人都能看到)。