Laravel隊(duì)列批量發(fā)送郵件,限制調(diào)用頻率 支持QQ郵箱/163郵箱/谷歌郵箱/騰訊企業(yè)郵箱

項(xiàng)目需要使用郵件拓展業(yè)務(wù),要用到隊(duì)列群發(fā)的功能,特此記錄一下

為了防止郵件發(fā)送過多導(dǎo)致信件發(fā)送失敗,同時(shí)使用了兩種解決方法

1、使用了多個(gè)郵箱批量發(fā)送郵件

2、限制了郵件發(fā)送任務(wù)的調(diào)用頻率。

首先創(chuàng)建一個(gè)隊(duì)列任務(wù):

php artisan make:job SendMail

隊(duì)列的環(huán)境配置請(qǐng)參考laravel的官方文檔

建議在開發(fā)環(huán)境下將.env中配置為 QUEUE_CONNECTION=sync 方便調(diào)試,生產(chǎn)環(huán)境下再配置為redis驅(qū)動(dòng)

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redis;

class SendMail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $content;
    protected $email;
    protected $user;
    protected $job_id;
    public $timeout =120;  //120秒超時(shí)

    /**
     * Create a new job instance.
     *
     * @param $job_id
     * @param $content
     * @param $email
     * @param $user
     */
    public function __construct($job_id, $content, $email, $user)
    {
        $this->content = $content;
        $this->email = $email;
        $this->user = $user;
        $this->job_id = $job_id;
    }

    /**
     * Execute the job.
     * @return void
     */
    public function handle()
    {
        //限制任務(wù)的調(diào)用:每20秒鐘只調(diào)用10次
       Redis::throttle('key')->allow(10)->every(20)->then(function () {
            try {
                $this->handleEmail();//具體的發(fā)送郵件方法
            } catch (\Exception $e) {
                Log::error('queue error : ' . $e->getMessage());//打印錯(cuò)誤日志
            }
        }, function () {
            return $this->release(10);
        });
    }

    /**
     * 發(fā)送郵件
     */
    function handleEmail()
    {
        //備份原有Mailer
        $backup = Mail::getSwiftMailer();
        $user = $this->user; //獲取用戶的姓名
        $email = $this->email;//獲取用戶的郵箱地址
        $content = $this->content;//獲取郵件模板的內(nèi)容
        //使用正則表達(dá)式替換相應(yīng)的用戶的姓名
        $email_content = preg_replace('/\{\{s\}\}/', $user->name, $content->content);  //模板內(nèi)容
        $email_theme = preg_replace('/\{\{s\}\}/', $user->name, $content->theme); //郵件主題
        $email_sign = preg_replace('/\{\{s\}\}/', $user->name, $content->sign);;  //郵件簽名
        $email_sign = preg_replace('/\{\{t\}\}/', date('Y-m-d'), $email_sign);;  //郵件簽名{{t}}

        // 設(shè)置郵箱賬號(hào),支持qq郵箱/163郵箱/谷歌郵箱/騰訊企業(yè)郵箱
        if ($email->type == 'qq') {
            $transport = new \Swift_SmtpTransport('smtp.qq.com', 465, 'ssl');
        } else if ($email->type == 'gmail') {
            $transport = new \Swift_SmtpTransport('smtp.gmail.com', 465, 'ssl');
        }  else if ($email->type == '163') {
            $transport = new \Swift_SmtpTransport('smtp.163.com', 465, 'ssl');
        } else if ($email->type == 'exmail') {
            $transport = new \Swift_SmtpTransport('smtp.exmail.qq.com', 465, 'ssl');
        } else {
            throw  new AdminApiException('郵箱類型不支持!');
        }
        $transport->setUsername($email->email);
        $transport->setPassword($email->secret);

        $mailer = new \Swift_Mailer($transport);

        Mail::setSwiftMailer($mailer);

        Mail::send('emails.kol.index',
            ['content' => $email_content, 'email_sign' => $email_sign],
            function ($message) use ($email_theme, $user, $email) {
                $message->from($email->email, $email->email);
                $message->subject($email_theme);
                $message->to($user->email);
            });
        // 發(fā)送后還原
        Mail::setSwiftMailer($backup);
    }
}

由于限制了隊(duì)列的調(diào)用頻率,所以任務(wù)失敗的次數(shù)是無法計(jì)算的,需要配合超時(shí)來做

我將任務(wù)超時(shí)時(shí)間設(shè)置為120秒

隊(duì)列的調(diào)用

public function store(Request $request)
{
    ..........
    foreach ($job->user as $user) {
        $email = $emails->random(); //隨機(jī)一個(gè)郵箱
        //傳遞郵件的模板、郵箱和用戶作為一個(gè)單獨(dú)的發(fā)送任務(wù)
        SendMail::dispatch($job_id, $template, $email, $user);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 隊(duì)列 簡(jiǎn)介 laravel 的隊(duì)列服務(wù)對(duì)各種不同的后臺(tái)隊(duì)列服務(wù)提供了統(tǒng)一的 API。隊(duì)列允許你延遲執(zhí)行消耗時(shí)間的任...
    Dearmadman閱讀 21,015評(píng)論 7 26
  • Laravel框架一:原理機(jī)制篇 Laravel作為在國(guó)內(nèi)國(guó)外都頗為流行的PHP框架,風(fēng)格優(yōu)雅,其擁有自己的一些特...
    Mr_Z_Heng閱讀 3,932評(píng)論 0 13
  • 1 環(huán)境 Laravel是一種類似ThinkPHP的php框架,封裝的諸多功能可以很方便的使用。隊(duì)列Queue便是...
    bbdlg閱讀 12,708評(píng)論 7 10
  • feisky云計(jì)算、虛擬化與Linux技術(shù)筆記posts - 1014, comments - 298, trac...
    不排版閱讀 4,302評(píng)論 0 5
  • 我想把對(duì)每個(gè)領(lǐng)域的害怕都表達(dá)出來,通過占星指引心理恐懼的表達(dá): 水土相位: 記得很小的時(shí)候,學(xué)習(xí),寫作文,考試答卷...
    拉鋸之戰(zhàn)閱讀 565評(píng)論 0 2

友情鏈接更多精彩內(nèi)容