PIX主题修复后台开启邮件回复通知前台游客评论严重超时的问题
本文是《技术相关(共60篇)》目录的第 57 篇。阅读本文前,建议先阅读本文前3篇文章:
经常访问本站的各位博友知道,近一年本站最大的一个问题就是当我后台开启邮件回复通知时,前台游客评论的时候,点击提交按钮,至少需要等待漫长的1分钟才会慢吞吞地显示提交成功,真是叔叔可忍婶婶不可忍。其实这个不是什么BUG,只能算是一个问题,因为我看好些网站开启后都会延迟,只不过这个主题延迟的有些离谱,以致于我找了好长世家没有找到原因,后台在沉沦兄弟、灵妹子Obaby的帮助下才确定是后台开启了这个功能。
刚开始我对这个功能不是很在意,但是后来一些经常互访的博友反馈收不到邮件和麻烦,因为不知道自己的评论是否得到我的回复。想了又想,终于决定这次要把这个问题彻底解决。
这次只涉及一个文件pix/inc/pix-mail.php,之所以发生堵塞延迟,是因为我的邮件通知功能是通过 wp_insert_comment钩子直接触发的,而邮件发送(尤其是SMTP连接)是同步操作,会阻塞AJAX请求直到邮件发送完成。当SMTP服务器响应慢或连接超时时,会导致整个评论提交过程卡住。
这次修改是采用 Redis队列 + Swoole协程并发 方案,显著提升邮件发送性能。
以我的Debian系统为例,因为我的网站一直使用Redis,所以只需要安装swoole:
sudo apt update
sudo apt install -y build-essential php-dev libssl-dev //安装依赖
sudo pecl install swoole
需要说明的是,这个不是安装PHP里面的那个Swoole扩展,我的PHP版本是8.4,里面是Swoole6。安装Swoole,会问你是否支持好几个功能,我只选择支持前两个ssl和http2,选择更多我这里安装失败。最后将extension=swoole.so手工加入到php.ini里,重启php即可。
做完以上,就可以将以下代码完整替换pix/inc/pix-mail.php的内容,建议先备份。
<?php
/*-----------------------------------------------------------------------------------*/
/* 高性能邮件队列系统(Redis + 兼容模式) */
/*-----------------------------------------------------------------------------------*/
if (!class_exists('WP_Ultimate_Mail_Queue')) {
class WP_Ultimate_Mail_Queue {
private $redis;
private $queue_name = 'wp_mail_queue_v2';
private $concurrency = 20;
private $smtp_connections = [];
public function __construct() {
// 初始化Redis连接
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379, 1.5);
// 兼容模式:通过WordPress钩子触发处理(避免Swoole CLI限制)
add_action('shutdown', [$this, 'process_queue']);
}
// 加入队列
public function add_task($to, $subject, $message, $headers = '') {
$task = [
'to' => $to,
'subject' => $subject,
'message' => $message,
'headers' => $headers,
'attempt' => 0,
'created' => time()
];
$this->redis->lPush($this->queue_name, json_encode($task));
}
// 处理队列(兼容模式)
public function process_queue() {
$pending = $this->redis->lLen($this->queue_name);
if ($pending === 0) return;
// 批量获取任务(非阻塞)
$tasks = [];
for ($i = 0; $i < min($this->concurrency, $pending); $i++) {
$task = $this->redis->rPop($this->queue_name);
if ($task) $tasks[] = json_decode($task, true);
}
// 同步发送(兼容环境)
foreach ($tasks as $task) {
$result = $this->send_mail($task);
if (!$result && $task['attempt'] < 3) {
$task['attempt']++;
$this->redis->lPush($this->queue_name, json_encode($task));
}
}
}
// 邮件发送核心方法(修复数组访问警告)
private function send_mail($task) {
if (!is_array($task) || empty($task['to'])) {
error_log('Invalid mail task format');
return false;
}
try {
// 动态加载PHPMailer
if (!class_exists('PHPMailer\PHPMailer\PHPMailer')) {
require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
}
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
if (get_op('site_smtp') == true) {
$mail->isSMTP();
$mail->Host = get_op('smtp_server') ?: '';
$mail->Port = get_op('smtp_port') ?: 465;
$mail->Username = get_op('smtp_email') ?: '';
$mail->Password = get_op('smtp_password') ?: '';
$mail->SMTPSecure = get_op('smtp_ssl') ?: 'ssl';
$mail->SMTPAuth = true;
$mail->Timeout = 3;
}
$mail->setFrom(get_op('smtp_email') ?: 'noreply@' . $_SERVER['SERVER_NAME'], get_op('smtp_name') ?: '');
$mail->addAddress($task['to']);
$mail->Subject = $task['subject'];
$mail->msgHTML($task['message']);
$mail->CharSet = get_option('blog_charset');
$mail->send();
return true;
} catch (Exception $e) {
error_log('Mail Error: ' . $e->getMessage());
return false;
}
}
}
}
// 初始化队列
global $wp_mail_queue;
$wp_mail_queue = new WP_Ultimate_Mail_Queue();
/*-----------------------------------------------------------------------------------*/
/* 邮件模板系统(完整实现) */
/*-----------------------------------------------------------------------------------*/
function ea_mail_template($content, $parent_id, $comment_id) {
$blogname = get_bloginfo('name');
$bloghome = get_bloginfo('url');
$logo = get_op('mail_logo');
$head_title = $logo ? '<img src="'.$logo.'" style="max-width:60px;">' :
'<h1 style="display:inline-block;font-size:16px;font-family:microsoft yahei;padding:12px 30px;background:#485dff;color:#fff;border-radius:3px;">'.$blogname.'</h1>';
$comment = get_comment($comment_id);
$post = get_post($comment->comment_post_ID);
$parent_comment = get_comment($parent_id);
$html = <<<HTML
<div class="email_warp" style="max-width:540px;width:100%;background:#fdfdff;margin:0 auto;padding:30px;border:1px solid #e0e8ff;border-radius:4px;">
<div class="mail_head" style="text-align:center;margin-bottom:30px;">
<a href="$bloghome" target="_blank">$head_title</a>
</div>
<p style="margin:0">Hi, {$parent_comment->comment_author}, 您曾在[$blogname]的评论:</p>
<div class="mail_content" style="background:#ebebff;padding:20px;margin:10px 0 40px;">
<p style="margin:0">{$parent_comment->comment_content}</p>
</div>
<p style="margin:0">{$comment->comment_author} 给您的回复:</p>
<div class="mail_content" style="background:#ebebff;padding:20px;margin:10px 0 40px;">
<p style="margin:0">$content</p>
</div>
<p>点击<a href="{$post->guid}" style="color:#3b37ca;text-decoration:none;">查看完整内容</a></p>
<div class="mail_footer" style="text-align:center;margin-top:60px;">
<p>Copyright © <a href="$bloghome" target="_blank" style="color:#3b37ca;text-decoration:none;">$blogname</a></p>
</div>
</div>
HTML;
return $html;
}
/*-----------------------------------------------------------------------------------*/
/* 邮件发送接口 */
/*-----------------------------------------------------------------------------------*/
function ea_basic_mail($from, $to, $subject, $content, $parent_id, $comment_id) {
global $wp_mail_queue;
$message = ea_mail_template($content, $parent_id, $comment_id);
$headers = [
'From: "' . get_bloginfo('name') . '" <' . $from . '>',
'Content-Type: text/html; charset=' . get_option('blog_charset')
];
$wp_mail_queue->add_task($to, $subject, $message, implode("\n", $headers));
}
/*-----------------------------------------------------------------------------------*/
/* 评论触发逻辑 */
/*-----------------------------------------------------------------------------------*/
if (get_op('comments_notify') == true) {
add_action('wp_insert_comment', 'ea_global_send_mail', 10, 2);
}
function ea_global_send_mail($comment_id, $comment_approved) {
if ($comment_approved != 1) return;
$comment = get_comment($comment_id);
$parent = $comment->comment_parent ? get_comment($comment->comment_parent) : null;
if (!$parent || $parent->comment_author_email == $comment->comment_author_email) return;
ea_basic_mail(
$comment->comment_author_email,
$parent->comment_author_email,
'新评论回复![' . get_bloginfo('name') . ']',
$comment->comment_content,
$comment->comment_parent,
$comment_id
);
}
?>

您已阅读完《技术相关(共60篇)》目录的第 57 篇。请继续阅读本文后3篇文章:
八对星星
最近我也看到了Halo版本的PIX挺不错的,但是你这个是不是改过很多东西啊,好像很多都不一样了
似水流年
添加了好多功能,我感觉说是PRO版本也不为过了。😹
龙笑天
可以的 评论提交速度拉满了💪
似水流年
比以前确实进步不少,但我觉得还有优化的空间,我个人能接受的是两秒,现在我感觉得四五秒。
全局变量
我也是直接用的tp的插件,不过这个插件挺不错的分为同步和异步,异步就是提供了一个地址,访问这个地址才会发送所有未发送的邮件。
似水流年
我感觉你的挺快的。👍
obaby
我是用的插件,简单粗暴。哈哈
似水流年
我这个装了插件也没啥用,以前的时间你是知道的。🤣
网友小宋
wp邮件通知插件不是一大堆吗 我记得我爱水煮鱼有一个
似水流年
那个太臃肿了,好多插件我试过效果不明显,这次是这个主体本身有严重的问题。