活力39282
在线时间13640 小时
阅读权限200
管理员
自由的灵魂
- 积分
- 107434
- 主题
- 5630
- 回帖
- 26661
- 注册时间
- 2003-4-10
- 最后登录
- 2026-10-2
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1、问题缘起
论坛原有回复审核邮件通知功能,但新主题进入审核时管理员只能通过登录后台查看“内容审核”列表才能发现,缺乏主动提醒。同时,无论是主题还是回复审核,邮件中仅显示“系统审核规则”,无法告知管理员具体触发的敏感词,导致审核响应滞后,管理员需自行猜测审核原因。
核心需求:
- 主题进入审核时即时邮件通知管理员
- 回复审核邮件中同样显示敏感词详情
- 邮件中需明确标注触发的具体敏感词(复用系统已匹配的结果,避免重复检测)
- 附上后台审核页面链接,方便一键跳转处理
- 考虑到审核的紧迫性,所有审核邮件均即时发送(不经过队列)
2、解决方案
(1)简要技术分析:
Discuz! 内核在敏感词处理时,discuz_censor::instance()->words_found 属性已存储本次匹配到的敏感词列表。在主题和回复的审核判断处获取该对象,提取敏感词后通过 sendmail 即时发送邮件给管理员。
(2)修改文件列表:
| 操作 | 文件路径 | | 修改 | /source/include/post/post_newthread.php | | 修改 | /source/include/post/post_newreply.php |
(3)关键代码段:
主题审核邮件代码(post_newthread.php):
- // ==================== 主题审核邮件通知管理员 ====================
- if ($modthread->param('modnewthreads')) {
- // 获取命中的敏感词
- $sensitive_words = '';
- $censor = discuz_censor::instance();
- if (!empty($censor->words_found)) {
- $sensitive_words = implode(', ', array_unique($censor->words_found));
- }
-
- $admin_email = 'admin@dianbo.org';
- $admin_subject = '【论坛审核】有主题需要审核';
- $admin_message = "<html><body>";
- $admin_message .= "<p>论坛有一条新主题触发了审核规则,已进入审核区,请及时处理。</p>";
- $admin_message .= "<hr>";
- $admin_message .= "<p><strong>触发时间:</strong>" . date('Y-m-d H:i:s') . "</p>";
- $admin_message .= "<p><strong>发帖用户:</strong>" . $_G['username'] . " (UID: " . $_G['uid'] . ")</p>";
- $admin_message .= "<p><strong>主题标题:</strong>" . htmlspecialchars($subject) . "</p>";
- $admin_message .= "<p><strong>内容预览:</strong><br>" . nl2br(htmlspecialchars(cutstr($message, 300))) . "</p>";
- if (!empty($sensitive_words)) {
- $admin_message .= "<p><strong>触发敏感词:</strong><span style="color:red;">" . htmlspecialchars($sensitive_words) . "</span></p>";
- }
- $admin_message .= "<p><strong>操作指引:</strong><br>";
- $admin_message .= "请登录后台审核此主题:<a href="https://www.dianbo.org/admin.php?action=moderate">https://www.dianbo.org/admin.php?action=moderate</a></p>";
- $admin_message .= "<p style="color:#999;">(此邮件由系统自动发送,请勿回复)</p>";
- $admin_message .= "</body></html>";
-
- // 即时发送
- loaducenter();
- include_once libfile('function/mail');
- @sendmail($admin_email, $admin_subject, $admin_message);
- }
- // ==================== 主题审核邮件通知结束 ====================
复制代码
回复审核邮件代码(post_newreply.php,在原有代码基础上添加敏感词提取):
- // ==================== 管理员审核通知(任何进入审核的回复)====================
- if($pid && $modpost->param('modnewreplies')) {
- // 获取命中的敏感词(复用系统已匹配的结果)
- $sensitive_words = '';
- $censor = discuz_censor::instance();
- if (!empty($censor->words_found)) {
- $sensitive_words = implode(', ', array_unique($censor->words_found));
- }
-
- // 获取触发审核的原因
- $trigger_reason = $is_garbage_intercepted ? '纯图片回复(新注册用户)' : '系统审核规则(违禁词/敏感词等)';
-
- // 获取用户注册时间
- $reg_timestamp = $_G['member']['regdate'];
- $hours_since_reg = (TIMESTAMP - $reg_timestamp) / 3600;
-
- $admin_email = 'admin@dianbo.org';
- $admin_subject = '【论坛审核】发现新回复需要审核';
- $admin_message = '<html><body>';
- $admin_message .= '<p>论坛有一条新回复触发了审核规则,已进入审核区,请及时处理。</p>';
- $admin_message .= '<hr>';
- $admin_message .= '<p><strong>触发原因:</strong>' . $trigger_reason . '</p>';
- if (!empty($sensitive_words)) {
- $admin_message .= '<p><strong>触发敏感词:</strong><span style="color:red;">' . htmlspecialchars($sensitive_words) . '</span></p>';
- }
- $admin_message .= '<p><strong>触发时间:</strong>' . date('Y-m-d H:i:s') . '</p>';
- $admin_message .= '<p><strong>发帖用户:</strong>' . $_G['username'] . ' (UID: ' . $_G['uid'] . ')</p>';
- $admin_message .= '<p><strong>用户注册时间:</strong>' . date('Y-m-d H:i:s', $reg_timestamp) . ' (注册已 ' . round($hours_since_reg, 1) . ' 小时)</p>';
- $admin_message .= '<p><strong>回复内容预览:</strong><br>' . nl2br(htmlspecialchars(cutstr($message, 300))) . '</p>';
- $admin_message .= '<p><strong>主题链接:</strong><a href="' . $_G['siteurl'] . 'forum.php?mod=viewthread&tid=' . $_G['tid'] . '">查看主题</a></p>';
- $admin_message .= '<hr>';
- $admin_message .= '<p><strong>操作指引:</strong><br>';
- $admin_message .= '1. 进入后台 > 内容审核 > 帖子审核<br>';
- $admin_message .= '2. 审核该回复,通过或删除<br>';
- $admin_message .= '3. 后台链接:<a href="' . $_G['siteurl'] . 'admin.php">' . $_G['siteurl'] . 'admin.php</a></p>';
- $admin_message .= '<p style="color:#999;">(此邮件由系统自动发送,请勿回复)</p>';
- $admin_message .= '</body></html>';
-
- loaducenter();
- include_once libfile('function/mail');
- @sendmail($admin_email, $admin_subject, $admin_message);
- }
- // ==================== 管理员审核通知结束 ====================
复制代码
关键实现原理:
- discuz_censor::instance() 获取敏感词处理单例对象
- $censor->words_found 属性存储本次匹配到的敏感词数组
- implode(', ', array_unique(...)) 去重后拼接为可读字符串
- 使用 @sendmail() 即时发送,确保审核邮件不延迟
3、最终实现效果
| 场景 | 优化前 | 优化后 | | 新主题进入审核 | 无主动通知 | ✅ 管理员邮箱即时收到邮件 | | 新回复进入审核 | 仅显示“系统审核规则” | ✅ 显示具体触发敏感词(红色标注) | | 敏感词详情 | 需自行猜测 | ✅ 明确列出命中的敏感词 | | 处理入口 | 需登录后台手动查找 | ✅ 邮件中直接附上审核页面链接 | | 发送方式 | 主题曾用队列(有延迟) | ✅ 即时发送 | | 审核响应速度 | 可能延迟数小时 | 即时响应 |
邮件示例:
4、重要技术沉淀
需更新到固化摘要:
- 二十、主题及回复审核邮件通知(含敏感词详情)(2026-06-11)
- 功能:新主题或新回复进入审核状态时,即时发送邮件通知管理员,并显示命中的敏感词
- 涉及文件:
- - source/include/post/post_newthread.php(主题审核)
- - source/include/post/post_newreply.php(回复审核)
- 关键对象:discuz_censor::instance()->words_found
- 管理员邮箱:admin@dianbo.org
- 后台链接:https://www.dianbo.org/admin.php?action=moderate
- 发送方式:即时发送(不经过邮件队列)
复制代码
踩坑点:
| 踩坑 | 正确做法 | | 误以为敏感词需重新检测 | 系统已有 $censor->words_found 存储匹配结果,直接复用即可 | | 通知发送给所有管理员(可能无审核权限) | 仅发送给指定管理员邮箱(创始人) | | 邮件内容不含敏感词,管理员需自行猜测 | 提取并展示敏感词,便于快速判断 | | 使用邮件队列可能导致通知延迟 | 审核通知需即时处理,使用 sendmail 而非队列入队 | | 主题审核未添加邮件通知 | 参考回复审核代码,在主题发布文件中补全 |
技术亮点:
- 完全复用系统内核的敏感词匹配结果,零性能损耗
- 无需修改核心函数 helper_form::censor(),仅读取已有属性
- 去重处理避免重复关键词
- 主题和回复审核统一风格
5、进一步优化可能性
- 支持多管理员:将 $admin_email 改为数组,循环发送给多个审核人员
- 审核类型区分:除敏感词外,还可标注其他审核原因(如链接数超限、注册时间短等)
- 一键审核链接:在邮件中嵌入带 formhash 的一键通过/删除链接(需注意安全风险)
- 异步降级:如遇到 SMTP 频繁超时,可回退到队列发送模式
|
|