使用Mailkit.Imap获取Office365收件箱正式邮件 规避UniqueId不同的重复邮件问题
解决方案
问题本质
你遇到的是Office365 IMAP接口的固有特性:带附件的大邮件投递到服务器时,会先生成临时可见的不完整副本,待全部数据落盘后再删除临时副本、生成正式的完整邮件,两个副本的UniqueId不共享。
可行方案
方案1:增加冷却窗口+草稿过滤(最易用,适合大部分场景)
临时副本的存在时长最多不超过15秒,可在搜索时过滤掉15秒内新生成的邮件,同时排除草稿标记的邮件,直接从源头避免拉取到临时副本:
Dim cutoffDate = DateTime.Now.AddSeconds(-15) ' 组合搜索条件:指定时间之后发送 + 非草稿 + 生成时间早于15秒前 Dim searchQuery = SearchQuery.And( SearchQuery.SentSince(pdate.ToString("dd-MMM-yyyy", DateTimeFormatInfo.InvariantInfo)), SearchQuery.Not(SearchQuery.IsDraft), SearchQuery.InternalDateBefore(cutoffDate) ) Dim listIds = ImapCliente.Inbox.Search(searchQuery) ' 拉取时新增附件信息项,方便后续校验 Dim listdoMjs = ImapCliente.Inbox.Fetch(listIds, MessageSummaryItems.Envelope Or MessageSummaryItems.Flags Or MessageSummaryItems.Attachments)
如果对实时性要求高,可把冷却时间调整到10秒,也能覆盖绝大多数场景。
方案2:增加邮件完整性校验
如果不能接受延迟拉取,可在拉取后增加校验逻辑,过滤掉不完整的邮件:
- 对声明了包含附件的邮件,校验附件集合长度是否大于0,若为空则标记为待确认,10秒后重新拉取该邮件的最新状态
- 可额外校验邮件头
X-MS-Exchange-Organization-MessageDirection是否为Incoming,排除未完成投递的临时邮件
方案3:监听事件自动修正(适合常驻后台的服务)
如果你的应用是持续运行的后台服务,可监听IMAP的邮件删除事件:当服务器删除某个UniqueId的邮件时,核对你本地存储的记录,若该Id已被本地存储,就按照发件人、主题、发送时间三个维度匹配新生成的正式邮件,替换本地的旧记录即可。
内容的提问来源于stack exchange,提问作者ZaZZ
相关产品推荐
相关产品推荐

