找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 49|回复: 0

[维护日志] [2026-09-13] [功能] [后台群发邮件队列改造] - 后台发送通知接入邮件队列

[复制链接]
  • 打卡等级:本地老炮

9337

威望

7448

金钱

1万

贡献

管理员

自由的灵魂

积分
107434
主题
5630
回帖
26661
注册时间
2003-4-10
最后登录
2026-10-2
发表于 2026-9-13 08:00:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1、问题缘起

论坛后台“用户 → 发送通知”功能支持按用户组、积分、注册时间等条件筛选会员并批量发送邮件。原本是同步发送:每发一封邮件都会等待 SMTP 响应,再处理下一封。

核心问题:

问题说明
SMTP 并发限额QQ 域名邮箱短时间内最多允许 10 个并列连接,超过后域名邮箱会拒发(临时封禁)
同步阻塞群发时页面需等待所有邮件发送完毕,收件人多时直接卡死或超时
无失败重试发送失败仅记录日志,无法自动重试


独立问题汇总:

序号问题结论
1后台群发邮件为何同步阻塞?notifymembers() 函数中直接调用 sendmail()
2QQ 邮箱为何拒发?短时间超过 10 个并列连接,触发服务商频率限制
3能否复用现有邮件队列?可以,系统已有 common_mail_queue 队列表和 Crontab 处理脚本
4邮件内容中的 {username}、{regdate} 为何没替换?后台群发不支持模板变量,需手动替换
5邮件中 mailto: 链接为何异常?邮件系统对 <html> 标签处理异常,导致 mailto: 被拼接为相对路径


2、解决方案

(1)简要技术分析:

在后台群发邮件的 email 分支中,将同步 sendmail() 替换为写入邮件队列表,由 Crontab 定时任务异步逐封发送,彻底避开 QQ 邮箱的并列连接限制。

(2)修改文件列表:

操作文件路径
修改/source/admincp/admincp_members.php


(3)关键代码段:

定位:搜索 } elseif($_GET['notifymembers'] == 'email') {

修改前:

  1. } elseif($_GET['notifymembers'] == 'email') {
  2.     if(!sendmail("{$member['username']} <{$member['email']}>", $subject, $message.$addmsg)) {
  3.         runlog('sendmail', "{$member['email']} sendmail failed.");
  4.     }
  5. }
复制代码


修改后:

  1. } elseif($_GET['notifymembers'] == 'email') {
  2.     // 替换消息中的变量占位符
  3.     $user_message = str_replace(
  4.         array('{username}', '{regdate}'),
  5.         array($member['username'], dgmdate($member['regdate'], 'Y-m-d')),
  6.         $message.$addmsg
  7.     );
  8.     // 写入邮件队列,由 Crontab 异步发送
  9.     C::t('common_mail_queue')->insert(array(
  10.         'uid' => $member['uid'],
  11.         'toemail' => $member['email'],
  12.         'username' => $member['username'],
  13.         'subject' => $subject,
  14.         'message' => $user_message,
  15.         'dateline' => TIMESTAMP,
  16.         'status' => 0,
  17.     ));
  18. }
复制代码


3、最终实现效果

指标优化前优化后
发送方式同步发送,逐封等待写入队列,异步发送
页面阻塞收件人多时卡死秒级完成写入
QQ 邮箱限额超过 10 并列连接即拒发每 1 分钟发 1 封,完全合规
失败重试无最多重试 3 次(队列已有机制)
变量替换不支持,显示 {username}自动替换为实际值
邮箱链接被拼接为 https://域名/mailto:...改为纯文本,无解析问题

截图202609130302474933.webp

4、重要技术沉淀

需更新到固化摘要:

  1. 二十七、后台群发邮件队列改造(2026-09-13)

  2. 功能:后台“用户→发送通知”的邮件发送改为写入队列,异步发送
  3. 涉及文件:source/admincp/admincp_members.php
  4. 修改位置:notifymembers() 函数中 email 分支
  5. 关键机制:复用 common_mail_queue 队列表 + Crontab 异步处理
  6. 变量替换:{username}、{regdate} 在入队前手动替换
复制代码


踩坑点:

踩坑正确做法
直接同步调用 sendmail()写入 common_mail_queue,由 Crontab 异步发送
QQ 邮箱超过 10 并列连接会拒发队列每 1 分钟发 1 封,规避频率限制
模板变量 {username} 未替换入队前用 str_replace() 手动替换
邮件中 mailto: 链接异常去掉 <html>/<body> 标签,邮箱改为纯文本


5、进一步优化的可能性

  • 支持更多变量:在 str_replace() 中增加 {email}、{uid}、{credits} 等占位符
  • 条件筛选优化:后台筛选条件较多时,可考虑分批写入队列,避免单次请求超时
  • 队列进度可视化:在后台增加“队列状态”页面,显示待发数量、失败数量
  • 发送时间控制:避免在凌晨等时段发送,可设置队列处理时间窗口


不懂就搜!点此搜点拨论坛。如果本坛没有,请尝试点此问AI,或跟帖提问。
发帖前注意看置顶帖。
不定期借助AI对点拨论坛陈年老帖进行挖坟回复,打扰勿怪!
您的提问是对点拨论坛的最大贡献!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|点拨论坛 |网站地图

GMT+8, 2026-10-2 01:31 , Processed in 0.079217 second(s), 10 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表