Metadata-Version: 2.4
Name: olm2mbox
Version: 0.1.0
Summary: Convert Outlook for Mac .olm archives to standard mbox format, with a disk-space-efficient mbox splitter for oversized files.
Author: Tony Wu
License: MIT
Project-URL: Homepage, https://github.com/tonywut/olm2mbox
Project-URL: Repository, https://github.com/tonywut/olm2mbox
Project-URL: Issues, https://github.com/tonywut/olm2mbox/issues
Keywords: olm,mbox,outlook,email,mail,converter,thunderbird,apple-mail
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Communications :: Email
Classifier: Topic :: Utilities
Classifier: Environment :: Console
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Dynamic: license-file

# olm2mbox

olm2mbox 是一个将 Microsoft Outlook for Mac 的 `.olm` 邮件存档转换为标准 `mbox` 格式的命令行工具，可导入 Thunderbird、Apple Mail 等几乎所有支持 mbox 的邮件客户端或归档工具。

olm2mbox is a command-line tool that converts Microsoft Outlook for Mac `.olm` mail archives into standard `mbox` format, ready to import into Thunderbird, Apple Mail, or any other mbox-compatible mail client or archival tool.

## 缘起 / Backstory

从 Outlook 迁移到 Apple Mail，官方并没有提供直接的一键迁移工具：唯一的路径是先把 Outlook for Mac 的邮箱导出成 `.olm` 存档，再想办法转换成 `mbox` 格式才能导入 Apple Mail。网上能搜到的现成转换工具要么收费不低，要么面对真实的大邮箱（几万封邮件、几十个多级子文件夹、上百 GB 附件）就处理不了——导入导到一半崩溃、中文乱码、子文件夹被漏掉等问题层出不穷。于是干脆让 AI（Claude Code）帮忙把这个工具从头写了出来，自己先拿一个 115GB、8.7万+封邮件的真实邮箱完整跑通、校验无损，现在开源出来，希望能帮到有同样需求的人。

There's no official one-click way to migrate from Outlook to Apple Mail: the only path is exporting your Outlook for Mac mailbox as an `.olm` archive, then somehow converting it to `mbox` so Apple Mail can import it. The existing conversion tools I found online were either expensive or simply couldn't handle a real-world mailbox with tens of thousands of messages, dozens of nested subfolders, and hundreds of gigabytes of attachments — crashing mid-import, mangling CJK text, or silently dropping subfolders. So I had AI (Claude Code) build this tool from scratch instead, ran it end-to-end against my own 115GB, 87,000+ message mailbox, verified it byte-for-byte, and I'm open-sourcing it here in case it helps someone else in the same spot.

## 特性 / Features

- **完整保留嵌套子文件夹结构 / Full nested-subfolder support** — 不只处理收件箱/已发送/草稿等标准文件夹，用户在 Outlook 里自建的多级子文件夹也会被扫描并各自导出为独立的 mbox 文件，镜像原有目录结构。
- **对脏数据健壮 / Resilient to malformed data** — 自动清理 XML 中的非法控制字符和噪声字符，修复包含换行符的邮件头导致的写入失败，处理地址中混入非 ASCII 字符导致标准库 `formataddr` 崩溃等真实遇到过的边界情况。
- **中文 / CJK 友好** — 正文使用 8bit 传输编码而非 quoted-printable，避免中文等多字节字符被编码放大近 3 倍，转换前后文件体积基本 1:1。
- **可续跑 / Resumable** — 超大邮箱转换到一半中断后，可用 `--resume` 跳过已完成的文件夹接着跑。
- **零依赖 / Zero dependencies** — 只用 Python 标准库，无需安装任何第三方包。
- **配套拆分工具 / Companion mbox splitter** — 转换后的单个 mbox 文件如果有几十 GB，导入 Apple Mail 等客户端容易直接闪退。`olm2mbox split` 可以把大 mbox 按体积拆成多份，采用"从文件尾部往前搬移 + 截断"的方式而非整份复制，拆分过程中几乎不额外占用磁盘空间，即使剩余空间小于原文件体积也能安全拆分。

已在一个约 115GB、8.7万+封邮件（32个多级文件夹）的真实邮箱存档上完整跑通并校验字节级无损。
Battle-tested end-to-end and byte-verified against a real ~115GB, 87,000+ message archive spanning 32 nested folders.

## 安装 / Installation

```bash
git clone https://github.com/tonywut/olm2mbox.git
cd olm2mbox
pip install .
```

需要 Python 3.8+，无第三方依赖。
Requires Python 3.8+, no third-party dependencies.

## 使用方法 / Usage

### 转换 .olm 为 mbox / Convert .olm to mbox

```bash
olm2mbox convert path/to/archive.olm path/to/output_dir
```

每个 OLM 文件夹（含嵌套子文件夹）会在 `output_dir` 下生成对应的 `.mbox` 文件，目录结构与原邮箱一致。
Each OLM folder (including nested subfolders) becomes a matching `.mbox` file under `output_dir`, mirroring the original folder tree.

常用参数 / Common options:

```bash
--folder NAME     # 只转换指定的顶层文件夹（原始显示名，如 Inbox）
                   # only convert this top-level folder (its original display name, e.g. Inbox)
--limit N          # 每个文件夹最多转换 N 封（用于测试）
                   # convert at most N messages per folder (for testing)
--resume           # 跳过已经生成过 .mbox 的文件夹，用于续跑中断的转换
                   # skip folders whose .mbox already exists, to resume an interrupted run
--stats-only       # 只扫描统计大小，不实际写出文件
                   # scan and report sizes without writing any output
```

### 拆分超大 mbox 文件 / Split an oversized mbox file

```bash
olm2mbox split path/to/big.mbox --max-bytes 2000000000
```

会在原文件旁生成 `big_part01.mbox`、`big_part02.mbox` ... 等按时间顺序排列的小文件，原文件在确认每一份都安全写入磁盘后被逐步截断，最终整个替换掉，全程几乎不产生额外磁盘占用。
This produces `big_part01.mbox`, `big_part02.mbox`, ... in chronological order alongside the source file. The source is progressively truncated as each part is safely flushed to disk, and is fully replaced by the parts at the end — with almost no extra disk usage along the way.

常用参数 / Common options:

```bash
--max-bytes N   # 每份的最大字节数，默认 2,000,000,000（约2GB）
                # maximum size per part in bytes, default 2,000,000,000 (~2GB)
--dry-run        # 只生成拆分文件，不改动（截断/删除）原文件，用于先行校验
                 # write part files without touching (truncating/deleting) the source
--out-dir DIR    # 拆分文件的输出目录，默认与原文件同目录
                 # directory to write part files into, default alongside the source
```

## 已知限制 / Known limitations

- OLM 数据里正文的"纯文本版本"和"HTML 版本"在实践中几乎总是相同内容；当邮件是 HTML 格式时，纯文本备选版本是对 HTML 做简单去标签处理生成的近似结果，原始 HTML 始终完整保留在 HTML 分支里。
  OLM rarely exposes a genuinely distinct plain-text body; for HTML messages, the plain-text alternative is a best-effort tag-stripped approximation, while the original HTML is always preserved verbatim.
- 邮件时间在 OLM 中不带时区信息，统一按 UTC 处理。
  OLM timestamps carry no timezone info and are treated as UTC.

## 支持 / Support

如果这个工具帮你省了不少事，欢迎请我喝一杯咖啡 ☕️

If this tool saved you some time, feel free to buy me a coffee ☕️

<p>
  <img src="assets/alipay-qr.jpg" alt="支付宝 Alipay" width="220">
  <img src="assets/wechat-qr.jpg" alt="微信支付 WeChat Pay" width="220">
</p>

## 许可证 / License

[MIT](LICENSE)
