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 |
|
dsh
|
9fef9da830
|
fix(imap): 新邮件推送补发 EXISTS 通知,修复 Apple Mail 等客户端需手动同步
问题:go-imap 更新通道只能表达 FETCH/EXPUNGE 类更新,新邮件到达时
客户端(IDLE 中)只收到裸 FETCH。不少客户端(如 Apple Mail)只认
RFC 2177 要求的 EXISTS 才会唤醒拉取,表现为'必须手动点击同步'。
修复:PushNewMessage 先向所有已选中该邮箱的匹配连接直接写入
'* N EXISTS'(Dovecot 同款行为),再广播 FETCH 更新。
实测 IDLE 客户端按序收到 '* 21 EXISTS' + '* 1 FETCH (UID ...)'。
|
2026-08-19 10:56:26 -04:00 |
|
kevin
|
278c16c36a
|
fix(imap): 修复多监听器广播更新导致 close of closed channel panic
broadcastUpdate 此前把同一个 backend.Update 对象推送到明文/TLS 两个
监听器的推送通道,两个 go-imap listenUpdates goroutine 各自对
update.Done() 执行 close,二次关闭同一 channel 触发 panic
(server.go:373 close of closed channel)。
修复:按监听器克隆 Update 对象(载荷共享、Done channel 独立),
新增回归测试:两个监听器收到的更新 Done channel 必须不同,且各自
close 不 panic;全量 -race 通过
|
2026-08-19 19:58:18 +08:00 |
|
kevin
|
6a9dcd0285
|
feat(imap): 多客户端状态实时同步 + 当前连接「断开并封禁」
- 推送扩展:IMAP STORE(已读/星标/\Deleted)推送 FETCH 标志更新、
EXPUNGE 推送 ExpungeUpdate(删除前序号)、APPEND/COPY/MOVE 推送
新邮件;POP3 QUIT 删除、Web 标已读/删除同样实时同步到 IMAP 客户端
- Pusher 接口统一 SMTP/POP3/Web 的推送入口,IMAP 内部操作经会话
通道直接入队(非阻塞,满则丢弃)
- 当前连接页新增「断开并封禁」:connhub 支持断开回调,SMTP/POP3
关底层连接、IMAP 经 ForEachConn 按地址断开;一键封禁 180 天并
断开该 IP 全部在线连接,黑名单页可随时解封
- 修复:POP3 PASS 成功后保留完整邮箱(此前被裸用户名覆盖)
- 新增测试:断开/按 IP 断开、flags/expunge 推送内容、POP3 删除推送、
Web 断开封禁处理器;全量 -race 通过
|
2026-08-19 19:56:04 +08:00 |
|
kevin
|
ede85e0698
|
feat(imap): 新邮件实时推送(IDLE)+ 后台当前连接监控
- IMAP 推送:imapBackend 实现 backend.BackendUpdater,SMTP 本地投递
与 Web 写信投递成功后 NotifyNewMessage,挂起 IDLE 的客户端即时收到
新邮件 FETCH 通知(按用户名+INBOX 过滤广播,通道满非阻塞丢弃)
- 当前连接:新增 internal/connhub 连接注册中心,SMTP/IMAP/POP3 三协议
注册/注销/用户名/TLS/活跃时间追踪;后台新增「当前连接」页
(/admin/connections,统计卡片+连接表格,每 5 秒自动刷新)
- 新增测试:connhub 并发安全、推送内容/非阻塞/nil 安全、
后台页面渲染;全量 -race 通过
|
2026-08-19 19:40:05 +08:00 |
|
kevin
|
353bfa88f2
|
feat: 新增 SMTP/IMAP/POP3 协议调用日志(含攻击分析筛选)
- 每个连接记录一条日志:协议、端口、来源 IP、用户名、成功/失败、
失败原因(密码错误/IP封禁/中继被拒/发件人伪造/未认证发信等)、
操作摘要、消息数与会话时长
- 管理后台新增「协议日志」页:按协议/状态/IP/用户名/时间筛选,
今日与历史成功/失败统计卡片,分页查看,可手动清理
- 后台每 6 小时自动清理超出 protocol_log_keep_days(默认30天)
的日志;新增 [web] protocol_log_keep_days 配置项
- 修复 POP3 认证既有 bug:handleUSER 丢弃邮箱域名导致 PASS 永远失败
- 新增 store 单测、SMTP/POP3 端到端测试与模板渲染测试
|
2026-08-19 18:49:29 +08:00 |
|
kevin
|
3f28ec20f4
|
fix(security): 修复 P2 中危项(cookie/协议限速/路径遍历/默认口令/中继TLS/安全头/信息泄露)
- 会话 cookie 增加 Secure 标志;新增 [web].cookie_secure 配置
(默认 true,仅本地 HTTP 调试关闭;缺失字段按安全默认处理)
- SMTP/IMAP/POP3 认证接入封禁体系(store.RecordAuthFailure 与 Web
共用 ban_entries):失败计数达 ban.max_fail_attempts 即封禁 IP,
已封禁 IP 拒绝认证,堵住协议层暴力破解
- 附件存储路径遍历防护重写:FullPath 白名单校验(UUID 文件名格式)
+ baseDir 前缀兜底,非法路径返回错误;Save 扩展名白名单化
- 初始管理员不再使用 admin/admin:密码取 MAILGO_ADMIN_PASSWORD 或
随机生成并打印一次;新增 MustChangePassword 首登强制改密
(管理员重置密码同样触发)
- 外发中继默认验证 TLS 证书(保护 AUTH 凭据,防 MITM),直投 MX
保持机会式 TLS;新增 outbound.relay_tls_insecure 开关(默认 false)
- 新增安全响应头中间件:HSTS、X-Frame-Options DENY、nosniff、
Referrer-Policy、基础 CSP(frame-ancestors 'none' 防点击劫持,
connect-src/form-action 'self' 防数据外泄)
- LDAP/OAuth 登录错误统一为通用文案,原始错误只写日志,
不再回显邮箱/内部细节(防用户枚举与信息泄露)
- 新增 25 个回归测试:cookie 标志、封禁阈值、路径遍历用例、
中继 TLS 验证(自签证书 STARTTLS 集成)、安全头、OAuth 文案
部署注意:升级后所有会话失效需重新登录;若直接以 HTTP 提供
服务需显式配置 cookie_secure = false。
|
2026-08-19 16:45:21 +08:00 |
|
dsh
|
f0b9ad3e6f
|
feat: 管理后台一键从 Caddy 获取证书 + TLS 证书热加载
- 域名编辑页新增“从 Caddy 获取证书”按钮:一键把本机 Caddy 已签发的
证书与私钥导入该域名的 TLS 目录并自动启用 TLS,支持通配符证书
(如 *.example.com 可匹配 mail.example.com),成功/失败均回显横幅
- 新增 internal/caddycert:搜索 Caddy 证书存储(同步镜像目录优先、
caddy.data_dir 与常见位置兜底),校验密钥对/有效期/SAN,并给出
可操作的中文错误提示(未找到/证书无效/权限不足)
- install.sh 新增 setup-caddy-cert:安装 root 权限的 systemd
path+timer 同步任务(mailgo-caddy-sync),把 Caddy 证书树镜像到
/srv/mail_go/tls/caddy(证书续期后自动更新、每日兜底),另授予
ACL 作为直接读取兜底;install 时自动检测并配置
- 新增 [caddy] data_dir 配置节,支持自定义 Caddy 数据目录
- 新增 internal/tlsutil:TLS 证书热加载器,每次握手按需重载证书
文件(mtime 检测),重载失败继续使用旧证书兜底并节流重试;
应用于 SMTPS 465/IMAPS 993/POP3S 995 与 STARTTLS,导入或上传
新证书后无需重启服务即生效
- 证书来源动态切换:协议显式配置优先,否则取首个启用 TLS 且有证书
的域名(10 秒缓存),新域名一键导入证书后自动切换
- 更新 README 与界面文案(去掉“重启服务生效”提示)
|
2026-08-16 23:39:43 -04:00 |
|
kevin
|
59719586a1
|
修复部分功能
|
2026-06-02 20:33:08 +08:00 |
|
kevin
|
9e50d05e71
|
一阶段ok
|
2026-06-01 18:59:55 +08:00 |
|