搭建SMTP中继实现WordPress免插件发信

通常,WordPress发送邮件需要安装使用SMTP发信插件,比如Easy WP SMTP等。这些插件的使用使得WordPress加载速度变慢,且给WordPress增加了额外的安全风险(参考Easy WP SMTP之前著名的提权及代码执行漏洞)。

一个解决办法是在WordPress的网站服务器上再额外搭建一套邮件服务器。但是,这样的方法显得过于累赘,我们只需要让WordPress发送邮件,收发信的处理应当交由专门的邮件服务器来完成。因此,我们今天介绍使用SMTP邮件中继(SMTP Relay)实现WordPress无插件邮件发送。

本文作者为香菇肥牛,本文链接为https://qing.su/article/159.html, 转载需注明原文链接。谢谢!

1, 环境及基础设置

本文的测试环境为Ubuntu 20.04 LTS 64 bit (其他操作系统类似), WordPress域名为example.com, WordPress IP地址为88.88.88.88.  WordPress所在服务器的主机名(服务器名)假设为server.example.com.  WordPress所在的服务器的25端口可以被屏蔽,不影响发信

用于发信的邮件服务器的主机名假设为mx.qing.su, 请自行替换为您自己的地址。您可以使用自己搭建的邮件服务器作为中继,也可以使用商业SMTP Relay服务(比如MailChannels, MailJet等等)。

如果您使用的是自己搭建的邮件服务器,请您在邮件服务器上添加好对应的域名example.com以及用户,比如hi@example.com.

您还需要做下列的DNS解析:

  • 设置example.com MX记录,记录值任意,但是必须存在。
  • 设置example.com SPF记录(TXT).  如果您使用的发信服务器是自己搭建的,您可以设置解析值为“v=spf1 a mx ip4:88.88.88.88 ~all”; 如果您使用的是商业SMTP Relay服务,请参考具体商家的SPF记录设定要求来设置。
  • 设置server.exampe.com A记录解析到88.88.88.88.

做好解析之后,请登录您的WordPress服务器,设置好主机名。这里假设短主机名为server, 长主机名为server.example.com.  请注意,主机名不能设置成example.com, 否则邮件没有办法投递到SMTP中继服务器上,只能投递到WordPress服务器本身。另外,如果您WordPress域名和邮件服务器的根域名是同一个域名,则WordPress服务器的长主机名不要设置为和邮件服务器的长主机名相同。比如,我的邮件服务器的主机名为mx.qing.su, 如果我有另外一台WordPress服务器,网站域名也是qing.su, 那么这台WordPress服务器的长主机名就不能设置为mx.qing.su, 而可以设置为web.qing.su或者server.qing.su或者www.qing.su都可以。如果您不知道如何设置主机名,请参考我们的图文视频教程:https://qing.su/how-to-set-hostname

然后,我们就可以开始搭建邮件中继了。

2, 安装与配置Postfix

我们需要安装Postfix来实现SMTP中继。

1
apt-get install postfix libsasl2-modules

请注意,如果您的操作系统模板已经默认安装了Postfix, 您同样需要安装libsasl2-modules, 否则无法进行后续的SASL验证。

Postfix安装过程会出现下面几个界面。

在General type of mail configuration这个界面,我们需要选择Internet Site, 如下图。

然后,会出现System mail name的选项框,如果您的主机名设置正确,这里应该会自动填入您的长主机名,我们这里是server.example.com.

安装好之后就可以开始配置Postfix了。我们编辑文件/etc/postfix/main.cf:

找到下面这行:

1
inet_interfaces = all

改成:

1
inet_interfaces = loopback-only

这样的设置将使得Postfix仅监听本地请求,防止被他人利用。

接着配置中继,找到下面这行:

1
relayhost =

我们在后面填上邮件服务器的主机名与端口:

1
relayhost = mx.qing.su:587

请注意,我们这里使用587作为邮件提交端口。在main.cf末尾添加下面几行,配置SASL验证信息:

1
2
3
4
5
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = may
header_size_limit = 4096000

我们指明了SASL验证信息的配置文件位置为/etc/postfix/sasl_passwd.  我们编辑这个文件,按照下面的格式填写发信用户的SMTP用户名与密码。

1
mx.qing.su:587    hi@example.com:password

最后,我们hash生成验证信息,并重启Postfix使得更改生效。

1
2
3
postmap /etc/postfix/sasl_passwd
chmod 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
service postfix restart

如果您是按照我之前的教程搭建的iRedMail一键包,那么您还需要在邮件服务器上做一点更改。

编辑文件/opt/iredapd/settings.py  (该文件没有写权限,需要chmod +w提权,编辑完毕后降权),在末尾添加下面一行:

1
ALLOWED_LOGIN_MISMATCH_SENDERS = ['hi@example.com']

然后重启服务生效:

1
service iredapd restart

至此,我们已经配置好了SMTP中继。

3, 配置WordPress

配置WordPress之前,我们先简单介绍一下WordPress发邮件的两种方式。第一种是SMTP, 如果您安装了SMTP发信的插件,那么您的WordPress就是采用这种方式发信的。第二种是调用系统默认的sendmail.  由于我们已经配置好了SMTP邮件发送中继,因此,调用系统sendmail就会默认使用SMTP中继来发送邮件;换言之,我们只要卸载掉所有的SMTP发信插件,WordPress就会自动使用SMTP中继发送邮件。

但是,这样发送的邮件是有问题的。我们没有为WordPress指明发件人地址,因此发出来的邮件都是来自username@hostname.  比如,如果你用的是Nginx服务器,那么默认发件人可能是www-data@server.example.com; 如果你用的是Litespeed服务器,那么默认发件人可能是nobody@server.example.com.  我们希望通过根域名发信,比如使用hi@example.com这个地址,而不是hostname发信。我们还希望设置发件人姓名。

实现这一点,我们需要对WordPress的PHP代码做出一点替换。编辑您主题的functions.php文件,加入下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
function wpb_sender_email( $original_email_address ) {
        return 'hi@example.com';
}
function wpb_sender_name( $original_email_from ) {
        return '香菇肥牛';
}
function fix_my_email_return_path( $phpmailer ) {
        $phpmailer->Sender = $phpmailer->From;
}
add_filter( 'wp_mail_from', 'wpb_sender_email' );
add_filter( 'wp_mail_from_name', 'wpb_sender_name' );
add_action( 'phpmailer_init', 'fix_my_email_return_path' );

保存后即可生效。使用mail-tester.com测试一下WordPress的SMTP中继邮件发送,评分为满分10分,如下图。

这里为了简便,没有再额外添加DMARC记录,如果需要了解如何添加,请参考上一篇文章https://qing.su/article/158.html.

4, 隐藏WordPress服务器IP

如果你使用的是自己搭建的邮件服务器,那么用SMTP中继发送邮件的时候,会在邮件头中留下WordPress服务器的IP地址,如果您的服务器藏在CDN之后,这样就会暴露源IP.  我们可以修改邮件服务器(不是WordPress服务器)的Postfix配置文件,丢弃掉这个IP地址的邮件头信息。新建文件/etc/postfix/smtp_header_checks, 添加下面的行:

1
/^Received:/ IGNORE

然后编辑邮件服务器的Postfix配置文件/etc/postfix/main.cf, 在末尾添加下面的行:

1
smtp_header_checks = regexp:/etc/postfix/smtp_header_checks

最后我们让配置生效:

1
2
postmap /etc/postfix/smtp_header_checks
service postfix restart

 

至此,我们在WordPress服务器上使用Postfix搭建了SMTP邮件中继服务,这样WordPress就可以不通过插件直接使用SMTP发信,加快了发信和网页加载速度,也提升了安全性。如果您有任何疑问,欢迎在这里留言,我将尽力解答。本文作者为香菇肥牛,本文链接为https://qing.su/article/159.html, 转载需注明原文链接。谢谢!

 

 

6 thoughts on “搭建SMTP中继实现WordPress免插件发信”

  1. 这个方法配置的确更加专业了,我目前使用的办法是给服务器套一个ipv6地址,让邮件走ipv6出去(smtp有ipv6的情况),邮件头部就会有ipv6地址,且由于国内网络问题,这个ipv6地址很难从外部到达本机服务器,仅是单出不进。

    Reply
    • 最后那段代码是指WordPress替换的那段代码吗?如果不起用,可能是因为你的插件或者主题在其他地方控制了这几个环境变量

      Reply

Leave a Comment