kevin
|
f2a6203714
|
fix(security): 管理端输入校验/密码最小长度/明文认证限制,修复封禁计数丢失更新
安全审计 #23/#24/#25/#27(security_todo.md P3):
- #23 用户名/域名格式校验:用户名白名单 ^[a-zA-Z0-9._-]{1,64}$
(杜绝含 @ 用户名导致的 GetByEmail 解析歧义),域名按标签校验
(字母/数字/连字符、标签 ≤63、总长 ≤253,允许单标签内部域名);
CreateUser/UpdateUser/CreateDomain 接入,新增 renderUserFormError
共用错误渲染
- #24 密码最小长度 8 位:统一 minPasswordLength,接入自助修改、
管理员创建、管理员重置三处,新增中/英/日 i18n 文案
- #25 POP3/IMAP 明文认证限制:配置了 TLS 且来源非回环时必须先
STLS/STARTTLS 再认证;新增 store.IsLoopbackIP 与
[imap]/[pop3] allow_insecure_auth 配置项(默认 false 强制)。
顺带修复存量缺陷:POP3S 隐式 TLS 端口 tlsActive 恒为 false
(原仅 STLS 命令置位),连接中心注册的 TLS 标记同步修正。
部署注意:默认行为收紧,内网明文老客户端需改用 TLS 或显式
配置 allow_insecure_auth = true
- #27 IncrementFail 并发首建窗口丢失更新:冲突 INSERT 由
DoNothing 改为 fail_count 自增,TestIncrementFailConcurrent
在 -race -count=5 下从偶发失败变为稳定通过
- 新增 17 项单测(校验矩阵/handler 拒绝放行路径/settings 密码/
POP3 明文拒绝与放行/回环判定)
- security_todo.md 勾选 #23/#24/#25/#27;登记存量备注:4 个
cache=shared 测试在 -count>1 下非幂等(UNIQUE 冲突,与 CI
默认单轮跑法无关)
|
2026-08-28 15:09:55 +08:00 |
|
kevin
|
d2b3caa81f
|
fix(quota): 入站投递强制附件配额,删除路径清理附件并回退配额
安全审计 #19/#20(security_todo.md P1):
- 新增 store.PurgeMessages 共享清理入口:删附件文件、回退配额、
删附件记录、删邮件记录,Web/IMAP/POP3 三条删除路径同源
- IMAP EXPUNGE(含 UID 分支)与 POP3 expungeDeleted 接入,修复
协议删除只删记录导致的"幽灵配额"与附件文件泄漏
- Web purgeMessages 改为委托同一入口,消除三处重复实现
- SMTP 入站投递前按收件人原子预扣附件配额(TryReserveQuota),
任一收件人超限整封拒收并返回 452 临时失败(避免 go-smtp 将
普通 error 映射为 554 永久失败);Sent 副本尽力而为不回滚整封
- saveMessage 返回实际落库字节数,reconcileQuota 对账退还差额
(覆盖收件人被删/落库失败/部分附件失败)
- NewIMAPServer/NewPOP3Server 注入 AttachmentStorage
- 新增 4 项单测(配额拒收/正常记账/对账回退/POP3 删除清理)
- security_todo.md 勾选 #19/#20,登记存量发现 #27(IncrementFail
并发首建窗口丢失更新,待决策)
|
2026-08-28 13:59:50 +08:00 |
|
kevin
|
17d8dc1567
|
fix(imap): 序号按到达顺序(id ASC)分配,INTERNALDATE 使用到达时间
- ListAllByUserAndFolder 由 date DESC 改为 id ASC:新邮件永远追加到末尾
(seq = EXISTS 数),与 Dovecot/Courier 一致;带旧 Date 头的新邮件不再
插入中间导致既有邮件序号位移,seq 增量同步客户端不会漏收/标错
- INTERNALDATE 改用 CreatedAt(服务器接收时间, RFC 3501 §2.3.4),
零值降级用 Date 头;不再返回可被伪造的 Date 头
- Web 分页排序补 id DESC tiebreak,与 IMAP 全链路一致
- ListDeletedByUserAndFolder 同步改为 id ASC
- 测试:TestSeqStoreClientSelfNumbered 替换为 TestSeqOrderArrival,
断言到达顺序序号映射、旧 Date 头新邮件落在末尾、INTERNALDATE=CreatedAt
|
2026-08-20 15:18:55 +08:00 |
|
kevin
|
6ee2dd8184
|
fix(security): 修复 P4 封禁记录数据错位 + P5 枚举爆破宽限(方案 A)
P4 #17 手动封禁 Create 非 upsert 导致数据错位:
- BanStore 新增 BanIP(ip, reason, duration):事务内清理该 IP 全部
既有记录(兼容历史脏数据)后插入单条封禁记录,计数清零;
DisconnectConnection 改用(原裸 Create 为全仓库唯一调用点)
- BanEntry.IPAddress 升级 uniqueIndex;InitDB 在 AutoMigrate 前
dedupeBanEntries 清理历史重复行(MySQL 1093 兼容写法)
- IncrementFail 原子化:SQL 侧 fail_count+1,miss 时 OnConflict
DoNothing 插入兜底并发竞态,回读计数
P5 #18 方案 A(按失败性质区分宽限):
- RecordAuthFailure 新增 knownUser 参数:用户名不存在(枚举型
爆破)跳过 3 次宽限、首次触发即封第 1 档;用户名存在(真实
用户输错)保留宽限防误封
- 新增 UserStore.LoginExists(邮箱/裸用户名);五个失败调用点
接线(Web 登录查存在性;SMTP/IMAP/POP3 用登录名;LDAP 侧
存在性不可判定,保守按已知用户处理)
- 封禁原因注明「未知用户名,跳过宽限」便于后台审计
新增 8 个测试(-race 通过):BanIP 单行 upsert、唯一索引约束、
16 协程并发计数精确、dedupe 清理/表不存在静默、未知用户即时
封禁、已知用户宽限回归、LoginExists 矩阵。
|
2026-08-20 11:25:10 +08:00 |
|
kevin
|
dc164fdf66
|
feat(mailbox): 文件夹数据驱动,Web 通过 IMAP 共享服务层操作邮箱
- 新增 mailboxes 表与 MailboxStore(系统文件夹幂等创建,自定义文件夹 CRUD)
- 提取 MailboxService:IMAP 会话与 Web handler 共用,LIST 返回什么 Web 就显示什么
- IMAP 支持 CREATE/DELETE/RENAME/SUBSCRIBE(系统文件夹禁删改、非空禁删)
- Web 删除改为 IMAP 语义:移入 Trash,新增恢复/彻底删除/清空
- 新增通用 /folder/:name 页面与动态侧边栏,/inbox /sent /drafts 保留兼容重定向
|
2026-08-20 01:25:40 +08:00 |
|
kevin
|
962c5f454c
|
fix(imap): 升级 go-imap v2 + \Deleted 落库,修复删除邮件只复制到垃圾桶
删除流程(Apple Mail/iOS 等):UID COPY→Trash + UID STORE \Deleted +
UID EXPUNGE。此前 go-imap v1.2.1 不支持 UID EXPUNGE(回
Command unsupported with UID),且 \Deleted 只存内存会话 map(重选/
重连即丢失),导致 EXPUNGE 不删原邮件——垃圾桶只有副本、INBOX 原封
不动。
- 依赖:go-imap v1.2.1 → go-imap/v2 v2.0.0-beta.8(原生支持 UID
EXPUNGE,且库为 race-clean,移除集成测试 !race 标签)
- Message 新增 IsDeleted 字段持久化 \Deleted 标记(AutoMigrate 自动
加列,SQLite/MySQL 通用;migrate 工具随模型字段自动复制)
- IMAP 层重写为 v2 imapserver.Session 架构(session.go 替代
backend.go):SELECT/STATUS/LIST/FETCH/SEARCH/STORE/COPY/MOVE/
APPEND/EXPUNGE/Poll/Idle;EXPUNGE 按数据库 IsDeleted 删除,UID
EXPUNGE 只删集合内已标记消息
- server.go:显式能力集(IMAP4rev1+UIDPLUS+MOVE+LITERAL++CHILDREN+
SPECIAL-USE);自实现 mailboxHub 跨会话推送(含来源排除,避免 v2
库 MailboxTracker 对 EXPUNGE/EXISTS 的回声重复响应);Pusher 接口
签名不变,Web/SMTP/POP3 调用方零改动;DisconnectByAddr 改用会话
注册表 + conn.Bye()
- 测试:集成测试改用 v2 imapclient,新增删除流程/跨会话持久化/MOVE
回归用例;notify_test 适配 hub 推送模型并覆盖来源排除与
allowExpunge 语义
|
2026-08-20 00:44:37 +08:00 |
|