Skip to main content

Copy and transfer IMAP mailboxes

Project description

pymap-copy

donate PyPI version release license

In our company we often have to copy mailboxes from one to another server. For this we used IMAPCopy as 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!

Features

  • Copies folders and subfolders
  • Copies mails even with flags (seen, answered, ...)
  • Connecting via SSL/TLS (by default), STARTTLS or without encryption
  • Supports 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 bar
  • Uses buffer for max performance
  • Optimized for large mailboxes
  • Workaround for Microsoft Exchange Server's IMAP bug
  • Statistics
  • Simple usage

Requirements

  • Python >= 3.6

Installation

pip (recommended)

  1. Install pymap-copy: python3 -m pip install pymap-copy
  2. Start the program:pymap-copy.py --help

Upgrade: python3 -m pip install --upgrade pymap-copy

whl / release

  1. Download the latest release
  2. Install the wheel-file: python3 -m pip install pymap_copy-X.X-py3-none-any.whl
  3. Start the program:pymap-copy.py --help

Upgrade: Simply install a newer release

git

  1. Clone this repo
  2. Install the requirements by running python3 -m pip install -r requirements.txt
  3. Start the program:./pymap-copy.py --help

Upgrade: git pull

Simple usage

By 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=abcdef

If you just want to look what would happen append -d/--dry-run.

Incorrect login

If 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 root

Redirections

You want to merge INBOX.Send Items with the INBOX.Send folder? You can do this with -r/--redirect. The syntax of this argument is simple source:destination. For this example you can use -r "INBOX.Send Items:INBOX.Send" to put all mails from the source folder INBOX.Send Items the to destination folder INBOX.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 root

In some cases it's necessary to copy all mails from source into an import folder on destination. In this case you can use --destination-root to 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 to INBOX.

If you want to merge all folders into INBOX you 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-merge INBOX would 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 optimization

You could change the buffer size with -b/--buffer-size to 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 timeouts

To 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-interval followed by the desired number of seconds.

Use of source-folder argument

As a further optimization you can target specific folders you want to copy to the destination (versus the default of everything). Use -f / --source-folder to 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 only INBOX:
--source-folder INBOX 
Copy INBOX.Archives and all subfolders:
--source-folder INBOX.Archives.* --source-folder INBOX.Archives

You can also use this argument but please notice, that all folders started with INBOX.Archives (like INBOX.Archives123 and INBOX.ArchivesNew) will be copied too (if they exists).

--source-folder INBOX.Archives*

Microsoft Exchange Server IMAP bug

If your destination is an Microsoft Exchange Server (EX) you'll properly get an bad command exception 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 got broken pipe? This is also an Exchange feature. 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 following these instructions. You can also exclude these mails from copy by using the --max-mail-size argument.

Encryption & Ports

By default pymap-copy will use port 993 with ssl/tls. You can change this behavior by using --source-encryption/--destination-encryption and --source-port/--destination-port. If no port is specified, it will choose the default port based on given encryption.

Possible encryption are tls, ssl (the same as tls), none and starttls.

Default ports

Encryption Port
tls 993
ssl 993
starttls 143
none 143

Credits

Created and maintained by Lukas Schulte-Tickmann / Schluggi.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymap-copy-1.0.2.tar.gz (16.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymap_copy-1.0.2-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

Details for the file pymap-copy-1.0.2.tar.gz.

File metadata

  • Download URL: pymap-copy-1.0.2.tar.gz
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.6.1 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.55.1 CPython/3.8.10

File hashes

Hashes for pymap-copy-1.0.2.tar.gz
Algorithm Hash digest
SHA256 871a955efb8279ca0c9020c3664b473ca796c47fe0716c7d6b335e2c2ee50907
MD5 b9978d4373cba9661e887a6a3a945726
BLAKE2b-256 10a93f8002fb882ea70816d08c74a155155ae18c8927625f2c0cc1e49cb8e8a0

See more details on using hashes here.

File details

Details for the file pymap_copy-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: pymap_copy-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 14.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.6.1 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.55.1 CPython/3.8.10

File hashes

Hashes for pymap_copy-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a704ca6e56f4d5feb2fe7c171500bb9b003d762cfb43aabc753f98e8f2392465
MD5 97d3d41a3f5af7abee34e8e4b41c2bdb
BLAKE2b-256 81e5a759ad38149b54909b7559ffa55ee3915b41944a0e70e4ab096acaebab1d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page