PHP mail() 返回 false 表示未成功提交至本地MTA,需检查disable_functions、sendmail_path路径、mail.log权限、MTA服务状态、-f参数及SPF配置。
PHP mail() 函数返回 false 时,不等于“没发出去”,而是“连本地 MTA 都没交上去”——真正的问题往往藏在系统层或配置层,不是改几行 PHP 就能解决的。
别只信 function_exists('mail') 返回 true,它只说明函数存在,不代表能用。很多主机(尤其 one.com、SiteGround 等共享环境)会保留函数声明但实际拦截调用。
var_dump(ini_get('disable_functions')),确认 mail 不在返回值里php -r "var_dump(mail('[email protected]','t','t'));",在 CLI 下单独测试——Web 环境和 CLI 的 php.ini 可能不同phpinfo() 页面里的 sendmail_path 值是否为空或指向不存在路径(如 /usr/sbin/sendmail 但实际是 /usr/bin/sendmail)PHP 8.5.5+ 默认支持 mail.log,但它不会自动创建目录或设权限,静默失败很常见。
php.ini 中设置 mail.log = /var/log/php_mail.log(路径必须绝对、父目录需存在)www-data 或 nginx)对该路径有 write 权限:sudo chown www-data:www-data /var/log/php_mail.log(若文件不存在,先 touch 再 chown)mail() 调用,立刻 tail -f /var/log/php_mail.log 查看是否有记录——没输出=根本没走到 mail 层mail() 是个“甩手掌柜”,只把数据交给本地 MTA;MTA 拒绝或挂掉,mail() 就直接返回 false,不报错。
立即学习“PHP免费学习笔记(深入)”;
systemctl is-active sendmail 或 systemctl is-active postfix,状态不是 active (running) 就得先启动echo -e "To: [email protected]: testnnbody" | /usr/sbin/sendmail -t -i,若卡住或报 cannot connect to daemon,说明 MTA 没监听或被防火墙拦了/var/log/mail.log 或 /var/log/maillog,搜索 stat= 或 reject 关键词,常能看到具体拒因(如 user unknown、no valid recipients)多数共享主机要求明确发件人身份,否则直接丢弃;而错误信息只有通过 Return-Path 才能回传到你邮箱,mail() 自身不暴露这些。
$additional_params:必须用 -f [email protected],域名要和 From: 头一致,否则 SPF 失败$headers 中显式加 Return-Path: [email protected],双重保险$to 设成你自己邮箱,等几分钟——如果邮件没到,但你收到了一封主题为 Returned mail 的退信,里面就含原始错误(如 550 5.7.1 Client host rejected)真正卡点不在 PHP 代码里,而在 sendmail_path 对不对、MTA 日志有没有权限读、-f 域名有没有配 SPF 记录——这些地方漏一个,mail() 就永远静默返回 false。