Package: pymap-copy
pymap-copyIn our company we often have to copy mailboxes from one to another server. For this we usedIMAPCopyas so far. Due to compatibility issues, first of all the missing
SSL/TLS and STARTTLS support i wrote my own python-based version. I hope you like it!FeaturesCopies folders and subfoldersCopies mails even with flags (seen, answered, ...)Connecting via SSL/TLS (by default), STARTTLS or without encryptionSupports incremental copy (copies only new mails/folders)User specific redirections (with wildcard support)Auto subscribe new folders (by default)Auto find the special IMAP folders Drafts, Trash, etc. (by default)Quota checking (by default)Over all progress barUses buffer for max performanceOptimized for large mailboxesWorkaround for Microsoft Exchange Server's IMAP bugStatisticsSimple usageRequirementsPython >= 3.6Installationpip (recommended)Install pymap-copy:python3 -m pip install pymap-copyStart the program:pymap-copy.py --helpUpgrade:python3 -m pip install --upgrade pymap-copywhl / releaseDownload the latestreleaseInstall the wheel-file:python3 -m pip install pymap_copy-X.X-py3-none-any.whlStart the program:pymap-copy.py --helpUpgrade: Simply install a newer releasegitClone this repoInstall the requirements by runningpython3 -m pip install -r requirements.txtStart the program:./pymap-copy.py --helpUpgrade:git pullSimple usageBy running the following command the whole structure (folders & mails) from user1 will be copy to the mailbox of user2.pymap-copy.py \
--source-user=user1 \
--source-server=server1.example.org \
--source-pass=2345678 \
--destination-user=user2 \
--destination-server=server2.example.info \
--destination-pass=abcdefIf you just want to look what would happen append-d/--dry-run.Incorrect loginIf your password has special characters (like!,$,#, ...) in it, you have to quote them with a backslash (\)
in front. This is a common mistake (#8).Redirections and destination rootRedirectionsYou want to mergeINBOX.Send Itemswith theINBOX.Sendfolder? You can do this with-r/--redirect.
The syntax of this argument is simplesource:destination. For this example you can use-r "INBOX.Send Items:INBOX.Send"to put all mails from the source folderINBOX.Send Itemsthe to destination folderINBOX.Send. Please make sure you use quotation marks if one of the folders includes a special character or space like
as in this example. In addition, the folder names must be case-sensitive with the correct seperator. Do a dry run
(-d/--dry-run) to check that everything will redirect correctly.Destination rootIn some cases it's necessary to copy all mails from source into an import folder on destination. In this case you can
use--destination-rootto define the import folder:--destination-root INBOX.Import.Special case: The source has another root than the destination.Current folder: INBOX (144 mails, 49.0 MB) -> INBOX (non existing)
Current folder: INBOX.Folder1 (4 mails, 7.2 MB) -> INBOX.Folder1 (non existing)
Current folder: Trash.Folder1 (22 mails, 1.1 MB) -> Trash.Folder1 (non existing)This often does not work. Most mail providers do not allow folders parallel toINBOX.If you want to merge all folders intoINBOXyou can use--destination-root INBOX --destination-root-merge. The
result should be as shown:Current folder: INBOX (144 mails, 49.0 MB) -> INBOX (non existing)
Current folder: INBOX.Folder1 (4 mails, 7.2 MB) -> INBOX.Folder1 (non existing)
Current folder: Trash.Folder1 (22 mails, 1.1 MB) -> INBOX.Trash.Folder1 (non existing)Without--destination-root-mergeINBOXwould be prepend to all folders:Current folder: INBOX (144 mails, 49.0 MB) -> INBOX.INBOX (non existing)
Current folder: INBOX.Folder1 (4 mails, 7.2 MB) -> INBOX.INBOX.Folder1 (non existing)
Current folder: Trash.Folder1 (22 mails, 1.1 MB) -> INBOX.Trash.Folder1 (non existing)As always: Do a dry run (-d/--dry-run) to ensure that everything is going well.Performance optimizationYou could change the buffer size with-b/--buffer-sizeto increase the download speed from the source.
If you know the source mailbox has a lot of small mails use a higher size. In the case of lager mails use a lower size
to counter timeouts. For bad internet connections you also should use a lower sized buffer.Preventing timeoutsTo prevent timeouts, both server (the source and destination) will automatically be set into the IMAP idle mode. Most
servers can hold this idle mode for 30 minutes. The idle mode restarts every 28 minutes (1680 seconds) so there should
be no timeout. If a timeout occurs nevertheless you can change the restart interval by using--idle-intervalfollowed
by the desired number of seconds.Use of source-folder argumentAs a further optimization you can target specific folders you want to copy to the destination (versus the default of
everything). Use-f/--source-folderto only copy that folder(s). The flag can be specified multiple times to
indicate multiple folders to copy. The argument does support wildcard by using*and the end.Copy onlyINBOX:--source-folder INBOXCopyINBOX.Archivesand all subfolders:--source-folder INBOX.Archives.* --source-folder INBOX.ArchivesYou can also use this argument but please notice, that all folders started withINBOX.Archives(likeINBOX.Archives123andINBOX.ArchivesNew) will be copied too (if they exists).--source-folder INBOX.Archives*Microsoft Exchange Server IMAP bugIf your destination is an Microsoft Exchange Server (EX) you'll properly get anbad commandexception while coping
some mails. This happens because the EX analyse (and in some cases modify) new mails. There is a bug in this lookup
process (since EX version 5 -.-). To prevent an exception you can use the argument--max-line-length 4096. This will
skip all mails with lines more than 4096 characters.You gotbroken pipe? This is also an Exchangefeature. There is a limit of failures (by default three) in
a single connection. Once you reach the limit, the server will disconnect you and pymap-copy will show an error for
each further mail. Mostly these error occurs because the size of the mail is larger than the max allowed size. The
best way is to increase the limit (you need admin access to the server) by followingthese instructions.
You can also exclude these mails from copy by using the--max-mail-sizeargument.Encryption & PortsBy default pymap-copy will use port 993 with ssl/tls.
You can change this behavior by using--source-encryption/--destination-encryptionand--source-port/--destination-port. If no port is specified, it will choose the default port based on given
encryption.Possible encryption aretls,ssl(the same astls),noneandstarttls.Default portsEncryptionPorttls993ssl993starttls143none143CreditsCreated and maintained by Lukas Schulte-Tickmann / Schluggi.