眼前这个迁移项目让你有些不安。你需要把电子邮件从服务器 A 迁移到服务器 B,既不能丢失任何一封邮件,也不能破坏文件夹结构,更不想为了搬运本就属于你的数据,向第三方供应商支付每位用户 $15 的“迁移许可”费用。
你要找的工具就是 imapsync。本指南将准确说明如何使用它,同时避免损坏用户的邮箱。
imapsync 是什么,又不是什么
imapsync 是一个命令行工具,用于在两台 IMAP 服务器之间同步邮箱。它充当中间代理,同时连接两台服务器,从源服务器读取邮件,再将邮件追加到目标服务器。它可以跟踪状态、处理中断,并保留文件夹结构、标记和邮件内容。
它不是备份工具,也不是 SMTP 中继。它不会处理你的 Google 日历、Outlook 联系人或 Exchange 传输规则。它只使用 IMAP。如果源服务器受到防火墙隔离或已经离线,imapsync 就无法访问。没有例外。
imapsync 之所以成为邮箱间迁移的行业标准,关键在于它的状态保留层。成功迁移不只是移动文本,还要保留以下三项内容:
- 内容:RFC 822 邮件正文、附件、MIME 编码,以及信封内的所有内容。
- 元数据:各种标记,包括
\Seen(已读)、\Answered(已回复)、\Flagged(已加星标)。如果这些标记没有迁移,用户会在第一天误以为自己收到了 4,000 封新的未读邮件。 - 结构:文件夹层级。新服务器上的
INBOX/Clients/ProjectA必须与原来完全一致,而不能被压平为一个名称中带点号、字面名称为INBOX.Clients.ProjectA的文件夹。
imapsync 能处理这三项内容,前提是配置正确。这正是困难所在,也是本指南要解决的问题。
硬性限制:imapsync 本身并不了解 Gmail 的速率限制或 Microsoft 的 API 限流策略。全速运行可能导致你的 IP 被封禁。它也不会主动推送数据:如果要把数据送到某处,就必须从源端拉取。默认情况下,它也不会删除目标端的内容。这是一项安全设计,但如果没有留意,也可能造成麻烦,详情见阶段 6。
如需进一步了解该协议,请参阅我们的域名邮箱设置指南。
阶段 1:全面摸底,不要跳过
新手上来就复制,专业人员则会先审计环境。如果你不知道要迁移什么,就很可能失败,而且偏偏会在周日凌晨 2 点、已经来不及补救的时候失败。
1. 找出超大邮箱
某位用户可能有一个 45GB 的邮箱,也许是 CEO,也许是从 2011 年起就持有 sales@ 别名的人。如果把这个邮箱和 500MB 的用户放在同一个批次中迁移,整个批次会停滞,而你只能盯着冻结的终端,完全不知道完成了多少。
先运行预扫描:
imapsync \
--host1 imap.source.com --user1 user@source.com --passfile1 /secret/pass1 \
--host2 imap.dest.com --user2 user@dest.com --passfile2 /secret/pass2 \
--dry --justfoldersizes
它会在不触碰任何邮件的情况下,列出每个文件夹的大小。超过 10GB 的邮箱都需要单独处理,包括设置更长的超时时间、安排专用运行窗口,并全程密切关注。
2. 暗数据问题
每家公司都有僵尸账户,例如邮件仍被转发到某处的离职员工账户,以及名为“服务账户”、实际上却是打印机或旧版 CRM 集成所用共享邮箱的账户。如果清点时漏掉这些账户,切换 DNS 后,其中的数据就会滞留在旧系统中。
请将源系统用户列表与实际在职用户进行核对。如果 bob@company.com 已于三年前离职,现在就应决定是迁移他的邮箱,还是将其归档为 EML 导出文件。如果不在切换前决定,最糟糕的情况下就只能在压力之下临时处理。我们的客户电子邮件管理指南提供了一份完整的迁移前清单模板。
3. 邮件数量才是真相
绝不要只相信以 GB 计的容量。源服务器 A 可能显示邮箱为 10GB,目标服务器 B 却将完全相同的数据计为 11GB。这并不是错误,而是因为不同服务器的存储计算方式不同。Exchange 会计入 Recoverable Items 文件夹,也就是“Dumpster”,而 Gmail 会对不同标签下的邮件进行去重。
真正重要的指标是邮件数量。如果源端有 14,200 封邮件,目标端也有 14,200 封邮件,迁移就已完成。字节数相差不到 10% 属于正常现象。超过 10% 时,请先查明原因再确认完成。
阶段 2:安全迁移流程
迁移中最严重的错误,是采用“Big Bang”方式:周五晚上一次搬完全部数据,并指望周一早上之前结束。如果邮件总量为 50GB,限速为 500KB/s,时间根本不够。到了周一服务仍会中断,你还得向 CEO 解释为什么收件箱空空如也。
专业做法是分阶段迁移。在用户仍使用旧系统时完成大部分工作,切换时只执行一次很小的最终增量同步。
步骤 1:试运行
移动任何数据之前,先确认能够连接。将 --dry 与 --justfolders 结合使用。这样可以模拟运行并显示文件夹结构,而不会复制任何内容。
imapsync \
--host1 imap.gmail.com --user1 user@source.com --passfile1 /secret/pass1 \
--host2 imap.trekmail.net --user2 user@dest.com --passfile2 /secret/pass2 \
--dry --justfolders
重点检查两件事:身份验证是否成功,以及文件夹名称是什么样。如果源端出现 [Gmail]/Sent Mail,就需要将其映射到目标端的 Sent Items。不要等到正式切换时才发现这个问题。
步骤 2:批量同步(预迁移)
在切换前 1-2 周运行此步骤,此时用户仍在旧系统中工作。目标是提前完成 90-95% 的数据迁移,使其不再占用关键切换窗口。
imapsync \
--host1 imap.source.com --user1 user@source.com --passfile1 /secret/pass1 \
--host2 imap.dest.com --user2 user@dest.com --passfile2 /secret/pass2 \
--usecache --skipsize --maxsize 25000000
--usecache 必不可少。它会在本地保存迁移状态。后续每次运行都会与该缓存比较,只处理变化,而不会从头检查每一封邮件。不使用它,每次运行都会进行完整扫描。
--maxsize 25000000 会在首次迁移时跳过大于 25MB 的邮件。大型附件最容易导致超时和连接中断。之后可以延长超时时间,单独运行一次来迁移这些邮件。
步骤 3:增量同步
在切换前几天,再运行一次。imapsync 会读取缓存,发现目标端已经有 10,000 封邮件,跳过它们,只复制批量同步后新到达的 50-100 封邮件。这次运行应该只需几分钟,而不是几小时。
步骤 4:正式切换
现在到了关键时刻。请按以下顺序操作:
- 降低 DNS TTL:切换前 48 小时,将 MX 记录的 TTL 设置为 300 秒。如果等到最后一刻才修改,某些解析器可能会继续缓存旧 MX,最长可达 24 小时。这样一来,即使已经切换,邮件仍会投递到旧服务器。
- 切换 MX 记录:将其指向新的邮件服务商。
- 等待 60 分钟,让主要解析器上的传播过程稳定下来。
- 运行最终增量同步:最后一次 imapsync 会捕获传播期间仍投递到旧服务器的邮件。
如需详细了解 DNS 切换窗口及传播期间的监控重点,请参阅我们的域名邮箱设置指南。
阶段 3:标记、文件夹与“已发送”陷阱
不同 IMAP 服务器使用不同的“方言”。如果不在它们之间进行转换,用户登录后会看到结构混乱的邮箱,并且有理由责怪你。
分隔符问题
这是最常见的技术故障,却很少有人在亲身遇到之前谈起它。
不同 IMAP 服务器使用不同字符来分隔文件夹层级:
- Dovecot 通常使用点号:
INBOX.Clients.ProjectA - Exchange/Outlook 使用斜杠:
INBOX/Clients/ProjectA - 有些服务器完全不使用分隔符,而是依靠 IMAP
NAMESPACE命令
如果直接迁移,imapsync 可能会在目标端创建一个字面名称为 INBOX.Clients.ProjectA 的文件夹。它是一个名称中带点号的单层文件夹,而不是三级嵌套结构。每位用户的文件夹结构看起来都会一团糟。
解决方法是使用 --regextrans2,通过正则表达式动态改写文件夹路径。批量迁移 100 位用户之前,务必先在一个测试账户上使用 --dry 检查文件夹创建结果。
“已发送”文件夹的混乱
各服务器对“已发送”文件夹的命名都不一样。这绝非小麻烦,如果忽略,会严重影响用户体验。
| 电子邮件平台 | “已发送”文件夹名称 |
|---|---|
| Gmail / Google Workspace | [Gmail]/Sent Mail |
| Outlook / Exchange | Sent Items |
| cPanel / Courier | Sent |
| 德国服务器 | Gesendete Elemente |
| 西班牙服务器 | Enviados |
如果不做映射,用户最终会看到两个已发送文件夹:正在使用的 Sent Items,以及包含全部历史邮件、名为 Sent Mail 的新“幽灵”文件夹。用户一定会发现,而且不会满意。
请明确映射:
--regextrans2 's/^\[Gmail\]\/Sent Mail/Sent Items/'
这条命令告诉 imapsync:“如果源文件夹以 [Gmail]/Sent Mail 开头,就在目标端将其重命名为 Sent Items。”先使用 --dry 运行完整的文件夹映射,确认每项规则都能正确生效,再正式执行。
Gmail All Mail 陷阱
Gmail 有一个名为 [Gmail]/All Mail 的文件夹。其中包含每一封电子邮件的副本,不受标签影响。这是 Gmail 的内部全量视图,只是以 IMAP 文件夹的形式显示出来。
如果同时迁移 All Mail 和 Inbox 以及 Sent Mail,目标端的每封邮件都会重复两次或三次。一个 10GB 的邮箱会变成 30GB,每封邮件也会出现多次。这将是一场灾难。
务必将它排除:
--exclude "All Mail"
除非确有迁移需要,否则也请排除 [Gmail]/Spam 和 [Gmail]/Trash。没有人想把旧垃圾邮件一起迁走。
阶段 4:性能调优与限速
不能不加限制地向 Google 或 Microsoft 发送大量数据。它们的基础设施会把高流量 IMAP 连接当作拒绝服务攻击,因为从平台的角度来看,两者表现完全相同。
触发限流后的处罚
一旦超过速率限制,Gmail 通常约为每秒 1 封邮件或每小时 500MB,服务器就会开始返回 HTTP 429、NO [OVERQUOTA],或者简单的 BAD 错误。如果继续施压,账户会被锁定 24 小时。你不会想为此联系支持人员。
调优参数
--maxmessagespersecond 1 # Hard speed limit: 1 email per second
--maxbytespersecond 500000 # Bandwidth cap: 500KB/s
--timeout 120 # Network timeout in seconds (default is often too short for big attachments)
--reconnectretry1 3 # Retry on source connection drops
--reconnectretry2 3 # Retry on destination connection drops
每秒 1 封邮件听起来慢得难以忍受,事实也确实如此。但稳定运行才能完成迁移。运行过于激进,在第 3 小时被封禁,就永远无法完成。
MSP 注意:如果为多个客户并行迁移,不要同时连接同一台源服务器。请错开开始时间。每个并行任务都需要自己的限速额度。
如果要迁移到 TrekMail,我们的 IMAP 接收服务能够妥善处理高并发连接。与 Google 或 Microsoft 源端相比,你可以在目标端使用更高速度。
阶段 5:身份验证,现代身份验证的门槛
把 password123 写进纯文本文件的时代已经结束。Google 和 Microsoft 都已弃用 IMAP 基本身份验证。如果尝试使用普通登录凭据,系统会返回身份验证错误,你可能要花一小时反复琢磨哪里出了问题。
应用专用密码(中小企业方案)
对于大多数单域迁移,应用专用密码是最快捷的方案。这类密码由 16 个字符组成,可以绕过 2FA,并兼容旧式 IMAP 客户端:
- 登录源账户(Gmail、Workspace 等)
- 如果尚未启用双重身份验证(2-Factor Authentication),请将其启用,这是生成应用专用密码的前提
- 前往“安全性”设置 → “应用专用密码”
- 为“其他设备”上的“邮件”生成密码
- 在 imapsync 的
--passfile中将该字符串用作密码
请将它保存在权限为 chmod 600 的文件中,不要直接写在命令行里。凭据一旦进入 Bash 历史记录,迟早会造成问题。
OAuth2(MSP 与企业方案)
如果你是需要迁移 500 位用户的 MSP,就不可能手动生成 500 个应用专用密码,而是需要 OAuth2。这种方式更复杂,但在大规模迁移中是唯一现实的选择:
- 在源租户中注册应用(Microsoft 使用 Azure AD,Google 使用 Google Cloud Console)
- 授予它对整个租户中所有邮箱的完整访问权限,此操作需要全局管理员批准
- 为每位用户生成 Refresh Token,或使用服务账户模拟用户身份
- 通过
--oauthaccesstoken1将令牌传给 imapsync
如果错误配置 Azure AD 或 GCP 中的应用权限,结果可能是每个邮箱都拒绝访问,或者更糟:无意间授予应用超出预期的权限。点击“授予管理员同意”之前,请仔细阅读权限范围。
如需了解大规模迁移的实用方法,请参阅我们的客户电子邮件管理指南。
阶段 6:常见故障模式与恢复方法
再周密的计划也会遇到问题。下面介绍如何判断故障原因并加以修复,而不必从头开始。
1. UIDVALIDITY 问题(噩梦场景)
每个 IMAP 文件夹都有一个名为 UIDVALIDITY 的唯一标识符。imapsync 依靠它跟踪已经复制的邮件。如果源服务器上的文件夹被删除后重新创建,或者服务器索引损坏并重建,该 ID 就会发生变化。
症状:imapsync 发现新的 UIDVALIDITY 后,会将其视为一个全新的文件夹并重新下载所有内容。该文件夹中的每封邮件都会产生副本。在大规模迁移中,这意味着数百个邮箱里会出现数千封重复邮件。
解决方法:删除临时目录中的本地缓存文件,再使用 --useheader 重新运行:
--useheader
这会强制 imapsync 比较每封邮件的 Message-ID 标头,而不是依赖文件夹 UID。该标头不可变且唯一。此方法较慢,但可以避免重复。只要怀疑源服务器索引被改动过,就应使用它。
2. 损坏邮件与零字节邮件
旧服务器会积累“幽灵”邮件,例如只有标头而没有正文的邮件,或大小恰好为 0 字节的文件。这通常源于失败的导入、中途崩溃的投递过程,或者一台多年未得到妥善维护的老旧服务器。
症状:imapsync 尝试获取一封邮件,服务器挂起 120 秒后断开连接。之后,它会在同一封邮件上无限重复这一过程。
解决方法:
--minbytes 10
该参数让 imapsync 跳过所有小于 10 字节的邮件。真正的电子邮件不可能小于 10 字节。它本质上是一个“跳过空文件”的筛选器,可以安全用于每次迁移。
3. 已删除邮件“复活”的问题
你在周一运行了批量同步。周二,用户从源端删除了 50 封邮件。周三,你运行增量同步。
默认情况下,imapsync 只添加邮件,不会根据源端的删除操作来删除目标端邮件。对于大多数使用场景,这是有意且正确的设计。但这也意味着,那 50 封已经删除的邮件会在新邮箱里重新出现。用户会将其报告为“幽灵邮件”或“删掉后又回来的邮件”。
解决方法是 --delete2,但使用时必须极其谨慎:
--delete2
这个参数会告诉 imapsync:如果源端没有某封邮件,就从目标端将其删除。
只能在切换 MX 之前的预迁移阶段使用它。如果在切换后运行,已经到达目标端的新邮件会被删除,因为 MX 已经指向目标端,而这些邮件并不存在于旧的源端。你将丢失邮件。切换后绝不要使用 --delete2。
4. 大型附件导致连接中断
如果 IMAP 连接的超时时间较短,一个 40MB 的 PDF 附件有时就会导致连接停滞。服务器发送邮件时,网络稍有波动,连接便可能在 95% 时断开。imapsync 会记录错误并继续处理,目标端最终留下不完整的邮件。
解决方法:迁移大型附件时,将 --timeout 增加到 300 秒。还可以在批量同步时使用 --maxsize 25000000 跳过大型附件,随后以更宽松的限速和更长的超时时间运行专门的附件迁移。
验证:如何证明迁移成功
脚本已经结束,终端也显示完成。但你怎么知道 CEO 的邮件没有消失在某个空路由中?
1. 查看摘要块
imapsync 会在每次运行结束时输出摘要。以下三个数字最重要:
- Transferred:最终增量运行时应为 0。如果不是零,说明仍有邮件尚未成功迁移。
- Skipped:应等于或大于源端的邮件总数。这些邮件已经位于目标端。
- Errors:应为 0。任何非零错误计数都必须先调查,之后才能宣布完成。
2. 抽查
使用一个全新的 IMAP 客户端登录新邮箱,不要使用带有本地缓存的客户端,否则检查将失去意义。请检查:
- Sent Items:多年来的已发送邮件是否都在,并且层级正确?
- 一个深层嵌套的子文件夹:层级是否正确?
- 最新邮件:是否与源端显示的邮件相同?
- 一封已标记或已加星标的邮件:
\Flagged属性是否保留下来?
3. 日志取证搜索
用户报告缺少一封邮件。在断言“肯定是丢了”之前,请先查日志:
grep -i "bob@sender.com" /var/log/imapsync/user@source.com.log
日志会记录每一封邮件的处理结果:Transferred、Skipped(目标端已存在)或带有具体错误代码的 Error。如果结果是 Error,你就能准确知道是哪封邮件、哪个文件夹以及哪个错误代码导致了问题。这才是恢复工作的起点,而不是靠猜测。
4. 邮件数量审计
最后进行合理性检查时,请直接查询两台服务器:
# On source (example for Dovecot)
doveadm mailbox status -u user@source.com messages '*'
# Or use imapsync's own count
imapsync ... --dry --justfoldersizes 2>&1 | grep "Messages"
比较源端和目标端的邮件数量。考虑到排除的垃圾邮件文件夹和 Gmail All Mail 去重,两者应相差不超过 1-2%。如果差异更大,请先检查错误日志再确认完成。
另一种选择:不再使用终端
我们编写这份指南,是因为我们重视透明度。对于希望获得完全控制,并且不介意处理 Perl 依赖项、OAuth2 应用注册和日志取证工作的运维人员,imapsync 是合适的工具。
但对很多运维人员来说,无论是迁移第一个域名的创始人,还是迁移 200 个客户席位的代理机构,配置所有这些内容的时间成本都会超过节省的软件费用。
| 方式 | 最适合 | 需要交换的成本 |
|---|---|---|
| imapsync(自行操作) | 系统管理员、要求完全控制的场景、特殊的源服务器 | 以时间和专业能力换取零工具成本 |
| TrekMail 内置迁移 | 创始人、代理机构和重视时间的运维人员 | 以精细标记控制换取速度和简便性 |
| 第三方迁移供应商 | 有合规要求和相应预算的企业 | 以资金换取 SLA 保证,通常为每位用户 $15-$25 |
TrekMail 的内置迁移工具在服务器端运行,不必在 Outlook 中花三小时拖动文件夹,也不必深陷 Perl 依赖问题。只需指定源端(Gmail、cPanel 或任何标准 IMAP 服务器),输入凭据,服务器就会处理迁移。你可以在控制面板中查看进度。
它的定价模式也与常见方案不同。不按用户收费。固定费率方案起价为 $3.50/月,可覆盖最多 100 位用户并分布在 50 个域名中,所有用户共享存储空间。即使某位高管有 40GB 附件,也不会迫使所有人升级方案,因为存储空间在整个账户中共享。
请查看 TrekMail 定价,比较各方案包含的内容。有关该工具的具体分步流程,请参阅文档中的开始迁移指南。
无论你是自行编写 imapsync 脚本,还是使用我们的平台,目标都相同:顺利迁移电子邮件,不丢失数据,也不必为此按席位付费。
如果你准备停止按用户付费,并希望由我们处理迁移,请免费试用 TrekMail,试用期为 14 天,无需银行卡。