WordPress集成SendCloud邮件代发,规避SMTP泄漏网站主机真实IP的风险

还是几个月前,中国博客联盟的晓风依然博主 QQ 联系我,说发现 WordPress 评论回复邮件存在一个巨大的风险:WordPress 评论回复邮件,不管是使用 SMTP 代发还是用 Sendmail 发送,都会暴露网站主机的真实 IP!

经过我亲自验证,发现的确存在这个令人担忧的问题!但是,一时之间并没有合适的解决方案,所以我和他都一致认为在没有找到替代方案之前,这个东西不能曝光!就算有部分人已经知道了,但还是不能明晃晃的摆到台面上来公布于众!

接下来的几个月,张戈一直在新公司持续高强度的工作,根本没有闲暇时间来研究替代方案!可惜让我担忧的事情最终还是发生了:幻杀博客的博主小幻在博客公布了这个会泄漏 IP 的“BUG”,却没有分享解决方案!我除了感叹出身牛犊不怕虎之外,也只能无奈加紧步伐,尽快找到替代方案。

一、如何泄漏

看过幻杀博客的文章的朋友应该已经知道是怎么一回事了。就是当我们的网站通过 SMTP 代发或者 php 调用 SendMail 来发邮件通知评论者时,我们发送过去的邮件原文中将带有我们主机的真实 IP!!如果被人恶意利用,我们的 CDN 防护都将变得毫无意义(点此查看个人网站暴漏真实 IP 的危害)!

最新补充:果然,在乌云上早就有朋友发过这个漏洞了,感兴趣的童鞋可以前往看看:

某方法可以无视 CDN 查找真实 IP 导致真实站点遭受 DDOS 或入侵

二、解决方案

①、自建 API

既然不能使用 SMTP 代发,又不能使用 SendMail,那就只有一个办法了:用第三方 API 代发邮件即可,就算暴露 IP 也是暴露了邮件服务器的 IP,和我们的小站没有任何关系。

本来我是想在 SAE 搭建一个邮件代发 API,后来想到了中国博客联盟那么多的邮件模板,而自己空闲时间确实太少,只好先放弃了。

A. 小幻版本

小幻被我吐槽之后,说去研究下自建邮件 API 服务,目前已在他博客分享了一个自建的邮件代发 API,感兴趣的朋友可以前往查看:

使用邮件代发 API 发送回复邮件提醒

不得不说这家伙确实是一个很赞的高中技术宅(再次汗颜下自己高中时还只会玩 QQ)。

B. SAE 版本

小武这个技术宅,为了解决评论显示代发,导致变成垃圾邮件问题,在 SAE 搭建了一个邮件 API,而且是专门给 WordPress 评论回复用的,感兴趣的朋友可以去了解一下:

通过新浪 SAE 发送 wordpress 评论提醒邮件

②、SendCloud

写到这,本文主角终于姗姗来迟。

SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据[1] 。主要提供两种类型的邮件发送服务,一类是事务性邮件,一类是商务性邮件。 ——摘自百度百科

SendCloud 我目前的公司也在使用,而且我也曾写过关于 SendCloud 的堵塞监控脚本:

SendCloud 邮件队列状态和已使用额度的 Python 监控脚本

感兴趣的可以前往一探究竟。这玩意如何牛逼,如何高大上我就不说了。简单的说就是一个邮件代发服务,比上面介绍的自建 API 更加完善,当然使用也更加复杂,希望看完本文的朋友可以成功集成到 WordPress 当中。

三、动手集成

①、注册帐号

如何注册就不赘述了,官网地址:http://sendcloud.sohu.com/

②、域名设置

邮件设置==>域名==>新增发信域名

完成后,进入域名设置,按照提示到你的 DNS 解析控制台新增必须的几个记录:

下面还有一个收信配置,也是一个必配项:

Ps:不过这里有一个技巧,上图可以很明显的看到,我现有的记录值是 2 个,一个 sendcloud,一个是 QQ 的域名邮箱。因为,我不是很想用 Sendloud 的转发功能,而是想继续用之前就配好的 QQ 域名邮箱。这里该如何实现呢?很简单,在 DNS 解析那新建 2 个 MX 记录,然后将 QQ 域名的 MX 优先级设置更小即可!

下面是张戈博客的相关 DNS 设置,不会的可以参考下:

设置好了之后,可以点击右上角的【检测配置】来探测是否生效。这个生效时间长短不一,咱们先继续做后面的设置。

最新补充:其实如果你的网站要用其他域名邮箱或企业邮箱,那么只要在 Sencloud 域名验证后将 MX 记录改为相应的域名邮箱或企业邮箱记录即可!比如张戈博客要用 QQ 的域名邮箱,那么就将上图中的 sendcloud 的 MX 记录删除,只保留 QQ 邮箱的 MX 记录就好了。并不影响 sendcloud 发信,因为这个 MX 记录只是用于收信,而最爽的是 QQ 邮箱那边依然可以用域名邮箱发信!

③、获取 api_user 和 api_key

登录后,就会获得帐号专属的 API_KEY,当然如果你忘记了也可以使用会员首页的重置功能。

接着点击上方的【邮件设置】==>【Api_user】,来创建新的 API_KEY 备用:

④、邮件样本

Ps:目前已和邮件模板合并,请直接跳过这一步!展开

Sendloud 为了避免有人恶意发送垃圾邮件,就推出了这个审核机制,所有邮件代发都必须先通过样本校验。貌似是要达到 80%以上的匹配率才会给你发出去,否则就返回不匹配错误。

官方给出的注意事项:

注意事项:

  1. 为避免不良信息传播,用户在发送邮件前,需提交样本审核,真实发送的邮件内容会和样本进行匹配。
  2. 邮件样本可以是具体的某一封邮件,也可以是带有变量的邮件模板。
  3. 审核时间:工作日(周一至周五 9:00-18:00)一小时以内审核;非工作日上午和下午定时审核一次。

这算是整个流程中比较麻烦的一步,不过大家完全不用担心,因为张戈都已经写好了模板:

Ps:和下面的邮件模板代码一样,就不重复粘贴了!

点击【发送相关】==>【邮件样本】==>【创建样本】==>参考下图填写好上方栏位==>切换到【源码模式】==>粘贴上面的代码==>提交审核即可

当然, 我们可以根据需求提交多个模板,不过一般 WP 就评论回复通知用的最多,其他自己研究吧!

⑤、邮件模板

看到这,估计大伙要骂娘了。。。刚弄了一个邮件样本,又要弄邮件模板!当然,我们是可以直接 post 整个邮件内容到 Sendloud,但是并不是强迫症所向往的,我们追求的是极致,因为使用模板发送只要 post 模板中的几个变量即可。

废话不说,点击【发送相关】==>【邮件模板】===>【创建模板】

和上面的邮件样本一样,将以下代码粘贴到源码模式保存即可:

<style type="text/css">blockquote{
width: 94%;
color: #8b8b8b;
margin: 0 auto;
padding: 10px;
clear: both;
border: 1px solid #ebebeb;
}
</style>
<table cellpadding="0" cellspacing="0" style="font-family: 微软雅黑,verdana, arial; margin: 0 auto; width: 100%;">
	<tbody>
		<tr>
		<td style="background: #08c; color: #fff; font-family: 微软雅黑,verdana, arial; font-size:15px;line-height: 35px;"><strong>&nbsp; 您在%blogname%的留言有了新的回复:</strong></td>
		</tr>
		<tr>
		<td style="border: solid 1px #ccc; font-size: 13px; line-height: 180%; padding: 20px;"><span style="color: rgb(186, 76, 50); font-family:微软雅黑, verdana, arial; line-height: 23.3999996185303px;">%comment_author1%</span>, 您好!
		<p>您曾在<span style="color:#ba4c32;">《%conent_title%》</span>的留言:</p>
                <blockquote>
		<p>%comment_content1%</p>
		</blockquote>
                <p><span style="color:#ba4c32;">%comment_author2%</span> 给你的回复:</p>
                <blockquote>
		<p>%comment_content2%</p>
		</blockquote>
		<p style="padding: 5px;">您可以点此 <a href="%comment_link%">查看完整回复內容</a></p>
		<p style="padding: 5px;">欢迎您再度光临&nbsp;<a href="%home_url%" target="_blank" title="%description%">%blogname%</a>!</p>
		</td>
		</tr>
		<tr>
		<td style="color: rgb(255, 255, 255); font-size: 12px; line-height: 21.6000003814697px; padding: 10px; background: rgb(51, 51, 51);">请注意:此邮件由&nbsp;<a href="%home_url%" target="_blank" title="%description%">%blogname%</a>&nbsp;自动发送,请勿直接回复。<br />如果此邮件不是您请求的,请忽略并删除!</td>
          </tr>
	</tbody>
</table>
<p><a href="%%user_defined_unsubscribe_link%%" style="background: #1ABC9C;border:1px solid #13A386;padding:8px 20px;color: #fff;text-decoration:none;border-radius:4px">不想再收到此类邮件</a></p>

调用名称推荐使用字母:

这里就不用审核了,但是注意这个模板在邮件样本中必须存在匹配的样本,否则无法发出去。

⑥、PHP 函数

唉,张戈折腾一上午,分享出来几分钟!代码如下:

/**
** WordPress集成Sendloud邮件代发函数
** 原创地址:http://zhangge.net/5045.html
** Ps:转载不保留出处 and 篡改版权的都木有小JJ。
**/
function SendCloud_mail($from,$fromname,$to,$subject,$message,$template) {
    $api_user = "这里填写sendcloud的app_user"; //注意保留英文双引号!
    $api_key = "这里填写Sendloud的api_key";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_URL, 'http://sendcloud.sohu.com/webapi/mail.send_template.json');
    $substitution_vars  = json_encode(array('to' => array($to),'sub' => $message));
    $data = array(
        'api_user' => $api_user,
        'api_key' => $api_key,
        'from' => $from,
        'fromname' => $fromname,
        'template_invoke_name'=> $template,
        'subject' => $subject,
        'substitution_vars'=> $substitution_vars
        );
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    $result = curl_exec($ch);
    if($result === false) {
        echo curl_error($ch);
    }
    curl_close($ch);
    return $result;
}
//下面是修改版的WordPress发邮件代码(支持嵌套评论邮件)
//适用于Sendloud,你们看张戈多厚道,任何时候都保留出处,不像某些小人!
 
/* 邮件通知 by Qiqiboy */
function comment_SendCloudMail_notify($comment_id) {
     $comment = get_comment($comment_id);//根据id获取这条评论相关数据
     $comment_approved=$comment->comment_approved;
     if ($comment_approved != 1) { return; }  
     $content=$comment->comment_content;
     //对评论内容进行匹配
     $match_count=preg_match_all('/<a href="#comment-([0-9]+)?" rel="nofollow">/si',$content,$matchs);
     if($match_count>0){ //如果匹配到了
         foreach($matchs[1] as $parent_id){//对每个子匹配都进行邮件发送操作
             SimPaled_send_email($parent_id,$comment);
         }
     } elseif ($comment->comment_parent!='0'){//以防万一,有人故意删了@回复,还可以通过查找父级评论id来确定邮件发送对象
         $parent_id=$comment->comment_parent;
         SimPaled_send_email($parent_id,$comment);
     } else return;
 }
add_action('comment_post', 'comment_SendCloudMail_notify');
 
function SimPaled_send_email($parent_id,$comment){//发送邮件的函数 by Qiqiboy.com
     $admin_email = get_bloginfo ('admin_email');//管理员邮箱
     $parent_comment=get_comment($parent_id);//获取被回复人(或叫父级评论)相关信息
     $author_email=$comment->comment_author_email;//评论人邮箱
     $to = trim($parent_comment->comment_author_email);//被回复人邮箱
     $spam_confirmed = $comment->comment_approved;
     if ($spam_confirmed != 'spam' && $to != $admin_email && $to != $author_email) {
         $wp_email = 'no-reply@' . preg_replace('#^www\.#', '', strtolower($_SERVER['SERVER_NAME'])); // e-mail 發出點, no-reply 可改為可用的 e-mail.
         $subject = '您在 [' . get_option("blogname") . '] 的留言有了新的回复!';
         $fromname = get_option('blogname');
         $message = array(
                "%conent_title%"=>array(get_the_title($comment->comment_post_ID)),
                "%comment_content1%"=>array(trim(get_comment($parent_id)->comment_content)),
                "%comment_content2%"=>array(trim($comment->comment_content)),
                "%comment_author1%"=>array(trim(get_comment($parent_id)->comment_author)),
                "%comment_author2%"=>array(trim($comment->comment_author)),
                "%comment_link%"=>array(htmlspecialchars(get_comment_link($parent_id,array("type" => "all")))),
                "%blogname%"=>array(get_option('blogname')),
                "%description%"=>array(get_bloginfo('description')),
                "%home_url%"=>array(get_option('home'))
                );
        if( $to != '' && is_email($to)){
           SendCloud_mail( $wp_email, $fromname, $to, $subject, $message, '此处请修改为模板调用名称');
        }
     }
 }

将以上代码添加到主题目录的 functions.php 当中即可,放哪个位置我就不再阐述了,这都搞不清估计也玩不转这种折腾活了。

⑦、系统邮件(可选)

什么叫系统邮件?就是有人在你博客留言了,或者有评论需要审核,WordPress 是可以设置邮件提醒的,这里需要用到 wp_mail 函数。但是我懒得将这个功能也用 Sendloud 来代发,一是麻烦,二是发给管理员的,泄漏 IP 又如何?

所以,之前如果已经弄过 SMTP,可以保留如下代码,让系统继续使用 SMTP 发邮件给管理员:

//使用smtp发送邮件,代码中使用的是QQ邮箱,你可以参照你使用的邮箱具体设置SMTP   
add_action('phpmailer_init', 'mail_smtp');   
function mail_smtp( $phpmailer ) {   
    $phpmailer->FromName = 'XX博客'; //发件人   
    $phpmailer->Host = 'smtp.qq.com'; //修改为你使用的SMTP服务器   
    $phpmailer->Port = 25; //SMTP端口   
    $phpmailer->Username = 'user@domain.com'; //邮箱账户      
    $phpmailer->Password = 'password'; //邮箱密码   
    $phpmailer->From = 'user@domain.com'; //你的邮箱      
    $phpmailer->SMTPAuth = true;      
    $phpmailer->SMTPSecure = ''; //tls or ssl (port=25留空,465为ssl)   
    $phpmailer->IsSMTP();   
}

但是如果之前已经添加过评论回复邮件通知代码的的,请注意注释掉,否则之前的代码可能还会继续工作,泄漏 IP,一般在 functions.php 里面添加如下代码即可:

//移除原有的邮件通知动作钩子(一般都是用的comment_mail_notify这个函数,自己注意辨别)
remove_action('comment_post', 'comment_mail_notify');

四、效果预览

目前张戈已经使用了一个多月了,非常稳定。免费用户每天可以发送 200 封邮件,这已经足够应付绝大部分个人博客了!

Ps:如图,最看不起那些乱填邮件的人!要么就灌水,要么就是找茬的。而且经常对 SendCloud 请求一些无效邮件,将会降低帐号的信誉度,影响以后的发送成功率。

很多人看到本文肯定会望而却步,因为确实弄起来比较复杂,也比较麻烦!但是,张戈作为吃螃蟹的都已经分享出来了,你还嫌麻烦?

Ps:这篇文章又花了我 4 个多小时!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术小讲堂

PHP环境中安装pear、phpunit以及xdebug全攻略1.准备2.安装

首先,本文是基于wamp环境的基础上的,所以,如果您看到这里还没有搭建好wamp环境的话,介意您先把环境搭建好,因为这里都是一些实践性的内容。 1.准备 wam...

4088
来自专栏架构师之旅

HTTPS加密连接不再安全 新攻击可轻松绕过

HTTP,即超文本传输协议,是互联网上应用最为广泛的一种网络协议。然而HTTP协议以明文方式发送内容,不提供任何方式的数据加密,这导致这种方式特别不安全。对此便...

2188
来自专栏Python爬虫与数据挖掘

手把手教你如何安装水晶易表——靠谱的安装教程

关于水晶易表的介绍在之前的文章就有提及过,感兴趣的小伙伴可以戳这篇文章:关于水晶易表的简介及其安装初识,在此不再进行赘述。今天给大家分享一下水晶易表的安装教程,...

1374
来自专栏FreeBuf

SSL Strip的未来:HTTPS 前端劫持

作者 EtherDream 前言 在之前介绍的流量劫持文章里,曾提到一种『HTTPS 向下降级』的方案 —— 将页面中的 HTTPS 超链接全都替换成 HTTP...

2875
来自专栏友弟技术工作室

全平台最佳密码管理工具大全:支持 Windows、Linux、Mac、Android、iOS 以及企业应用

原文 当谈到网络安全的防护时,从各种网络威胁的角度来看,仅安装一个防病毒软件或运行一个安全的 Linux 操作系统,并不意味你就是足够安全的。 今天大多数网络...

1.2K11
来自专栏北京马哥教育

学了Python后,我走哪里都可以连WIFI!为什么?反正就是这么强!

? WIFI破解,Python程序员必学技能。WIFI已经完全普及,现在Python程序员没网,走到哪里都不怕!教你们一招,如何在图片中提取Python脚本代...

6149
来自专栏Python爬虫与数据挖掘

手把手教你如何安装水晶易表——靠谱的安装教程

关于水晶易表的介绍在之前的文章就有提及过,感兴趣的小伙伴可以戳这篇文章:关于水晶易表的简介及其安装初识,在此不再进行赘述。今天给大家分享一下水晶易表的安装教程,...

1565
来自专栏逸鹏说道

大公司都有哪些开源项目之腾讯

1.WeUI 为微信Web服务量身设计 WeUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信 Web 开发量身设计,可以令用户的使用感知...

5106
来自专栏信安之路

【读者投稿】wifi渗透-狸猫换太子

上期作者发布了一篇关于wifi钓鱼的方法,今天我来给大佬们带来一篇关于拿到wifi密码能干什么?

1450
来自专栏FreeBuf

花生壳黑吃黑之一:Web练手基地

作为我这样的新手,看网上的渗透社工教程,看的我热血沸腾,但是我怎么找那种脆弱网站练手啊,现在网站一个比一个保护强,什么弱口令,什么注入到哪里去找啊?菜鸟们是否有...

44910

扫码关注云+社区

领取腾讯云代金券