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 语义
This commit is contained in:
@@ -33,6 +33,13 @@ type MailStore interface {
|
||||
// SetFlaggedStates 批量设置多封邮件的星标状态(单条 UPDATE ... IN)。
|
||||
SetFlaggedStates(ids []uint, flagged bool) error
|
||||
MoveToFolder(id uint, folder string) error
|
||||
// SetDeletedStates 批量设置多封邮件的 \Deleted 标记(单条 UPDATE ... IN)。
|
||||
SetDeletedStates(ids []uint, deleted bool) error
|
||||
// ListDeletedByUserAndFolder 列出某文件夹中所有已标记 \Deleted 的邮件
|
||||
// (按 date DESC, id DESC 排序,与全量列表一致,序号映射全链路相同)。
|
||||
ListDeletedByUserAndFolder(userID uint, folder string) ([]db.Message, error)
|
||||
// DeleteMany 批量硬删除多封邮件(单条 DELETE ... IN)。
|
||||
DeleteMany(ids []uint) error
|
||||
Delete(id uint) error
|
||||
CountUnread(userID uint, folder string) (int64, error)
|
||||
CountByFolder(folder string) (int64, error)
|
||||
@@ -130,6 +137,32 @@ func (s *mailStoreGorm) MoveToFolder(id uint, folder string) error {
|
||||
return s.db.Model(&db.Message{}).Where("id = ?", id).Update("folder", folder).Error
|
||||
}
|
||||
|
||||
// SetDeletedStates 批量设置多封邮件的 \Deleted 标记。
|
||||
func (s *mailStoreGorm) SetDeletedStates(ids []uint, deleted bool) error {
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
return s.db.Model(&db.Message{}).Where("id IN ?", ids).Update("is_deleted", deleted).Error
|
||||
}
|
||||
|
||||
// ListDeletedByUserAndFolder 列出某文件夹中所有已标记 \Deleted 的邮件。
|
||||
func (s *mailStoreGorm) ListDeletedByUserAndFolder(userID uint, folder string) ([]db.Message, error) {
|
||||
var messages []db.Message
|
||||
if err := s.db.Where("user_id = ? AND folder = ? AND is_deleted = ?", userID, folder, true).
|
||||
Order("date DESC, id DESC").Find(&messages).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// DeleteMany 批量硬删除多封邮件。
|
||||
func (s *mailStoreGorm) DeleteMany(ids []uint) error {
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
return s.db.Where("id IN ?", ids).Delete(&db.Message{}).Error
|
||||
}
|
||||
|
||||
// Delete removes a message by ID.
|
||||
func (s *mailStoreGorm) Delete(id uint) error {
|
||||
return s.db.Delete(&db.Message{}, id).Error
|
||||
|
||||
Reference in New Issue
Block a user