作为一个基本没人访问的网站,偶尔还有些评论。这些评论的发送者发送后基本不太会再来网站访问了,但若评论有了回复,评论发送者也就不会知道了使用评论发送时留下的邮箱进行通知是一个比较好的办法,这就需要在一条评论有其他人回复时自动发送邮件通知评论的发送者。
有大量Wordpress插件能实现这一功能,但插件质量良莠不齐,有漏洞的插件甚至会威胁整个博客的安全。并且要发送邮件需要在软件中保存发送邮箱的用户名密码,别人写的插件指不定会上传哪些东西。为了邮箱和博客的安全,我决定自己实现这一功能
话不多说,方法如下,首先在主题编辑器修改functions.php文件,添加如下代码
function comment_mail_notify($comment_id) { $comment = get_comment($comment_id); $parent_id = $comment->comment_parent ? $comment->comment_parent : ''; $spam_confirmed = $comment->comment_approved; if (($parent_id != '') && ($spam_confirmed != 'spam')) { require_once('/disk/website/htdocs/public/PHPMailer/include.php'); $to = trim(get_comment($parent_id)->comment_author_email); $subject = '您在 [' . get_option("blogname") . '] 的留言有了回复'; $message = ' <div style="background-color:#eef2fa; border:1px solid #d8e3e8; color:#111; padding:0 15px; -moz-border-radius:5px; -webkit-border-radius:5px; -khtml-border-radius:5px;"> <p>' . trim(get_comment($parent_id)->comment_author) . ',您好!</p> <p>您在《' . get_the_title($comment->comment_post_ID) . '》的留言:<br />' . trim(get_comment($parent_id)->comment_content) . '</p> <p>' . trim($comment->comment_author) . ' 刚才给了您回复:<br />' . trim($comment->comment_content) . '<br /></p> <p>您可以 <a href="'.get_comment_link($parent_id).'" target="_blank">点击查看回复</a></p> <p>欢迎再度光临 <a href="https://www.zhouii.com/" target="_blank">' . get_option('blogname') . '</a></p> </div>'; mymail($to, $subject, $message); } } add_action('comment_post', 'comment_mail_notify');
add_action函数时Wordpress在接收到评论时调用comment_mail_notify函数。函数内($parent_id != '')保证评论有父评论时才发送通知,也就是评论是在回复另一条评论时再给另一条评论的发送者回复。邮件的html内容拼接后放在$to变量内,最后的mymail函数就实现了发送邮件的动作,mymail函数(位于PHPMailer文件夹的include.php中,代码在下面)使用我邮箱的用户名密码调用PHPMailer的邮件发送函数。邮件发送功能需要自己配置,可以使用sendmail等,我这里用了PHP发送邮件的第三方库PHPMailer
<?php require_once __DIR__ . '/Exception.php'; require_once __DIR__ . '/OAuth.php'; require_once __DIR__ . '/PHPMailer.php'; require_once __DIR__ . '/POP3.php'; require_once __DIR__ . '/SMTP.php'; use PHPMailer\ PHPMailer\ PHPMailer; use PHPMailer\ PHPMailer\ Exception; function mymail( $to, $subject, $message ) { $mail = new PHPMailer( true ); try { $mail->CharSet = 'UTF-8'; //Server settings $mail->isSMTP(); // Set mailer to use SMTP $mail->Host = 'SMTP服务器地址'; // Specify main and backup SMTP servers $mail->SMTPAuth = true; // Enable SMTP authentication $mail->Username = '发件电子邮箱地址'; // SMTP username $mail->Password = '***邮箱密码***'; // SMTP password $mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted $mail->Port = 25; // TCP port to connect to $mail->SMTPOptions = array( 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ) ); //Recipients $mail->setFrom( '发件电子邮箱地址', '显示名称' ); $mail->addAddress( $to ); // Add a recipient // Content $mail->isHTML( true ); // Set email format to HTML $mail->Subject = $subject; $mail->Body = $message; $mail->send(); } catch ( Exception $e ) { echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; } }
这样导致的一个问题就是操作是同步进行的,就是评论者的评论请求提交后需要等待mymail函数返回才能返回,邮件发送动作通常需要一两秒,会减慢评论速度。
懒得搞异步操作 解决方案就是在前端提示用户稍等,就能减缓用户的焦急心理,好似评论没有那么长时间一样
再在主题编辑器编辑主题文件的footer.php增加以下代码即可在用户点击评论按钮后提示“正在提交中”
<script src="https://cdn.staticfile.org/jquery/3.1.1/jquery.min.js"></script> <script src="https://tiny.zhouii.com/public/myjs.js"></script><script>$('body').prepend('<div id="waiting" style="position: fixed;text-align: center;display: none;margin: auto;top: 0;height: 100%;width: 100%;background: rgba(255, 255, 255, 0.7);z-index:2000; "><h1></h1><img src="https://tiny.zhouii.com/public/pending.gif" align="center" /></div>');$('#submit').click(function(){lock("正在提交中……");});</script>
其中lock函数在myjs.js中定义如下,可以使提示语不随页面滚动改变位置,始终显示在屏幕中央
function lock(tip) { $('#waiting>h1').html(tip).css('margin-top',$(window).height()/2-60); $('#waiting').css('display','block'); }