Mailkit技术问询:获取已读邮件时间及.eml存储已读时间可行性
Hey 你好!咱们逐个解决你的两个问题哈:
首先得说明下:IMAP协议本身并没有统一规定“已读时间”这个字段,不同邮件服务器的实现可能不一样,但通常有两种思路可以尝试:
从服务器元数据或自定义头获取
用Mailkit连接到IMAP服务器后,你可以获取邮件的摘要信息,包含标记状态和服务器内部时间。需要注意的是,服务器的InternalDate是邮件到达服务器的时间,不是已读时间,但如果服务器支持的话,可能会在邮件的自定义头里添加已读时间(比如X-Seen-Time这类非标准字段)。另外,有些服务器支持CONDSTORE扩展,可以获取邮件的修改序列,但这个相对复杂。
给你一段参考代码:using (var client = new ImapClient()) { await client.ConnectAsync("imap.example.com", 993, SecureSocketOptions.SslOnConnect); await client.AuthenticateAsync("你的用户名", "你的密码"); var inbox = client.Inbox; await inbox.OpenAsync(FolderAccess.ReadOnly); // 获取所有邮件的标记和内部时间 var mailSummaries = await inbox.FetchAsync(0, -1, MessageSummaryItems.Flags | MessageSummaryItems.InternalDate); foreach (var summary in mailSummaries) { // 检查邮件是否已读 if (summary.Flags.HasFlag(MessageFlags.Seen)) { Console.WriteLine($"邮件唯一ID: {summary.UniqueId}"); // 尝试查找自定义的已读时间头 var seenTimeHeader = summary.Headers.FirstOrDefault(h => h.Field.Equals("X-Seen-Time", StringComparison.OrdinalIgnoreCase)); if (seenTimeHeader != null) { Console.WriteLine("已读时间: " + seenTimeHeader.Value); } else { Console.WriteLine("服务器未提供已读时间,建议自行记录"); } } } await client.DisconnectAsync(true); }自行记录已读时间
如果服务器没提供已读时间的相关数据,最靠谱的方式还是在你用Mailkit把邮件标记为已读(调用AddFlagsAsync设置MessageFlags.Seen)的那一刻,把当前时间存到你的数据库、配置文件里,和邮件的唯一ID关联起来。
直接说结论:标准的.eml格式(也就是MIME邮件格式)本身不包含“已读/打开时间”这个信息。
因为已读时间属于邮件客户端或服务器的元数据,不是邮件本身的内容——你用Mailkit导出的.eml文件,只包含邮件的原始内容:发件人、收件人、主题、正文、附件这些,不会带上已读标记的设置时间。
所以如果要向用户展示这个时间,必须单独保存:比如在导出.eml的同时,把已读时间存在数据库里,或者给.eml文件命名的时候带上时间(比如mail_123_202405201430.eml),或者额外生成一个配套的文本文件记录这个信息。
补充一句:有些本地邮件客户端可能会给本地存储的.eml加自定义头来记已读时间,但这是非标准的,换个客户端或场景就没用了,所以还是单独存最稳妥。
内容的提问来源于stack exchange,提问作者OMID

