1、在vendor中創建目錄結構如下:
lvfk 此文件夾下可以由多個插件
└── mailerqueue 插件名稱
└── src 存放插件源碼
├── Mailer.php 繼承\yii\swiftmailer\Mailer,自定參數並正真發送Redis中存儲的郵件
└── Message.php 繼承\yii\swiftmailer\Message,改寫原有發送郵件功能爲存儲到Redis列表中
2、編寫Mail.php 和 Message.php
Message.php
<?php
/**
* Message.php.
* User: lvfk
* Date: 2018/2/3 0003
* Time: 16:40
* Desc:
*/
namespace lvfk\mailerqueue;
use yii\base\InvalidConfigException;
class Message extends \yii\swiftmailer\Message
{
/**
* 存儲郵件到redis隊列中
* @return mixed
* @throws InvalidConfigException
*/
public function queue(){
//檢測redis
$redis = \Yii::$app->redis;
if(empty($redis)){
throw new InvalidConfigException('redis not found in config');
}
//檢測mailer
$mailer = \Yii::$app->mailer;
if(empty($redis) || !$redis->select($mailer->db) || empty($mailer->key)){
throw new InvalidConfigException('mailer not found in config');
}
if(empty($mailer->key)){
throw new InvalidConfigException('parameter key not found in mailer config');
}
if(!$redis->select($mailer->db)){
throw new InvalidConfigException('parameter db not found in mailer config');
}
//發送
$message = [];
$message['from'] = array_keys($this->from);
$message['to'] = array_keys($this->getTo());
$message['cc'] = !empty($this->getCc())?array_keys($this->getCc()):[];
$message['bcc'] = !empty($this->getBcc())?array_keys($this->getBcc()):[];
$message['reply_to'] = !empty($this->getReplyTo())?array_keys($this->getReplyTo()):[];
$message['charset'] = $this->getCharset();
$message['subject'] = $this->getSubject();
//正文處理
$parts = $this->getSwiftMessage()->getChildren();
if(!is_array($parts) || count($parts) == 0){
$parts = [$this->getSwiftMessage()];
}
foreach ($parts as $part){
if(!$parts instanceof \Swift_Mime_Attachment){//判斷是否爲附件
switch ($part->getContentType()){//判斷內容格式
case "text/html":
$message['html_body'] = $part->getBody();
break;
case "text/plain":
$message['text_body'] = $part->getBody();
break;
}
}
if(!empty($message['charset'])){
$message['charset'] = $part->getCharset();
}
}
return $redis->rpush($mailer->key, json_encode($message));
}
}
Mail.php
<?php
/**
* Mailer.php.
* User: lvfk
* Date: 2018/2/3 0003
* Time: 17:06
* Desc:
*/
namespace lvfk\mailerqueue;
use yii\base\InvalidConfigException;
use yii\web\ServerErrorHttpException;
class Mailer extends \yii\swiftmailer\Mailer
{
//指定到我們自定義的Message類
public $messageClass = 'lvfk\mailerqueue\Message';
public $db = '0';//默認爲redis第0個數據庫
public $key = 'mails';//默認爲redis的存儲隊列名字
/**
* 設置數據
* @param $messageObj
* @param $message
* @return bool
*/
private function setMessage($messageObj, $message){
if (empty($messageObj)) {
return false;
}
if (!empty($message['from']) && !empty($message['to'])) {
$messageObj->setFrom($message['from'])->setTo($message['to']);
if (!empty($message['cc'])) {
$messageObj->setCc($message['cc']);
}
if (!empty($message['bcc'])) {
$messageObj->setBcc($message['bcc']);
}
if (!empty($message['reply_to'])) {
$messageObj->setReplyTo($message['reply_to']);
}
if (!empty($message['charset'])) {
$messageObj->setCharset($message['charset']);
}
if (!empty($message['subject'])) {
$messageObj->setSubject($message['subject']);
}
if (!empty($message['html_body'])) {
$messageObj->setHtmlBody($message['html_body']);
}
if (!empty($message['text_body'])) {
$messageObj->setTextBody($message['text_body']);
}
return $messageObj;
}
return false;
}
/**
* 發郵件
*/
public function process(){
//檢測redis
$redis = \Yii::$app->redis;
if(empty($redis)){
throw new InvalidConfigException('redis not found in config');
}
//獲取郵件列表,併發送
if($redis->select($this->db) && $messages = $redis->lrange($this->key, 0, -1)){
$messageObj = new Message();
foreach ($messages as $message){
$message = json_decode($message, true);
if(empty($message) || !$this->setMessage($messageObj, $message)){
throw new ServerErrorHttpException('message error');
}
if($messageObj->send()){//發送成功之後,刪除隊列中數據
$redis->lrem($this->key, -1, json_encode($message));
}
}
}
return true;
}
}
3、在web.php中配置,業務代碼中即可使用自定義插件
'aliases' => [//在配置添加,實現mailer中class可以找到我們的自定義插件類
'@lvfk/mailerqueue' => '@vendor/lvfk/mailerqueue/src'
],
以下兩個在components數組中配置:
//自定義mailer組件
'mailer' => [
'class' => 'lvfk\mailerqueue\Mailer',
'db' => 9,//設置redis使用庫
'key' => 'mails',//redis 列表名字
'useFileTransport' => false,
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'smtp.163.com',
'username' => '[email protected]',
'password' => 'xxxx',
'port' => '465',
'encryption' => 'ssl',
],
],
//redis 操作組件配置
'redis' => [
'class' => 'yii\redis\Connection',
'hostname' => 'localhost',
'port' => 6379,
'database' => 9,
'password' => '123456',
],
4、業務代碼中調用//先發送到redis,異步發送
\Yii::$app->mailer->compose('reply', [
'username'=>$username,
'userpass'=>$userpass,
'useremail'=>$this->useremail,
'time'=>$time,
'token'=>$token
])
->setSubject('電子郵箱註冊激活')
->setFrom(['[email protected]'=>'lvfk'])
->setTo($this->useremail)
->queue();
5、異步發送,使用yii2的commands命令5.1、由於yii2的command命令使用的是配置console.php而不是web.php,因此要把第3步中的三個配置移到console.php中
5.2、在commands編寫文件MailerController.php
class MailerController extends Controller
{
/**
* 發送郵件
*/
public function actionSend()
{
\Yii::$app->mailer->process();
var_dump('發送完畢');
}
}
5.3、發送在項目更目錄中執行:./yii mailer/send
6、利用crontab任務定時發送郵件
*/3 * * * * /var/www/yii2/yii mailer /send >> /var/log/mailer.log
7、插件提交composer
7.1、在github網站上新建一個新庫yii2_mailerqueue
7.2、把新庫克隆到本地
git clone https://github.com/Justshunjian/yii2_mailerqueue.git
7.3、把插件src複製到克隆到本地的yii2_mailerqueue
cp -r /var/www/yii2-shop/vendor/lvfk/mailerqueue/src/ yii2_mailerqueue/
7.4、編寫composer.json
{
"name": "lvfk/mailerqueue",
"type": "yii2-extension",
"description": " async mailer by swiftmailer and redis base on yii2",
"keywords": ["yii2","redis","async","mailer"],
"license": "MIT",
"support": {
"issues":"https://github.com/Justshunjian/yii2_mailerqueue/issues",
"forum":"",
"source":"https://github.com/Justshunjian/yii2_mailerqueue"
},
"authors":[
{
"name":"lvfk",
"email":"[email protected]"
}
],
"require":{
"yiisoft/yii2":"*",
"yiisoft/yii2-redis":"~2.0.0"
},
"autoload":{
"psr-4":{
"lvfk\\mailerqueue\\":"src/"
}
}
}
7.5、提交到github7.6、進入composer官網https://packagist.org/,使用github帳號登錄
7.7、登錄成功之後,點擊右上角submit
A、把待提交項目github的地址拷貝到網頁文本框
https://github.com/Justshunjian/yii2_mailerqueue.git
B、經過A就已經提交成功,但是在頁面上還需要根據提示設置當github更新之後,composer這步數據自動更新
curl -XPOST -H'content-type:application/json' 'https://packagist.org/api/update-package?username=Justshunjian&apiToken=TOKEN' -d'{"repository":{"url":"https://github.com/Justshunjian/yii2_mailerqueue.git"}}'
其中TOKEN在Profile中的Your API Token中隱藏的8、下載安裝並使用
8.1、下載安裝
composer require lvfk/mailerqueue
8.2、配置有微調,業務代碼使用無需調整
由於是下載安裝的,因此配置文件中的3個配置中別名設置aliases不用設置了,因爲是composer自動加載的,只需保留
以下兩個在components數組中配置:
//自定義mailer組件
'mailer' => [
'class' => 'lvfk\mailerqueue\Mailer',
'db' => 9,//設置redis使用庫
'key' => 'mails',//redis 列表名字
'useFileTransport' => false,
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'smtp.163.com',
'username' => '[email protected]',
'password' => 'xxxx',
'port' => '465',
'encryption' => 'ssl',
],
],
//redis 操作組件配置
'redis' => [
'class' => 'yii\redis\Connection',
'hostname' => 'localhost',
'port' => 6379,
'database' => 9,
'password' => '123456',
],
9、完成