dsh/mailgo:fix/auth-reset-and-date-sort
main
本次包含两个独立修复:
根因:Status() 硬编码 UidValidity=1。数据库重建后消息 ID 空间 完全变化(uid 2-166 对应完全不同的邮件),但 UIDVALIDITY 不变, Thunderbird 认为本地缓存(旧 uid 1-166)仍然有效,只下载"新增" (uid 167:*)与"缺失"(2,4,8,9)的少数邮件——列表只剩 1-3 封, 每次刷新数量随机。 修复(RFC 3501 UIDVALIDITY 语义):新增 mailbox_states 表, 每(用户,文件夹)首次访问随机生成并持久化 UIDVALIDITY;数据库 重建后新值触发客户端丢弃缓存全量重同步。0 值修正,不同用户/ 文件夹互相独立。 新增 TestMailboxStateUidValidity 单元测试。
问题:ResetFail 只在 Web 登录调用,协议层失败计数只增不减。 合法用户的客户端(手机 APP 用裸用户名重试、配置向导探测、输错 密码等)失败次数持续累积,每达到阈值就触发一次封禁档位,从第 4 次触发起真实封禁 30 分钟+——用户被反复误封,手机端表现为一直 卡在"正在接收邮件"。 修复: - IMAP/SMTP/POP3 认证成功路径调用 Bans.ResetFail(与 Web 一致) - 新增 UserStore.AuthenticateLogin:支持裸用户名(如 "kevin"), 唯一归属时自动解析到其域名;跨域名同名歧义时要求完整邮箱 - 新增 TestAuthenticateLoginBareUsername 单元测试
根因:date 列在 SQLite 中是文本,历史数据混存 +08:00/-04:00/+00:00 等时区偏移,ORDER BY date DESC 变成字符串字典序而非时间序: - Web 列表最新邮件排不到最前(如 22:21+08 的邮件排在 20:03+08 后面) - IMAP 序号与客户端按日期排序的视图不一致 修复: - mailStore.Create 统一 msg.Date = msg.Date.UTC()(所有写入路径 共用:SMTP/IMAP APPEND/Web/外发回执),新数据字典序即时间序 - 生产数据一次性迁移为 UTC 格式(130 条,Python 全量解析转换) - 验证:kevin INBOX 排序 172→170→166→164…(严格最新在前)
- 新增 [web].timezone 配置(IANA 时区或固定偏移,默认 Asia/Shanghai) - 新增 localTime 模板函数;shortDate 的"今天"判断也按展示时区 - view.html 邮件时间改用 localTime 渲染
问题:go-imap 更新通道只能表达 FETCH/EXPUNGE 类更新,新邮件到达时 客户端(IDLE 中)只收到裸 FETCH。不少客户端(如 Apple Mail)只认 RFC 2177 要求的 EXISTS 才会唤醒拉取,表现为'必须手动点击同步'。 修复:PushNewMessage 先向所有已选中该邮箱的匹配连接直接写入 '* N EXISTS'(Dovecot 同款行为),再广播 FETCH 更新。 实测 IDLE 客户端按序收到 '* 21 EXISTS' + '* 1 FETCH (UID ...)'。
原实现每封匹配消息单独 UPDATE + GetByID + seqOf 全量扫描(含大 附件 raw_data),手机整批标记已读(60+ 封)时产生 60 次写 + 180 次全量读,连接被长时间占住,其他连接响应被推送洪泛阻塞。 优化:收集目标状态后合并为单条 UPDATE ... IN 批量写;推送更新 直接用已加载列表的序号与目标状态(buildFlagsUpdateAt),不再 重复查库。实测 19 封批量 STORE 服务器耗时 372µs。
No dependencies set.
The note is not visible to the blocked user.
本次包含两个独立修复:
1. 认证(f48776e)
2. 日期排序(d9bb3cb)