用 MailKit
解析 mbox 文件最靠谱
直接上结论:别自己手写解析器,
MailKit是目前 C# 生态里唯一稳定支持完整 mbox 格式的开源库。它能正确处理多封邮件拼接、
From行边界、时间戳乱码、编码混用等坑点。
常见错误现象是用
StreamReader按行读取后简单切分
From行,结果遇到带附件的邮件或含
From字样的正文就断错位置——mbox 规范要求只有行首独立的
From(注意末尾空格)才是分隔符,且后面必须紧跟时间戳。
MailKit内部用状态机识别真实分隔符,跳过邮件体内的干扰文本 支持自动检测
Content-Transfer-Encoding和
charset,避免中文乱码 不依赖系统本地化设置,Windows/macOS/Linux 行为一致
mbox 文件路径和编码必须显式指定
很多失败案例源于默认编码误判。
StreamReader用 UTF-8 BOM 判断编码,但绝大多数 mbox 文件无 BOM,且实际是 ISO-8859-1 或 GBK 编码的原始 Unix 邮件存档。
使用
MailKit时,
MboxReader构造函数必须传入
Encoding参数:
using (var reader = new MboxReader("inbox.mbox", Encoding.GetEncoding("iso-8859-1")))
{
while (reader.TryReadMessage(out var message))
{
Console.WriteLine(message.Subject);
}
}
Unix 系统导出的老 mbox 多为 iso-8859-1;中文环境可能是
gb2312或
gbk若不确定编码,先用
file -i inbox.mbox(Linux/macOS)或
chardet工具探测 别用
Encoding.Default——它在 Windows 上是 GBK,在 Linux 容器里可能是 UTF-8,行为不可控
提取邮件头和正文要区分 TextBody
和 HtmlBody
MimeMessage的
TextBody不是“纯文本内容”,而是自动降级后的首选文本体。它会按
text/plain→
text/html→ 其他 text/* 类型顺序选取,且已解码(base64/QP)并转码为 .NET 字符串。
常见误区是直接读
message.Body,结果拿到的是原始 MIME 结构对象,不是可读字符串。 需要纯文本内容:优先用
message.TextBody,它已处理换行、编码、字符集转换 需要 HTML 渲染:用
message.HtmlBody,注意可能含相对路径引用的内嵌资源 要访问原始未解码数据(比如调试编码问题):遍历
message.BodyParts手动找
TextPart并调用
GetBodyAsText()
大文件下内存暴涨?得用流式处理 + 显式释放
MboxReader默认把整封邮件载入内存再解析 MIME 结构,单封超 10MB 的邮件(比如带大附件的旧存档)会导致 GC 压力骤增,甚至
OutOfMemoryException。
关键控制点有两个:
构造MboxReader时传入
leaveOpen: true,避免内部重复打开文件流 每次循环后手动调用
message.Dispose(),立即释放 MIME 解析树占用的内存 若只需提取发件人/主题/时间,可用
message.Headers直接读,跳过完整 MIME 解析
真正难搞的是混合了二进制附件和 base64 编码的老旧 mbox——那些没有
Content-Transfer-Encoding声明却实际用了 base64 的邮件,
MailKit会尝试自动探测,但仍有小概率失败。这时候得关掉自动探测,手动按块解析原始字节流。
