mailbox模块仅支持mbox、Maildir、MH、Babyl和MMDF等本地邮箱格式,无法读取.eml单文件或Outlook的.pst文件;.eml需用email.parser解析,.pst则需外部工具或商业库处理。

mailbox 模块能直接读取 .mbox 文件,但对 .eml 或 Outlook .pst 完全无效
Python 的 mailbox 模块只支持几种本地邮箱格式:主要是 mbox、Maildir、mh 和 Babyl。它不解析单个 .eml 文件(那是 email.parser 的事),更无法打开 Windows Outlook 的 .pst 或 Apple Mail 的 .mboxbundle —— 这些需要外部工具或商业库。
常见错误现象:FileNotFoundError 或静默失败,其实是路径错、格式不匹配,或文件被锁(比如 Thunderbird 正在运行)。
- 确认输入是纯文本
mbox:用head -n 5 your.mbox看开头是否含From(注意末尾空格)行 -
Maildir必须是目录结构,含cur/、new/、tmp/子目录,不能传入单个文件 - Windows 路径要用正斜杠或原始字符串:
r"C:\data\inbox"或"C:/data/inbox"
用 mailbox.mbox() 读取时必须显式调用 lock(),否则并发写会损坏文件
默认情况下 mailbox.mbox 不加锁,多进程/多线程同时写入会导致 From 行错位、邮件体截断 —— 这种损坏无法恢复。
正确做法是在实例化后立即调用 lock(),操作完再 unlock();若程序异常退出,需确保解锁(建议用 try/finally)。
立即学习“Python免费学习笔记(深入)”;
import mailbox
mbox = mailbox.mbox("inbox.mbox")
try:
mbox.lock()
mbox.add(message) # message 是 email.message.Message 实例
finally:
mbox.unlock()- 不要依赖
with语句自动管理锁 ——mailbox.mbox不实现上下文协议 - 若只读,可跳过锁,但一旦调用
add()或remove()就必须锁 - Linux/macOS 下推荐用
maillock(基于 flock),Windows 下用dotlock(创建 .lock 文件)
从 mbox 提取邮件内容时,别直接用 msg.get_payload(),先检查是否 multipart
get_payload() 在非 multipart 邮件中返回字符串,在 multipart 中返回 list —— 不判断就调用会触发 AttributeError 或返回空。
标准解法是用 msg.is_multipart() 分支处理,或统一用 email.policy.default 解析(Python 3.6+)。
from email import policy from email.parser import BytesParser <h1>推荐:用 policy 解析,自动处理编码和 multipart</h1><p>parser = BytesParser(policy=policy.default) msg = parser.parsebytes(raw_bytes)</p><p>if msg.is_multipart(): for part in msg.iter_parts(): if part.get_content_maintype() == "text": body = part.get_content() else: body = msg.get_content()
-
msg.get_payload(decode=True)只解 base64/quoted-printable,不处理字符集;get_content()才真正解码并转为 str - 附件名可能含非 ASCII 字符,用
part.get_filename()(不是get_param("filename")) - 日期字段用
email.utils.parsedate_to_datetime(msg["Date"]),别用datetime.strptime
转换 mbox 到 JSON 或 CSV 时,字段映射必须手动处理,没有通用 schema
mailbox 不提供导出方法,所有字段(如 Subject、From、Date)都得从 Message 对象里逐个取,且值可能是 None 或未解析的原始头字段。
容易踩的坑:直接 json.dump(msg) 会报 TypeError(Message 不可序列化),str(msg) 又包含整个原始邮件体(含 MIME 结构)。
- 只取关键字段:
msg["Subject"]、msg["From"]、msg["To"]、msg["Date"],并用email.utils.unquote清理引号 - 正文用前一节的
get_content()提取,避免 HTML 标签混入 CSV - 时间戳务必转为 ISO 格式:
parsedate_to_datetime(...).isoformat(),否则 Excel 无法识别
复杂点在于每封邮件的结构差异很大:有的没 Subject,有的 Date 格式非法,有的 From 是多个地址。这些边界情况必须单独判空或 fallback,没法靠一个函数兜底。


















