23 KiB
云端全项目测试报告
测试日期:2026-09-20,时区 Asia/Shanghai。工作区:D:\Desktop\Smail。服务器:47.108.78.12,页面:https://web.solit.cn/。
结论与任务状态
已完成一轮全项目自动化测试、发现问题的修复、Linux 构建和云端部署,并完成核心账号安全及邮件协议实机验证。接续补齐了内置 AliDNS 挑战、生产续期入口和 Nginx 自动换证同步,新增修改完成受影响包回归。当前没有未解决的自动化测试失败;真实外部邮箱收件、外部客户端网络路径和自然到期长期调度等仍未验收,不能宣布整个项目最终验收通过。
- [✓] 已按授权备份、清理 Smail 相关环境,重新初始化测试数据库。接续测试复用本轮数据库,没有重复清库。
- [✓] 修复测试发现的问题,相关包完成复测;最新程序已部署,云端和本地摘要一致。
- [✓] 续期补全前的业务代码完成一次独立的 Linux 后端全量复测,66 个包均退出成功;测试程序摘要、逐包日志与汇总已交叉核对。后续续期及配置校验修改按受影响包复测,不混称最新版重新完成 66 包全量。
- [✓] 三类账号登录、TOTP 选择、提醒行为、邮件验证码跨场景消费、密码重置和客户端凭据撤销完成相应实机验证。
- [✓] 项目部署包只包含三个程序与四个运行目录,没有加入 Python、部署或续期脚本。
- [✓] 本轮临时 TOTP、外部邮箱绑定均已停用,账号密码保持用户指定值。
- [✓] 实时 DNS 控制面、两个权威 DNS 和公共 DNS 均确认泛解析生效;邮件记录保留,DKIM 与运行密钥匹配。
- [✓] Web 及已启用邮件 TLS、STARTTLS 入口返回同一张覆盖根域名的泛域名证书。
- [!] 三个指定的 163 邮箱尚未完成真实收件和绑定验证。
- [!] 当前客户端到公网邮件端口的连接路径未通过,不能声称外网邮件客户端收发通过。
- [✓] 内置 AliDNS 在真实 staging CA 完成根域名及泛域名挑战、签发、记录清理;生产续期入口成功,配置变化自动触发 Nginx 同步与平滑重载。
- [!] 尚未等待证书自然进入续期窗口,未完成内置定时调度的长期运行验收。
- [!] Windows 提权 Named Pipe、依赖外部服务的插件业务等不在本轮 Linux 实机通过范围内。
本轮修复
| 提交 | 问题与结果 |
|---|---|
c82be24 |
修复全量测试的密码容量竞态,更新与现有行为不一致的审查夹具及前端说明。 |
b062ca6 |
项目 DNS 签发同时覆盖主域名及泛域名,保留两条同名 TXT 挑战。 |
65e61a3 |
修复真实数据库迁移中对文本主键错误处理序列的问题,校正日志测试。 |
b515186 |
公网地址探测支持失败回退,限制并发请求的总等待时间。 |
7aec99d |
密码重置同步撤销旧客户端授权码,补充事务回滚及用户隔离回归。 |
e0baf27 |
未认证 POP3 的 QUIT 立即回复并关闭连接,不提交邮箱更新。 |
310ad01 |
停用的外部邮箱允许所属用户重新绑定、切换用途;清除旧验证状态并要求重新验证。停用同时失效绑定和变更挑战,保留跨用户隔离及主要邮箱数量限制。 |
747f79a、951fdc0、1790e1f |
加入内置 AliDNS 凭据配置、受控证书导出与同步;修复只读沙箱权限检查,并拒绝硬链接私钥。 |
62ed09f |
修复 Nginx 配置检查在只读沙箱中无法打开 PID 文件的问题。 |
87cd28f |
DNS 清理改用受限凭据已有授权的记录列表接口,分页后精确核对 ID、名称、类型和值,只删除本轮创建的记录。 |
6920bff |
续期后上一张证书的引用格式校验不再依赖当前工作目录权限,实际证书路径、权限及密钥匹配校验保留。 |
每轮代码修改前均保存中文 Git 基线并推送。一次文档基线推送出现认证失败,重试后成功。没有使用宽泛暂存或提交测试凭据。
自动化测试证据
前期云端原始日志根目录:/var/tmp/smail-cloud-tests-20260920/。最新一次全量复测位于 /var/tmp/scf20/final-results/;完整本地副本位于 test-log/cloud-final-20260920/。
| 范围 | 结果 | 证据 |
|---|---|---|
| Linux 后端单次全量 | 66 个包均退出成功,1955 个 PASS 标记、0 个 FAIL 标记、5 个 SKIP 标记 | /var/tmp/scf20/final-results/summary.json、results.json 及逐包日志 |
| 最新前端 | 200 项通过,0 失败、0 跳过 | 本地 test-log/run-2026-09-19T21-11-24-986Z-25484/frontend.log |
| Windows 构建互斥与测试入口 | 4 项通过;Linux 专用项在 Windows 跳过 | 本地 test-log/run-2026-09-19T16-13-15-667Z-3920/deployment.log |
| Linux 资源策略 | 15 项通过 | 云端 resource-policy.log |
| 实际服务资源只读预检 | 通过,无失败项;不替代业务验收 | 云端 final-resource-check.json |
| 邮箱重新绑定修复的本地受影响包 | externalemail、controllers、recovery、verification 均通过 | 本地 test-log/run-2026-09-19T19-10-20-850Z-26796/backend.log |
| 邮箱重新绑定修复的 Linux 复测 | externalemail、controllers 均 EXIT=0 | 云端 rebind/externalemail.log、rebind/controllers.log |
| 续期及配置校验最终本地回归 | config、ssl、controllers、cron_server 通过;smail-config 编译通过,无测试文件 | 本地 test-log/run-2026-09-19T21-23-32-547Z-34536/backend.log |
| 最终 Linux 配置包 | 非特权 nobody 用户执行,413 个 PASS 标记、0 FAIL、0 SKIP,退出码 0 | /var/tmp/smail-tls-20260920/runtime/config-cwd-full.log |
| 最终 Linux 证书包 | 非特权 nobody 用户执行,50 个 PASS 标记、0 FAIL、4 SKIP,退出码 0 | 同目录 ssl-cwd-full.log |
上述 66 包全量运行时间为 03:58:42—04:05:54,systemd 记录耗时约 7 分 12 秒、内存峰值 256.5 MiB,结果为成功。66 个包来自同一源码快照,顺序执行,没有合并旧结果或以旧成功替换失败。PASS 标记包含父测试和子测试,不能表述为 1955 个独立案例;主包只有显式跳过的旧集成入口,退出成功不代表该入口已执行。
该次全量的测试源码快照为 418435cb94f62a11e0f5de7fbd913a20f05f7c24,与当时部署源码 310ad01 的后端、前端、对应测试、部署及插件目录无差异。实际测试子进程使用 nobody(UID/GID 65534),每包使用独立临时运行目录,没有指向 Smail 运行数据库。真实 MySQL、PostgreSQL 及跨库迁移集成用例全部执行通过。04:45 后新增续期实现及修复的验证范围为上表中的受影响包,最终部署源码为 6920bff。
已将云端原始证据下载到本地,核对 66 个包的集合无遗漏或重复、退出码全部为 0、每个测试程序 SHA-256 与本地构建收据一致、逐包日志计数与汇总一致。源码归档摘要也与构建收据一致。
- 构建收据:
test-log/cloud-final-20260920/build-receipt.json。 - 源码归档 SHA-256:
8b5475f0dc2e3036c819bcdf70b2fa44d3ab3e99246d7cc1c444d51a00da8c8d。 - 证据归档:
test-log/cloud-final-20260920/final-evidence.tar.gz。 - 证据归档 SHA-256:
3675c8f5a61a9af5373d0a6dfe3b952e53a068259a321d41cda2d49f9ccf3fe5。
此前 latest-summary.json、latest-packages.json 的 1953 个 PASS 是首轮全量与受影响包复测合并的历史统计,仍保留用于追溯;当前结论以本次 1955 个 PASS 的单次全量结果为准。
五个后端跳过项:
TestProductionPluginIsolationPolicy:Windows 专用。TestSecuritySetupBrowserFixture:需要显式启用的长期浏览器夹具。TestSystemdResultPrompt:需要隔离的 systemd 人工交互。TestSystemdCancelledInputResult:同上。TestMaster:旧集成入口,需显式启用,不能直接指向运行库。
本轮另行完成真实 smail-admin 启动、安全验证、成功提示及 stop 取消操作;自动化跳过项仍按跳过记录。Windows 未提权环境未完成 Named Pipe 验收,不列为通过。
云端业务验证
账号与登录
xuans为超级管理员,testadmin为管理员,testuser为普通用户。最终均保留用户指定密码;本文不记录密码、验证码、恢复令牌或 TOTP 密钥。- 未配置安全验证的超级管理员登录后,页面强制要求至少启用一种方式。最终浏览器重新加载后可见该中文弹窗,没有跳过保护。
- 普通用户点击“我知道了”后可继续,注销并重新登录会再次提醒未完成的安全设置。
- 三类账号均具备用户可选的 TOTP 功能。普通用户实测绑定、登录和停用;密码阶段约 473 毫秒、TOTP 验证约 83 毫秒。其他两类账号本轮早期测试完成后也已停用测试 TOTP。
- 登录密码正确后,有主要外部邮箱的账号返回验证选择,
delivery_status=idle,没有自动发邮件;只有主动发送才进入sending。
邮件验证码与公开密码恢复
使用普通测试用户的真实站内收件箱临时验证管理员,邮件经项目正常投递与邮件 API 读取,没有改数据库伪造验证结果。此闭环证明应用链路,不替代 163 外部收件验收。
| 步骤 | 最后一次实测耗时 | 结果 |
|---|---|---|
| 停用邮箱重新绑定为主要邮箱 | 3190 毫秒 | 成功,仍须邮件验证 |
| 确认重新绑定 | 84 毫秒 | 成功 |
| 管理员密码阶段 | 341 毫秒 | 返回 email 选择,邮件 idle |
| 主动发送登录验证码 | 71 毫秒 | 返回 sending,后台完成真实投递 |
| 邮件码完成登录 | 103 毫秒 | 成功 |
| 立即发起公开恢复 | 143 毫秒 | 识别管理员及 email 方式 |
| 紧接着发送恢复邮件 | 2628 毫秒 | 成功,没有被登录验证码冷却阻塞 |
| 邮件码验证恢复身份 | 74 毫秒 | 发放一次性重置凭证 |
| 设置密码 | 307 毫秒 | 重置成功 |
| 重置后密码登录 | 365 毫秒 | 成功进入验证选择 |
| 再次主动发送登录码 | 89 毫秒 | 成功 |
以上为当次单请求观测,不是负载压测或全网延迟保证。公开恢复请求未携带登录 Cookie 或 CSRF 头。测试完成后通过正式接口停用临时邮箱;管理员再次直接登录约 430 毫秒,超级管理员约 307 毫秒。
邮件协议与重置撤销
- 服务器本机经域名校验的 TLS 完成 SMTP 投递、IMAP 查询读取和 POP3 收取,数据库收件归属核对正常。证据:
protocol-acceptance.json。 - 真实密码重置后,旧客户端授权码在 SMTP、IMAP、POP3 均被拒绝。证据:
revoke/live-revocation.json。 - 未认证、输入 USER 后及错误密码后的 POP3 QUIT 均立即回应并关闭连接;相关包回归通过。证据:
revoke/live-pop3-quit.json。 - 超级管理员登录页恢复通道保持拒绝;本机重置使用受保护 Unix Domain Socket。最终
/run/smail/admin-control.sock权限为0600,所属用户/组为smail,未增加公网重置 TCP 监听。 - smail-admin 仅显式 start 进入交互,stop 取消;restart、reload 及变体不能开启新的重置交互。systemd 的 restart 仍可能先停止原交互,这一系统行为边界详见《管理员重置命令限制验收》。
证书与网络限制
真实证书签发者为 Let's Encrypt YR1,SAN 为 solit.cn 和 *.solit.cn,有效期从 2026-09-19 16:44:26 UTC 至 2026-12-18 16:44:25 UTC。服务器通过回环和公网地址连接 443、465、993、995,使用实际域名 SNI、系统 CA 进行校验,均通过 TLS 1.3。浏览器 HTTPS 页面可访问。
本机系统 DNS 将三个邮件子域名解析到 198.18.2.x;本机 Python 不论域名连接还是强制公网 IP,连 443 也发生 TLS EOF。现有证据只能说明客户端网络路径未通过,不能归因为云端证书错误,也不能声称公网邮件客户端收发正常。本轮没有修改本机网络设置。
Google 公共 DNS 已查到 DKIM;对 1.1.1.1 的 UDP 查询超时,未计为通过。本轮 ACME TXT 清理仅针对新建的两个记录 ID,核对剩余为零,既有记录保留。
03:32—03:44 补充实测
以下为接续时重新采集的实时证据,不依赖测试参数或历史快照判定通过。云端证据位于 /var/tmp/smail-cloud-tests-20260920/;本地副本位于忽略目录 test-log/cloud-audit-20260920/。
| 核验项 | 结果 | 证据 |
|---|---|---|
| DNS 控制面 | 阿里云当前返回 16 条记录,* A 47.108.78.12 已启用 |
本地 test-log/cloud-dns-current-20260920.json |
| 权威及公共解析 | dns13.hichina.com、dns14.hichina.com、8.8.8.8 共 33 次查询均返回 NOERROR;随机一级子域名、Web 和邮件服务地址均指向服务器 |
live-dns-audit.json |
| 邮件记录保留 | MX、SPF、DKIM、DMARC 均可查到;与清理前快照相比,没有删除原有记录,只新增泛解析并更新 Smail 的 default._domainkey 公钥 |
同上及本地清理前快照 |
| DKIM 密钥匹配 | 三个 DNS 查询源中的公钥均与 /opt/smail/ssl/dkim/dkim.priv 推导出的公钥一致;只比较公开材料,不输出私钥 |
live-dkim-match.json |
| 运行域名 | 邮件主域名为 solit.cn,后台为 web.solit.cn,公开 HTTPS 端口为 443;域名来自部署配置 |
live-domain-configuration.json |
| 统一证书 | 回环 443、8002、465、993、995,以及服务器经公网 IP 访问 443、465、993、995,全部通过系统信任链校验且指纹一致;443、8002 额外使用根域名 SNI 校验通过 | live-certificate-unification.json |
| STARTTLS 证书 | 回环 SMTP 25/587、POP3 110 升级为 TLS 1.3,证书指纹与上述入口一致 | live-starttls-certificates.json |
| 浏览器状态 | 实际 HTTPS 页面为安全上下文,/api/ping 两次返回 200,约 314 和 164 毫秒,超级管理员强制安全设置弹窗可见 |
本地 live-browser-check.json 保存最后一次结果 |
统一证书 DER SHA-256:f369937771b4b3bd4fc1ea624a8eed30e1451c8bcefdcd1c9c15043a33113018。
DKIM 公钥 DER SHA-256:df9958f7e8c20c7d7f8735bb062f7bd7485bbee3bbd254930d7ae8d68ae6731c。
上述 TLS 连接共 14 次,其中服务器经公网 IP 访问内部 8002 的两次连接超时,不列为通过;回环 8002 校验通过,公开后台仍从 443 访问。本轮没有开放内部端口。IMAP 当前使用 993 隐式 TLS,源码和现行默认端口策略一致;143 未启用,连接被拒绝,没有将其计为 STARTTLS 通过。
本机系统 DNS 此次将 Web 解析到 198.18.1.254,邮件地址仍解析到 198.18.2.x。本机 curl 和经本地 HTTP 代理的 Python TLS 连接仍在握手阶段失败;浏览器 HTTPS 正常。没有因此修改系统 DNS、代理或防火墙,也没有将服务器自身访问公网 IP 等同于外部客户端验收。
另发现既有 aliyun-cn-hangzhou._domainkey 同名 TXT 有两条,其中一条公钥明显截断。该记录属于既有阿里云邮件链路,本轮未删除或修改;Smail 的 default 选择器公钥匹配已单独通过。保留 DNS 记录不代表既有阿里云邮件链路也已验收。
仍未通过的项目
项目托管启用内置续期检查,手动及代理托管不触发 ACME,策略测试通过。04:45 后已补齐 AliDNS 自动管理 TXT 及 Nginx 自动同步,实测结果如下。尚未验证自然到期后的长期调度。服务器不依赖外部部署或续期脚本,没有新增外部 ACME 定时器。
指定的三个 163 地址尚未完成真实收件及绑定验证,本轮没有向这些外部收件箱发送测试邮件。后续需由各邮箱持有人接收真实验证码,再通过正式绑定流程完成验证。
04:45—05:40 内置续期与换证补充验收
实际 DNS 挑战与记录保留
通过正式配置接口、超级管理员重新认证及临时 TOTP,保存 management=project、challenge=dns、dnsProvider=alidns、dnsZone=solit.cn。两项凭据加密保存在配置中,公开接口不回填密文或明文。测试后已通过正式接口停用临时 TOTP。
第一次 staging 签发后的清理失败,原因是受限凭据无权调用 DescribeDomainRecordInfo,返回 Forbidden.RAM。该轮明确计为失败,原始日志保留;核对并清理该轮两个记录 ID 后,改用已获授权的 DescribeDomainRecords 分页精确查询,无须扩大云账号权限。
修复后第二次 staging 实测 33.39 秒完成 solit.cn 和 *.solit.cn 的新挑战、签发及清理。staging 证书只保留在测试内存,没有安装至线上。修复前后的四次最终库存均与原始 16 条记录逐条一致,既有记录全部保留,本轮新增挑战没有残留。原本已有的一条 _acme-challenge TXT 同样保留,不将“本轮无残留”描述为所有挑战 TXT 数量为零。
生产续期与 Nginx 自动同步
显式云端测试调用项目生产入口 GenSSL(true),3.90 秒成功保存新证书,配置代次 3→4。生产 CA 复用了有效授权并跳过 DNS 挑战,不能声称该轮重新验证 TXT;真实新挑战由前述 staging 独立证明。为避免两个配置管理器并发,此次测试入口执行前短暂停止 Smail,完成后自动恢复,因此不作为邮件连接连续性或自然到期调度证明。
配置更新自动触发 smail-tls-sync.path;该原生 systemd 单元调用程序本体 smail-config --export-project-tls,原子更新 /etc/nginx/smail/tls.pem,再执行 nginx -t 和平滑 reload。没有 Python 或 shell 续期程序。Nginx 主 PID 始终为 578671,未停止或重启;本轮没有验证重载期间其他站点的长期连接连续性。
同步程序只接受项目受控平铺证书,拒绝符号链接、硬链接及不安全权限;相同内容不重复写入,失败保留原文件。同步服务的只读沙箱仅放行 /etc/nginx/smail、Nginx 日志及 /run/nginx.pid。之前只读目录 chmod 和 Nginx PID 文件访问失败均已修复并实机复测,日志保留失败与成功过程。
当前证书覆盖 solit.cn、*.solit.cn,到期时间 2026-12-18T20:12:03Z;DER SHA-256 为 117d6f2b5b147ea7b98f84d44b22cd1580ffd489eddfdb680d8372f60bc6f2ba。项目新旧两套证书均保留,Nginx 合并文件为 0600 root:root。Nginx 仍使用 HTTPS 8002 上游、web.solit.cn SNI 和系统 CA 校验。
续期后配置加载问题
库存复查发现 config.Init() 报 invalid SSL configuration。在相同配置下,旧测试程序从 /opt/smail、/tmp 成功,从 /root 切换为 smail 用户后失败。原因是上一张证书引用的格式校验调用当前目录绝对路径解析,受到无权访问的工作目录影响,凭据和证书本身未损坏。
新增非特权 Linux 回归先证明旧代码失败,再改为纯引用格式检查,保留平铺名称、成对 token、路径边界及实际文件校验。修复后受限目录场景、路径逃逸/错配拒绝、配置及证书全包回归均通过;相同线上配置从 /root 以 smail 身份读取库存也成功。原始失败日志 dns-final.log 与 runtime/cwd-before.log 均保留。
浏览器与证据归档
05:31 实际桌面浏览器检查 SSL 配置页:项目托管、DNS 验证、阿里云自动续期、托管域名正确显示。两项凭据输入框为空并显示“已设置”,公开接口没有密钥内容。视口 1277×613,无横向溢出、无 HTTP 4xx/5xx 资源;配置读取 67 毫秒。检查后停用临时 TOTP,05:32 确认强制安全设置提示恢复,/api/ping 200、155 毫秒。这是单次观测,不代表负载测试。
05:39 使用当前正式浏览器会话注销后,以用户指定的 xuans 账号密码重新登录:注销 162 毫秒、登录 465 毫秒,HTTP 200、业务错误码 0;认证成功后仍要求至少启用一种安全验证。测试开始时在未注销的强制设置会话内直接调用登录接口,被安全设置中间件拒绝,不能把该拒绝误判为密码错误;随后按完整注销、登录流程验证通过。没有修改账号密码。
云端原始证据:/var/tmp/smail-tls-20260920/live/ 和 runtime/。本地归档:test-log/tls-acceptance/evidence.tar.gz,SHA-256 4990b3502df57fe7af33593ed4c532c39cda208e30e7bce35e2026b493d3c6a2,与云端一致。归档已下载,逐项核对 DNS 集合、失败/成功标记、数据库状态及程序摘要;核对结果为 verified-evidence.json,浏览器结果为 browser-ssl-evidence.json。
最终证书包的四项 SKIP 是需显式启用的真实云端入口;staging、生产续期及库存已在独立日志中执行,不因全包运行时跳过而冒充该次全包已执行真实签发。自然到期长期调度、外部邮箱和外部邮件客户端等剩余边界不变。
最新交付与运行状态
源码提交:6920bff39007c9a2305bb57c47bd27614e17a83c。运行版本:test-222651378aff。后续仅文档和基线提交,不改变部署程序。
发布包:out/release/Smail_linux_amd64.tar.gz。文件结构:
smail/
├── smail
├── smail-admin
├── smail-config
├── config/
├── data/
├── log/
└── ssl/
| 文件 | SHA-256 |
|---|---|
| 发布包 | c93c621911fa70e5b98ce8853d9e4019c2289748a218c8ccc3d696ebc01fb991 |
| smail | e7b6524f148ef01922e628802020c9288ee7b0f0a384c0192c9bd6a988907b96 |
| smail-admin | 1c78e5635d1e7fa4680db47d51d5293e2993b357627d56dbc633597f3f49996e |
| smail-config | 044d9d5b34901c4f6a756b9105ca181fd0767d8e664d222e23ee33ecec79816b |
本地构建收据:out/release-receipts/Smail_linux_amd64.json。三个云端文件均与收据一致。前端和内置插件构建完成;编辑器分块大于 500 KB 的既有构建提示仍存在,没有构建失败。
05:27:58 完成最后一次人工安装和启动。05:32 复核 Smail PID 为 719778,自动重启次数为 0,Nginx PID 578671、active。回环 443(Web 和主域名 SNI)、8002、465、993、995 六次连接均通过系统信任链与主机名校验,使用 TLS 1.3,证书指纹一致。两个数据库 integrity_check 均为 ok;启用的 TOTP 数量为 0,未停用的外部邮箱绑定数量为 0。最后一次启动后的 systemd warning 级日志查询无记录。本机恢复 socket 保持 0600 smail:smail。
最后一次部署前备份:/var/backups/smail-full-test-20260920/pre-cwd-fix/,含三个旧程序及停服时的配置、数据、证书归档。同级 pre-auto-dns/、pre-renewal/、pre-rebind/ 保留前序状态。测试日志和测试二进制保留在 /var/tmp/smail-cloud-tests-20260920/、/var/tmp/smail-tls-20260920/,不属于运行依赖;没有擅自删除验收证据。FDM、Scert、MySQL 和 PostgreSQL 未因最后一次 Smail 更新而停启;Nginx 在真实换证时平滑重载,最终程序更新没有再次重载。
公网恢复入口已通过正式配置流程设置 http.publicHttpsPort=443;/public-password-recovery 跳转到 https://web.solit.cn/rest/,不再暴露内部 8002 端口,恢复页面返回 200。