PHP的mail()函数常失败是因为它仅将邮件交给MTA而不保证投递,且不报错;应改用PHPMailer等库并配置SMTP、App Password及DNS记录。

PHP 用 mail() 发邮件为什么经常失败
绝大多数 PHP 邮件发送失败,不是代码写错了,而是 mail() 函数根本没连上本地或远程 MTA(比如 sendmail、Postfix)。它不报错,但返回 true 假成功——因为只负责把邮件“扔给”系统命令,后续投递完全脱手。
常见现象:mail() 返回 true,但收件人永远收不到;测试时发到 Gmail 显示 “This message was not encrypted”,其实是压根没进队列。
- Linux 下需确认
/usr/sbin/sendmail存在且可执行,且 PHP 的sendmail_path配置正确(phpinfo()查) - Windows 下默认不可用,除非手动配置 Mercury Mail 或类似服务,实际几乎没人这么干
- 多数共享主机禁用
mail(),或强制改写 From 头,导致 SPF 检查失败被拒收
用 PHPMailer 发 Gmail 邮件的最小可行配置
Gmail 要求 OAuth2 或开启「低安全性应用访问权限」(已逐步废弃),现在必须用 App Password(两步验证开启后生成)。
示例中关键点不是“能发”,而是避免踩坑:
立即学习“PHP免费学习笔记(深入)”;
- SMTP 主机必须是
smtp.gmail.com,端口选587(TLS)或465(SSL),别混用 -
setFrom()的邮箱必须和登录账号一致,否则 Gmail 直接拒信(即使 SMTP 认证通过) - 密码字段填的是 16 位「App Password」,不是你的 Gmail 登录密码
- 务必调用
$mail->isSMTP(),否则 PHPMailer 默认走mail(),又绕回第一段的问题
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->Username = 'your@gmail.com';
$mail->Password = 'abcd efgh ijkl mnop'; // App Password,带空格
$mail->setFrom('your@gmail.com', 'Your Name');
$mail->addAddress('to@example.com');
$mail->Subject = 'Test';
$mail->Body = 'Hello';
$mail->send();
为什么不要自己拼接 MIME 邮件头
手动用 mail() + 自定义 headers 参数发带附件或 HTML 的邮件,等于主动跳进编码、换行、边界符、Content-Transfer-Encoding 的深坑。
除了有一半电子商务的全部基本功能外,还增加了“模版自由更换”“程序在线自动更新升级”“分布式搜索”等特色功能 主要功能: ·网站的基本信息设置,部分数据以XML方式同服务器发生交互。 ·可自行关闭和开启网站,方便维护,可自定维护时显示的代码。 ·可自定义站点的关键字和描述,方便搜索引擎找到您的网站。 ·可自定义商品图片、新闻图片的上传目录和预览图片的大小。 ·提供自己设置网站的邮件发送服务器SM
典型错误包括:
- 中文主题没用
mb_encode_mimeheader(),收件箱显示乱码或问号 - HTML 正文没设
Content-Type: text/html; charset=UTF-8,Outlook 当纯文本渲染 - 附件路径含空格或中文,
Content-Disposition里没做 RFC 2231 编码,附件名损坏 - 换行符用
\n而非\r\n,部分 MTAs 直接丢弃整封邮件
这些逻辑 PHPMailer、Symfony Mailer 等库早已封装妥当,重复造轮子只会让调试时间远超开发时间。
生产环境必须检查的三件事
上线前不核对这三项,发信功能大概率在某次更新后突然失效:
- 服务器出站 587/465 端口是否被云厂商(如阿里云、AWS)默认屏蔽?需工单申请解封
- Gmail 的 App Password 是否过期(不会通知),或账号启用了新设备登录导致旧密码失效
- 是否漏了设置
DKIM和SPFDNS 记录?否则大量邮件进垃圾箱,且无法通过 Gmail 的Authentication-Results头排查
真正麻烦的从来不是“怎么发”,而是“为什么收不到”——而后者 90% 以上跟 PHP 代码无关。










