

图一是点击“保存模板”前的默认邮件模板,图二是点击“保存模板”后的默认邮件模板。
根因:框架 param() 默认开启 htmlspecialchars,把你的 HTML 模板“污染”后存盘
转义发生的位置(三处代码串联):
1、后台保存入口 admin/route/setting.php 约第 1120 行:
$bodies = param(‘body’, array(‘’, ‘’)); // 注意 body 可能有 HTML作者注释里自己写了“注意 body 可能有 HTML”,但 param() 的第三个参数 $htmlspecialchars 默认是 TRUE(xiunophp/misc.func.php 第 71 行)。
2、框架层 param_force() 第 143 行对每个数组元素执行:
$htmlspecialchars AND $v = htmlspecialchars($v);于是 POST 过来的 <div style="..."> 在入库前就被转成了 <div style="...>,写进 conf/email_templates.conf.php
3、下次打开设置页,模板第 39 行 esc_html($tpl[‘body’])(输出侧防 XSS,本身正确)再转义一次,textarea 里渲染出来的正是你图二看到的<div style="... 。
还有一个隐藏影响:实际发注册验证码邮件时(xn_email_template() 直接读这个 conf),邮件正文发的也是被转义过的实体文本,收到的邮件 HTML 会是乱的。修复代码后需要把三个模板重新保存一次。【PS:实践测试发送的确如此】
修复方法
改 admin/route/setting.php 两行(给 body 和 subject 关闭入参转义):
// 修改前
$subjects = param('subject', array(''));
$bodies = param('body', array('', '')); // 注意 body 可能有 HTML
// 修改后:第三参 FALSE = 不做 htmlspecialchars
$subjects = param('subject', array(''), FALSE);
$bodies = param('body', array('', ''), FALSE);安全性没有问题:输出侧 esc_html() 仍然对 textarea/value 转义(防 XSS 的正确位置就在输出侧);发信时 body 本来就是按 HTML 正文发送的;写 conf 用的是 var_export() 序列化,无注入风险。
修完后到后台把三个邮件模板(注册验证码、重置密码、更换邮箱)【PS:其实是五个邮件模板】的内容重新粘贴保存一次,把已污染的实体文本覆盖掉即可。
两点提醒:这是改程序源码,升级 XIUNOX 会被覆盖,升级后需重新打上;建议顺手给作者提个 issue——这是明确的 bug,一行注释都写对了、参数没传。
以上是AI分析和我自己实践,仅供作者及论坛各位大神参考。
如果,不想修改源码,我个人认为,目前暂时不在后台保存,在/conf/email_templates.conf.php里面直接修改保存。【PS:实践测试发送没有问题】
Bug反馈
- 程序版本:
- Xiuno X 最新版
- PHP版本:
- php8.5
- MySql:
- 8.4
- 复现步骤:
- 1.登录后台-2.站点设置-3.SMTP设置-4.邮件模板-5.保存模板-五个默认邮件模板出现乱码
- 预期结果:
- Bug 描述:
- SMTP设置邮件模板(默认)保存后,出现乱码
- 错误信息:
- 错误日志:
-
如果不按照提示进行填写,复制粘贴相同信息,将会被删除并扣除金币。


