批量发送邮件解决方案

首先批量发邮件肯定不能是循环得让用户等待发送完毕

我有两种实现,其实说白了本质都是一样得

1.定时器+队列

2.定时器+数据库表

还有一种我没有尝试,不过我个人感觉可能不太好,如果有大佬希望可以指点一二

那就是新开一个线程异步得一直发送,主线程则直接返回一个结果给用户即可(描述不精准勿怪)

我两种方式都采用了得,不过我得场景用数据库表更为恰当舒适,我就仅贴数据库表+定时器得实现代码了。

我是用laravel实现的

先使用命令php artisan make:command ProcessEmailQueue创建一个新的 Artisan 命令

首先先把需要的数据全部查出来存入数据库中

    public function sendEmail()
    {
        $authRepositories = new AuthRepositories();
        $historyRepositories = new HistoryRepositories();
        $userStr = $this->input['userIds'];
        $id = $this->input['historyId'];
        $content = $this->input['content'] ?? '';
        $type = $this->input['type'] ?? 0; //0-正常发送   1-定时发送
        $timing = $this->input['timing'] ?? null;
        if ($timing) {
            $timing = date('Y-m-d H:i:s', strtotime($timing));
        }
        $model = $historyRepositories->findVersion($id);
        $now = $model->now;
        $fileId = $model->file_id;
        $Filename = $model->label;
        $userIds = explode(',', $userStr);
        $users = $authRepositories->selectIn($userIds);
        $time = $model->updated_at;
        $bulkData = [];
        foreach ($users as $user) {
            $bulkData[] = [
                'username' => $user->username,
                'email' => $user->email,
                'now' => $now,
                'content' => $content,
                'timing' => $type == 1 ? $timing : null,
                'type' => $type,
                'time' => $time,
                'filename' => $Filename,
                'fileid' => $fileId
            ];
        }
        EmailSendModel::insert($bulkData);
    }

然后写定时任务(其实也就是刚刚创建一个新的 Artisan 命令类,laravel定时器我是通过这个命令类+crontab结合实现的)

class ProcessEmailQueue extends Command        //即时批量发送
{
    protected $signature = 'email:process-queue';
    protected $description = 'Process the regular email queue';

    /**
     * Execute the console command.
     *
     */
    public function handle(): void
    {
        set_time_limit(25);

        $fileRepositories = new FileRepositories();
        $reopository = new sendEmailReopository();
        $emailSend = EmailSendModel::query()->where('type', 0)->where('status', 0)->limit(10)->get();
        $success = [];
        $error = [];
        foreach ($emailSend as $model) {
            $collection = 'fileHtml' . $model->fileid;
            $historyHtml = $fileRepositories->findMongo($collection, $model->now)['content'] ?? '';
            $res = $reopository->send($model->username, $historyHtml, $model->filename, $model->time, $model->email);
            if ($res) {
                $success[] = $model->id;
            } else {
                $error[] = $model->id;
            }
        }
        if (!empty($success)) {
            EmailSendModel::query()->whereIn('id', $success)->update(['status' => 1]);
        }
        if (!empty($error)) {
            EmailSendModel::query()->whereIn('id', $error)->update(['status' => 2]);
        }
    }

}
class ProcessTimingEmailQueue extends Command    //定时发送
{
    protected $signature = 'email:process-timing-queue';
    protected $description = 'Process the timing email queue';

    /**
     * Execute the console command.
     *
     */
    public function handle(): void
    {
        set_time_limit(25);

        $fileRepositories = new FileRepositories();
        $reopository = new sendEmailReopository();
        $emailSend = EmailSendModel::query()
            ->where('type', 1)
            ->where('status', 0)
            ->where('timing', '<', Carbon::now('Asia/Shanghai'))
            ->limit(10)
            ->get();

        $success = [];
        $error = [];
        foreach ($emailSend as $model) {
            $collection = 'fileHtml' . $model->fileid;
            $historyHtml = $fileRepositories->findMongo($collection, $model->now)['content'] ?? '';
            $res = $reopository->send($model->username, $historyHtml, $model->filename, $model->time, $model->email);
            if ($res) {
                $success[] = $model->id;
            } else {
                $error[] = $model->id;
            }
        }
        if (!empty($success)) {
            EmailSendModel::query()->whereIn('id', $success)->update(['status' => 1]);
        }
        if (!empty($error)) {
            EmailSendModel::query()->whereIn('id', $error)->update(['status' => 2]);
        }
    }


}

然后再让crontab任务隔一段时间执行一次即可

* * * * * cd /wwwroot/file-web && php artisan email:process-queue
* * * * * sleep 30 && cd /wwwroot/file-web && php artisan email:process-queue

* * * * * cd /wwwroot/file-web && php artisan email:process-timing-queue
* * * * * sleep 30 && cd /wwwroot/file-web && php artisan email:process-timing-queue

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值