PHP 8.0 邮件发送失败主因是 PEAR Mail 路径加载失效或 each() 函数被移除;需将 include_once 'Net/SMTP.php' 改为 DIR . '/../Net/SMTP.php',并把 each() 替换为 foreach;mail() 返回 true 不代表邮件发出,建议改用 PHPMailer。

PHP 8.0 升级后邮件发送失败,大概率不是配置问题,而是两类硬性兼容性断裂:PEAR Mail 的路径加载失效 或 代码里调用了已被移除的 each() 函数。直接修这两处,90% 的场景能恢复。
PEAR Mail 报错 include_once('Net/SMTP.php'): Failed to open stream
这是 PHP 8.0+ 对 include_path 解析更严格导致的——它不再自动把 PEAR 安装目录映射进裸路径查找链。错误日志里出现 Net/SMTP.php 找不到,基本可锁定是这个原因。
实操建议:
- 定位你的 PEAR 安装路径(常见为
/usr/share/php/或/home/xxx/pear/share/pear/) - 修改以下文件中的所有
require_once 'XXX.php'或include_once 'XXX.php'语句:Mail/smtp.php、Mail.php、Net/SMTP.php、PEAR.php - 把类似
include_once 'Net/SMTP.php';替换为include_once __DIR__ . '/../Net/SMTP.php';(注意层级:从Mail/进入上层再进Net/) - 改完后清空 OPCache(
opcache_reset()或重启 PHP-FPM),否则缓存会掩盖修复效果
Xiuno BBS 或自研 Mail 封装类报错 Call to undefined function each()
each() 在 PHP 7.2 被废弃、PHP 8.0 彻底移除。如果你用的是 Xiuno BBS 4.0.4、或任何手动封装 SMTP 的旧代码,且错误日志里明确出现 Call to undefined function each(),那就是它了。
立即学习“PHP免费学习笔记(深入)”;
实操建议:
- 全局搜索项目中所有
each(,重点关注邮件相关文件(如xn_send_mail.func.php) - 把形如
while (list(, $line) = each($lines)) {改成foreach ($lines as $line) { - 若原逻辑依赖
each()返回的键值对,且你确实需要键名,请改用foreach ($array as $key => $value) - 注意:有些地方带
@each()的错误抑制符也要一并删掉,否则foreach无法生效
用 mail() 函数返回 true 却收不到邮件
这跟 PHP 版本无关,是长期被误读的老问题:mail() 返回 true 只代表“成功交给了本地 MTA”,不代表发出去了。PHP 8.0 只是让这类静默失败更显眼——因为底层 sendmail/postfix 往往根本没装或被云厂商屏蔽。
实操建议:
- 别再花时间调
mail();直接切到PHPMailer(Composer 安装:composer require phpmailer/phpmailer) - 确认 SMTP 端口和加密方式匹配:端口
587→SMTPSecure = 'tls';端口465→SMTPSecure = 'ssl'(部分服务商已弃用 SSL) - 用 Gmail 测试时,密码必须是“应用专用密码”,不是账户登录密码
- 检查
$mail->ErrorInfo,而不是只看$mail->send()返回值
最常被忽略的一点:PEAR 路径修复后,如果用的是 CGI/FPM 模式,get_include_path() 的实际值可能和 CLI 下不同,务必在 Web 环境里 phpinfo() 确认当前生效的 include_path。



















