由于自己手上的邮箱很多,难免会遇见迁移邮件这种情况,当然好久以前就考虑过了,因此入手了永久个人版的 eM Client。eM Client 固然好用,但我希望不用客户端就直接迁移邮件,因此选择试试 imapsync
Official imapsync migration tool ( release 2.261 ) (lamiral.info)
What is imapsync
imapsync 是一款用于在不同 IMAP 邮件系统之间进行邮件迁移和同步的开源工具。它可以在两个 IMAP 帐户之间同步邮件,并将邮件夹,子文件夹,邮件和其他邮件元数据(如已读/未读标记,标签和标记)复制到目标帐户
imapsync 支持许多 IMAP 服务器和服务,包括 Gmail,Yahoo Mail,Microsoft Exchange,Zimbra 等,并且具有各种功能,例如对话模式,只同步某个时间段的邮件,同时复制多个源帐户等
作者官网上提供付费商业支持(可获得 Windows 版本的 imapsync),免费则不提供支持及 Windows 版本的 imapsync
Installation
下面以 Debian 操作系统为例,imapsync 的要求是 Debian 版本 >= 7.x,及支持 Debian 9 Stretch, 10 Buster, 和 11 Bullseye
Prerequisites
- 伺服器 CPU 任意(作者写的),不要太拉就行,个人推荐 CPU 2核比较合适
- 伺服器 RAM 至少为 500MB 以上,个人推荐 RAM 为 2GB 比较合适
- 伺服器 Disk space 至少 100MB 以上,现在基本都能达到
- Apache2 环境或 NGINX 环境
本文使用 Akamai Cloud (Linode) 的高性能计算实例(Premium 4GB),并由 Akamai Cloud Marketplace 提供的 LAMP Stack 快速搭建 Apache2 环境
Akamai Cloud (Premium 4 GB) - Geekbench
Deploy a LAMP Stack through the Linode Marketplace | Linode Docs
如果你有 Hetzner 账号,也可以用 Hetzner 来新建伺服器进行部署 Apache 环境
Install dependencies
确保有足够的权限运行下面的命令,以 root 权限 或是通过 sudo
运行
apt install -y \
libauthen-ntlm-perl \
libcgi-pm-perl \
libcrypt-openssl-rsa-perl \
libdata-uniqid-perl \
libencode-imaputf7-perl \
libfile-copy-recursive-perl \
libfile-tail-perl \
libio-socket-inet6-perl \
libio-socket-ssl-perl \
libio-tee-perl \
libhtml-parser-perl \
libjson-webtoken-perl \
libmail-imapclient-perl \
libparse-recdescent-perl \
libproc-processtable-perl \
libmodule-scandeps-perl \
libreadonly-perl \
libregexp-common-perl \
libsys-meminfo-perl \
libterm-readkey-perl \
libtest-mockobject-perl \
libtest-pod-perl \
libunicode-string-perl \
liburi-perl \
libwww-perl \
libtest-nowarnings-perl \
libtest-deep-perl \
libtest-warn-perl \
make \
time \
cpanminus
Take imapsync and test
#Github是下载源码或是在作者官网下载imapsync源码,作者官网上的源码一般是最新的,其二选一
wget -N https://raw.githubusercontent.com/imapsync/imapsync/master/imapsync
wget -N https://imapsync.lamiral.info/imapsync
#赋予imapsync执行权限
chmod +x imapsync
#检查是否缺dependency,是否能够完成imapsync的基本操作
./imapsync
#testalive检测imapsync是否完成测试
./imapsync --testslive
作者提供的测试示例
host1: test1.lamiral.info, user1: test1, password1: secret1
host2: test2.lamiral.info, user2: test2, password2: secret2
imapsync \
--host1 test1.lamiral.info --user1 test1 --password1 secret1 \
--host2 test2.lamiral.info --user2 test2 --password2 secret2
Bash Script
上述步骤可以直接写成脚本,如下示例
#!/bin/bash
# Define color codes for printing
GREEN="\033[0;32m"
RED="\033[0;31m"
RESET="\033[0m"
# List of dependencies
dependencies=(
libauthen-ntlm-perl
libcgi-pm-perl
libcrypt-openssl-rsa-perl
libdata-uniqid-perl
libencode-imaputf7-perl
libfile-copy-recursive-perl
libfile-tail-perl
libio-socket-inet6-perl
libio-socket-ssl-perl
libio-tee-perl
libhtml-parser-perl
libjson-webtoken-perl
libmail-imapclient-perl
libparse-recdescent-perl
libproc-processtable-perl
libmodule-scandeps-perl
libreadonly-perl
libregexp-common-perl
libsys-meminfo-perl
libterm-readkey-perl
libtest-mockobject-perl
libtest-pod-perl
libunicode-string-perl
liburi-perl
libwww-perl
libtest-nowarnings-perl
libtest-deep-perl
libtest-warn-perl
make
time
cpanminus
)
# Check and install missing dependencies
missing_dependencies=()
for dependency in "${dependencies[@]}"; do
if ! dpkg -s "$dependency" >/dev/null 2>&1; then
missing_dependencies+=("$dependency")
fi
done
if [ "${#missing_dependencies[@]}" -gt 0 ]; then
echo -e "${RED}Missing dependencies:${RESET} ${missing_dependencies[@]}"
echo -e "${GREEN}Installing missing dependencies...${RESET}"
apt update
apt install -y "${missing_dependencies[@]}"
else
echo -e "${GREEN}All dependencies are already installed.${RESET}"
fi
# Download imapsync script to /usr/local/bin and add execute permission
imapsync_path="/usr/local/bin/imapsync"
# Remove existing imapsync file if present
if [ -f "$imapsync_path" ]; then
echo -e "${GREEN}Removing existing imapsync file...${RESET}"
rm "$imapsync_path"
fi
# Prompt the user to choose a download source
echo "Please choose the source to download imapsync:"
echo "1. Download from GitHub"
echo "2. Download from imapsync official website"
read -p "Enter your choice (1 or 2): " choice
# Depending on user choice, set the download URL
if [ "$choice" == "1" ]; then
download_url="https://raw.githubusercontent.com/imapsync/imapsync/master/imapsync"
elif [ "$choice" == "2" ]; then
download_url="https://imapsync.lamiral.info/imapsync"
else
echo -e "${RED}Invalid choice.${RESET}"
exit 1
fi
# Download the latest imapsync file and add execute permission
wget -N -P /usr/local/bin "$download_url" && chmod +x "$imapsync_path"
echo -e "${GREEN}Dependency installation and imapsync download are complete.${RESET}"
Start to use
Command Line Arguments
中括号 [] 里是参数后所接的数据类型
--host1 [str]:源或“来自”IMAP服务器的主机名或IP地址。
--port1 [int]:连接到 host1 上的端口号。可选,默认端口是知名端口 IMAP/143 或 IMAPS/993。
--user1 [str]:登录 host1 的用户名。
--password1 [str]:user1 的密码。
--host2 [str]:“目标”IMAP服务器的主机名或IP地址。
--port2 [int]:连接到 host2 上的端口号。可选。
--user2 [str]:登录 host2 的用户名。
--password2 [str]:user2 的密码。
--showpasswords :在输出中显示密码而不是“MASKED”。只需阅读即可重新启动完整运行日志中使用的命令行,或调试密码。这根本不是一个安全的做法!
--passfile1 [str] : user1 的密码文件。 它必须包含密码在第一行。 此选项避免显示命令行上的密码就像 --password1 一样。
--passfile2 [str] :user2 的密码文件。
Common Imap Server
icloud: imap.mail.me.com
Microsoft 365 / Outlook: outlook.office365.com
Gmail: imap.gmail.com
Yahoo: imap.mail.yahoo.com
Yandex: imap.yandex.com
Common Command Line
#未指定子文件夹的情况下将[user1]根目录所有mail同步至[user2]中根目录
imapsync \
--host1 [host1] --user1 [user1] --password1 [password1] \
--host2 [host2] --user2 [user2] --password2 [password2]
#用 --subfolder 参数指定子文件夹,将[user1]中[subfolder1]目录的mail同步至[user2]中[subfolder2]目录
imapsync \
--host1 [host1] --user1 [user1] --password1 [password1] --subfolder1 [subfolder1] \
--host2 [host2] --user2 [user2] --password2 [password2] --subfolder2 [subfolder2]
imapsync \
--host1 [host1] --user1 [user1] --passfile1 [password1 path] --subfolder1 [subfolder1] \
--host2 [host2] --user2 [user2] --passflie2 [passflie2 path] --subfolder2 [subfolder2]
Using Online "X" Service
考虑到用命令行操作不方便,作者弄了个 WebUI 操作界面来简单迁移邮件,当然功能比较有限,这里可以自己搭建一个和作者同款 WebUI
Download Assets
如下脚本只是将 WebUI 所需要的静态资源下载并放在 /var/www/html/imapsync/X/
路径下中,请根据自己网站目录自行调整
#!/bin/bash
# Create the directory
mkdir -p /var/www/html/imapsync/X/
# Change to the newly created directory
cd /var/www/html/imapsync/X/
# Download the necessary files
wget -N \
https://imapsync.lamiral.info/X/imapsync_form_extra.html \
https://imapsync.lamiral.info/X/imapsync_form.css \
https://imapsync.lamiral.info/X/imapsync_form.js \
https://imapsync.lamiral.info/X/logo_imapsync_Xn.png
# Create a symbolic link
ln -s imapsync_form_extra.html index.html
# Print completion message
echo "Installation complete. Please check the following link:"
echo "http://imapsync.mydomain.com/imapsync/X/imapsync_form_extra.html"
echo "Or the safer link:"
echo "https://imapsync.mydomain.com/imapsync/X/imapsync_form_extra.html"
Apache Configuration
Apache 需要正确配置确保,已经加载了 mod_cgi.so
这个模块。你可以在Apache的配置文件(如 httpd.conf
或 apache2.conf
)中添加以下行来加载这个模块
LoadModule cgi_module /usr/lib/apache2/modules/mod_cgi.so
如果没有配置文件,可以在 /etc/apache2/sites-available/
目录下创建一个新的配置文件,如 172-232-184-71.ip.linodeusercontent.com.conf
编辑此配置文件,确保加入以下配置
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
# Next line "no-gzip 1" is to avoid output buffering,
# clients can then see the log during the sync
SetEnv no-gzip 1
Options +ExecCGI -MultiViews
# Choose either one or the other, depending on your Apache version
# Lines beginning with # are ignored
# For Apache 2.2
#Order allow, deny
#Allow from all
# Apache 2.4
Require all granted
</Directory>
示例站点配置如下所示
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
# Next line "no-gzip 1" is to avoid output buffering,
# clients can then see the log during the sync
SetEnv no-gzip 1
Options +ExecCGI -MultiViews
# Choose either one or the other, depending on your Apache version
# Lines beginning with # are ignored
# For Apache 2.2
#Order allow, deny
#Allow from all
# Apache 2.4
Require all granted
</Directory>
<VirtualHost *:80>
ServerName 172-232-184-71.ip.linodeusercontent.com
ServerAlias www.172-232-184-71.ip.linodeusercontent.com
DocumentRoot /var/www/172-232-184-71.ip.linodeusercontent.com/public_html
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
<files xmlrpc.php>
order allow,deny
deny from all
</files>
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.172-232-184-71.ip.linodeusercontent.com [OR]
RewriteCond %{SERVER_NAME} =172-232-184-71.ip.linodeusercontent.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
如果 apache 非版本 2.4,请根据版本取消相应注释,并注释 apache 2.4
Copy imapsync to cgi-bin
根据上面 Apache 的配置,需要把 /usr/local/bin/imapsync
复制到 /usr/lib/cgi-bin
下
service apache2 restart
重启 Apache 服务
Check imapsync Status
browser 端上 /cgi-bin/imapsync
下检查是否正常运行
server 端上通过以下命令行检查是否正常运行
wget -nv -S -O- http://localhost/cgi-bin/imapsync?testslive=1
imapsync 启动测试时日志反馈中出现 200 OK to sync IMAP boxes
状态即正常
The limitation of imapsync
如果使用 NGINX 则还要麻烦一些,前几个月时已经问过作者,不过他也只会 apache,我使用 NGINX 搭建 WebUI 没有成功
Reference
Official imapsync migration tool ( release 2.261 ) (lamiral.info)
imapsync.lamiral.info/INSTALL.d/INSTALL.OnlineUI.txt
imapsync.lamiral.info/INSTALL.d/INSTALL.Debian.txt