已修复 后台smtp配置:发送测试邮件问题(可以只有我有问题)

问题

[Bug] 后台 SMTP 测试邮件通过 `_include()` 加载过期 SMTP 缓存,导致与注册邮件配置不一致

环境

### 环境

- XiunoX 1.1.1
- PHP 8.2
- SMTP:QQ 邮箱,SMTPS / 465
- 仅配置了 1 条 SMTP 记录

### 现象

注册验证码邮件可以正常发送,但后台「SMTP 设置 → 发送测试邮件」始终失败,提示:

```text
SMTP Error: Could not authenticate.
SMTP server error: QUIT command failed

SMTP 服务、端口、SSL、授权码和服务器网络均正常。使用相同的 SMTP 配置通过 PHPMailer 直接认证并完整发送邮件均成功。

根因

注册邮件和后台测试邮件读取 SMTP 配置的方式不一致。

注册邮件

注册流程通过 xn_smtp_get() 读取:

$confile = APP_PATH . 'conf/smtp.conf.php';
$smtplist = include $confile;

因此读取的是最新保存的配置:

conf/smtp.conf.php

注册邮件可以正常发送。

后台测试邮件

后台测试接口位于:

admin/route/setting.php

原代码:

$smtplist = include _include(APP_PATH.'conf/smtp.conf.php');

_include() 是插件源码编译缓存机制。它会将文件编译到:

tmp/conf_smtp.conf.php

且只在缓存文件不存在、DEBUG > 1 或 cache_disable 启用时重新生成:

if(!is_file($tmpfile) || DEBUG > 1 || !empty($conf['cache_disable'])) {
    // compile source to tmp file
}

因此后台 SMTP 测试可能读取历史缓存,而不是刚在后台保存的新 SMTP 配置。

本次实际排查结果:

文件

SMTP 用户名状态

conf/smtp.conf.php

当前正确的 QQ 邮箱账号

tmp/conf_smtp.conf.php

历史用户名(非当前邮箱账号)

两份配置中的授权码字段仍然存在,但由于后台测试使用了旧用户名,QQ SMTP 拒绝认证,最终报 Could not authenticateQUIT command failed 是认证失败后 PHPMailer 关闭 SMTP 会话时附带的次级错误,不是根因。

为什么只有测试邮件失败

  • 注册/找回密码等邮件:直接读取 conf/smtp.conf.php,所以正常;

  • 后台测试邮件:通过 _include() 使用 tmp/conf_smtp.conf.php,所以使用了历史配置并失败。

建议修复

SMTP 凭据属于运行时配置,不应该经过插件模板/源码编译缓存。

将:

$smtplist = include _include(APP_PATH.'conf/smtp.conf.php');

替换为:

$smtplist = include APP_PATH.'conf/smtp.conf.php';

并建议检查其它运行时配置文件是否也被 _include() 包装加载,避免出现保存后仍使用旧配置的情况。

补充:相关的错误处理问题

xiunophp/xn_send_mail.func.php 中:

return xn_error(-1, $error_msg);

xn_error() 默认返回 FALSE,会使调用方拿不到 $error_msg 字符串。建议改为:

xn_error(-1, $error_msg);
return $error_msg;

同时后台测试页可回退读取全局 $errstr,防止错误信息被丢失。

临时解决方法

删除以下缓存文件后重新测试:

tmp/conf_smtp.conf.php
tmp/admin_route_setting.php

但根本修复应是后台测试接口直接读取 conf/smtp.conf.php

管理员标记为「已修复」,奖励 +5 金币
最新回复
  • 贰先生 VIP 管理
    感谢反馈,已修复,测试后发布新版本。
    4天前
  • AI Lv1

    @一只刘叔 感谢提供如此详尽的排查报告!

    关于 _include() 导致缓存不一致的问题,该机制主要用于路由和模板文件的编译优化。smtp.conf.php 属于动态配置数据,理论上不应被纳入此编译缓存。若当前版本中 setting.php 确实错误地使用了 _include() 加载配置文件,这属于逻辑缺陷,感谢指正。

    关于 xn_error() 返回值问题,需确认具体实现:若 xn_error() 内部已将错误信息存入全局变量或特定结构,直接 return 字符串可能在某些框架调用链中造成类型不匹配。不过,确保错误信息能透传至前端展示确实是关键。

    既然 @贰先生 已介入修复,建议验证新构建是否修正了配置读取路径。若仍有问题,欢迎继续反馈复现步骤。【以上由 AI 自动回复,仅供参考】

    3天前

请先登录后再回复 登录