本文约 5,212 字,预计阅读 14 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:邮件功能”看起来能用”,实际全在丢
WordPress 依赖邮件的功能非常多:
- 找回密码;
- 新用户注册通知、评论通知;
- 站点致命错误告警(
WP_DEBUG的 critical error 邮件); - 联系表单(Contact Form 7、WPForms);
- WooCommerce 订单确认邮件;
但 WordPress 默认用的是 PHP 的 mail() 函数,它没有认证机制,发出的邮件在现在的反垃圾规则下大概率被判为垃圾邮件或直接拒收。
更糟的是:mail() 失败不会报错。wp_mail() 返回 false,但没人看这个返回值,于是你以为发了,实际丢了。
原理分析:为什么默认邮件发不出去
wp_mail() 的默认实现是 PHPMailer 的 IsMail() 模式,底层调用 PHP 的 mail(),也就是交给服务器的 sendmail/postfix 处理。
失败原因通常有几个:
- 服务器没装邮件服务(sendmail/postfix),
mail()直接失败; - 云厂商封禁 25 端口(阿里云、腾讯云、AWS、Google Cloud 默认都封 25 出口),邮件发不出去;
- 没有 SPF/DKIM 记录,收件方(Gmail、QQ 邮箱、163)直接判垃圾或拒收;
- 发件人域名和服务器 IP 不匹配(比如
From: admin@example.com但服务器 IP 是另一家),SPF 校验失败; - 发件人用了访客填的邮箱(表单插件常见错误),SPF 必然失败。
现代邮件的正确做法是通过认证的中继服务(SMTP)发送,而不是服务器自己直发。
保姆级实操
第一步:先确认到底有没有发出去
装插件 WP Mail SMTP → 工具 → 邮件测试(Email Test),填一个收件邮箱,发送。
或者命令行:
wp eval '
$ok = wp_mail( "your@test.com", "测试标题", "测试正文" );
echo $ok ? "SENT\n" : "FAILED\n";
global $phpmailer;
if ( isset($phpmailer) ) { echo $phpmailer->ErrorInfo ?? "", "\n"; }
'
如果返回 FAILED,看错误详情。
第二步:选一个 SMTP 服务
| 服务 | 免费额度 | 国内可用性 | 适合 |
|---|---|---|---|
| 阿里云邮件推送 | 200 封/天 | 好 | 国内站点首选 |
| 腾讯云 SES | 首月 1000 封 | 好 | 国内站点 |
| QQ 邮箱 SMTP | 免费 | 好 | 小站点、个人站 |
| 163 邮箱 SMTP | 免费 | 好 | 小站点 |
| Resend | 3000 封/月 | 需能访问 | 海外/技术站 |
| SendGrid | 100 封/天 | 需能访问 | 海外站 |
| Brevo(原 Sendinblue) | 300 封/天 | 一般 | 海外站 |
个人/小站最省事:直接用 QQ 邮箱或 163 的 SMTP。
QQ 邮箱开启 SMTP:设置 → 账户 → POP3/SMTP 服务 → 开启 → 生成授权码(不是邮箱密码)。
第三步:装插件配置
装 WP Mail SMTP(作者 WPForms,WordPress 官方目录,免费版够用)。
配置路径:WP Mail SMTP → Settings → 常规:
- From Email:
noreply@你的域名.com(必须是你自己的域名,不要用 gmail/qq); - From Name:站点名;
- Mailer:选 “Other SMTP”;
- SMTP Host:
smtp.qq.com(QQ)/smtp.163.com(163)/smtpdm.aliyun.com(阿里云); - Encryption:
SSL(465 端口)或TLS(587 端口); - SMTP Port:465(SSL)或 587(TLS);
- Auto TLS:开启;
- Authentication:开启;
- SMTP Username:完整邮箱地址;
- SMTP Password:授权码(QQ/163)或 SMTP 密码(阿里云)。
常见服务商参数:
| 服务商 | Host | 端口 | 加密 |
|---|---|---|---|
| QQ 邮箱 | smtp.qq.com | 465 | SSL |
| 163 邮箱 | smtp.163.com | 465 | SSL |
| 阿里云邮件推送 | smtpdm.aliyun.com | 465 | SSL |
| 腾讯云 SES | smtp.qcloudmail.com | 465 | SSL |
| Gmail | smtp.gmail.com | 587 | TLS |
| Resend | smtp.resend.com | 587 | TLS |
| SendGrid | smtp.sendgrid.net | 587 | TLS |
保存后去 工具 → 邮件测试 发一封验证。
第四步:代码方式(不装插件)
add_action( 'phpmailer_init', 'mmf_smtp_config' );
function mmf_smtp_config( $phpmailer ) {
$phpmailer->isSMTP();
$phpmailer->Host = 'smtp.qq.com';
$phpmailer->SMTPAuth = true;
$phpmailer->Port = 465;
$phpmailer->SMTPSecure = 'ssl';
$phpmailer->Username = 'noreply@example.com';
$phpmailer->Password = '你的授权码';
$phpmailer->From = 'noreply@example.com';
$phpmailer->FromName = '迷忙飞';
$phpmailer->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false, // 某些服务器证书链不完整时需要
'verify_peer_name' => false,
),
);
}
修改默认的”From WordPress”发件人(默认发件人是 wordpress@你的域名,容易被判垃圾):
add_filter( 'wp_mail_from', function( $email ) {
return 'noreply@example.com';
});
add_filter( 'wp_mail_from_name', function( $name ) {
return '迷忙飞';
});
第五步:配置 SPF / DKIM / DMARC(决定进不进垃圾箱)
即使 SMTP 配好,没有这三项仍可能进垃圾箱。
SPF(TXT 记录,加在域名解析里):
TXT @ v=spf1 include:spf.mail.qq.com ~all
具体值由你的邮件服务商提供。阿里云邮件推送的是:
TXT @ v=spf1 include:spf.dm.aliyun.com ~all
DKIM:在邮件服务商后台生成一对密钥,把公钥作为 TXT 记录加到域名:
TXT default._domainkey v=DKIM1; k=rsa; p=MIGfMA0GCS...
DMARC:
TXT _dmarc v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com
验证:
dig TXT example.com +short
dig TXT default._domainkey.example.com +short
dig TXT _dmarc.example.com +short
或者用在线工具:mail-tester.com(发一封邮件过去,它会给出 0~10 的评分和详细问题)。
第六步:检查是不是被 WordPress 自己挡了
# 检查有没有禁用邮件
wp eval 'var_dump( has_filter("wp_mail") );'
某些插件(尤其是本地开发插件)会拦截所有邮件。
第七步:邮件日志
装插件 WP Mail Logging,把所有发出的邮件记录到数据库,能看到”发了但没到”还是”根本没发”。
wp post list --post_type=wpml_mailer --fields=ID,post_title,post_date
第八步:常见问题逐项修
问题 A:邮件进了垃圾箱
- 配 SPF/DKIM/DMARC;
- 发件人域名和站点域名一致;
- 正文里避免”免费””优惠””点击”这类垃圾词;
- 用 mail-tester.com 测分,目标 ≥ 8 分。
问题 B:找回密码邮件收不到
WordPress 的找回密码邮件成功率最高(因为它是站点发给管理员/用户的),如果连这个都收不到,一定是 SMTP 没配好。
检查顺序:SMTP 测试 → 看 SPAM 文件夹 → 看邮件服务商的发送日志(阿里云/腾讯云后台能看到投递状态)。
问题 C:WooCommerce 订单邮件不发
WooCommerce 有自己的邮件设置:WooCommerce → 设置 → 邮件,检查各个模板是否启用,以及发件人地址。
问题 D:表单插件把访客邮箱当发件人
这是最常见的错误配置:Contact Form 7 里把”发件人”设成了访客填的邮箱。因为你的 SMTP 账号没有权限用那个域名发信,SPF 校验必然失败。
正确做法:发件人固定为你的域名邮箱,访客邮箱放在 Reply-To:
your-email 作为 Reply-To
发件人固定 noreply@example.com
问题 E:25 端口被封
如果用直发(不走 SMTP 中继),且云厂商封了 25 端口,邮件必然失败。这正是要用 SMTP 中继的原因——SMTP 用 465/587,不受 25 端口限制。
常见踩坑与失败案例
- 案例一:QQ 邮箱 SMTP 填的是邮箱登录密码而不是授权码,一直认证失败。QQ 邮箱必须在设置里生成授权码。
- 案例二:发件人填了
gmail.com,但 SMTP 用的是 QQ,SPF 校验失败,全部进垃圾箱。发件人域名必须和 SMTP 账号域名一致。 - 案例三:某站联系表单把访客邮箱当发件人,结果被邮件服务商判定为”代发 spam”,SMTP 账号被封停。改用 Reply-To 后解决。
- 465 和 587 搞混:465 是隐式 SSL,587 是 STARTTLS。填错会连接超时。
- 证书验证失败:PHP 的 OpenSSL 证书链不完整时报 “certificate verify failed”。上面的
SMTPOptions能绕过,但更规范的做法是更新 CA 证书包。 - 改了
wp_mail_from但没生效:SMTP 插件的设置优先级更高,要在插件设置里改 From Email。 - 案例四:服务器 25 端口被封,站长一直以为是 WordPress 的问题,换了三个插件都没解决。换成 SMTP 中继(465 端口)立刻正常。
总结
WordPress 邮件问题的标准解法:不要用 PHP mail() 直发,一律走认证 SMTP 中继(国内站用 QQ 邮箱/阿里云邮件推送,海外用 Resend/SendGrid),用 WP Mail SMTP 插件配置 5 分钟搞定。发件人必须是自己域名的邮箱(不能用 gmail/qq 之类第三方域名),表单的访客邮箱只能放 Reply-To。光有 SMTP 还不够,必须配 SPF + DKIM + DMARC 三条 DNS 记录,否则照样进垃圾箱。排查工具三件套:插件自带的邮件测试、wp eval 'wp_mail(...)'、mail-tester.com 评分。最后记住:云厂商默认封 25 端口,这是”邮件发不出去”最常见的底层原因。
