imapsync: one-way IMAP migration without duplicates
Imapsync is an IMAP transfers tool. The purpose of imapsync is to migrate IMAP accounts or to backup IMAP accounts. IMAP is one of the three current standard protocols to access mailboxes, the two others are POP3 and HTTP with webmails, webmails are often tied to an IMAP server. Upstream website is
At a glance
- What is it?
- imapsync copies a mailbox hierarchy from one IMAP server to another, incrementally and without duplicates. It is built for migrations and backups, not for keeping two live mailboxes in step.
- Who is it for?
- Adopt imapsync when you need a one-way copy of an IMAP account: a migration off an old provider, or a backup that can be re-run without producing duplicates. Do not adopt it to keep two mailboxes that a user edits on both sides in step; the README names offlineimap and mbsync for that job.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 51 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- imapsync/imapsync4,209 ★ · +47
| Repository | 2026-09-23 | 2026-11-14 |
|---|---|---|
| imapsync/imapsync | 4.2k | 4.2k |
47 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The problem imapsync solves: moving a mailbox between two IMAP servers
Moving mail between providers is tedious because IMAP has no standard transfer command. You can drag folders in a desktop client, but that breaks on large mailboxes, loses flags, and gives you no way to resume. imapsync is a command line tool that logs into two IMAP servers at once and copies the folder tree from the first to the second. The README calls it "incremental and recursive": recursive because it takes the whole hierarchy including subfolders, incremental because a second run only transfers what is missing. It is aimed at administrators and power users doing account migrations or periodic backups, not at end users who want a graphical client.
The scope is deliberately one direction. Folders, messages and flags (\Seen, \Answered, \Flagged and the rest) are copied, and flags are re-synchronised on every run unless --noresyncflags is given. Nothing on the destination is removed unless you ask for it. That default is the single most important thing to understand about the tool: a run that reports success has copied messages, not made the two sides identical.
How imapsync decides a message is already there
The deduplication mechanism is header based. By default imapsync identifies a message by its Message-Id and Received lines; if the same headers appear on both sides, the message is considered present and is not transferred again. The README states plainly that this choice can be changed with --useheader, and that most duplicate problems are solved with --useheader "Message-Id". That sentence is worth reading twice, because it tells you the default is not always right. Received headers are added by every mail server a message passes through and can differ between the source and the destination copy, so a mailbox that has travelled through several relays is a plausible source of duplicates or, worse, of repeated transfers of the same message.
Message sizes are deliberately not part of the identification. The README explains that an early version used size as a criterion and that this was a mistake, because the same message can be reported with different sizes by different servers. This is also why the total size of the two accounts can differ at the end of a run, sometimes by a lot, without the sync being wrong. Gmail is given as a concrete case: it does not count duplicate messages across folders twice, while imapsync does. If you plan to use total size as your success check, you are using the wrong signal. The right signal is the trio of lines the README quotes: how many identified messages on host1 are on host2, whether any unidentified message remains on host1, and the detected error count.
Installing imapsync and running a first sync
The repository ships a Makefile whose usage target is the entry point. Running make testp shows the Perl modules needed from your distribution or from CPAN, and make install is documented as the install step, run as root. The README's usage section gives the six credentials that form the core of every invocation: a hostname, a username and a password for each side.
A minimal first run against two test accounts looks like this, taken from the README:
imapsync \
--host1 test1.lamiral.info --user1 test1 --password1 secret1 \
--host2 test2.lamiral.info --user2 test2 --password2 secret2The tool prints the total sizes of both accounts at the start and at the end. What you are looking for is the closing lines: a return value of 0 with the EX_OK message, the pidfile removal, and the log file path, which by default is written under LOG_imapsync/ and can be changed with --logfile or turned off with --nolog. If those lines never appear, the README says the process is either still running (possibly hanging) or was killed without a trace.
Before touching a real account, do a dry run. The README documents --dry as making imapsync do nothing for real, and the option list in the repository is long enough that guessing is not worth it. The examples/ directory holds runnable starting points, including imapsync_example.sh for Unix, imapsync_example_darwin.sh for macOS, imapsync_example.bat for Windows and imapsync_example_oauth2.bat for OAuth2, plus sync_loop_unix.sh and sync_parallel_unix.sh for repeated and parallel runs. Reading one of those is faster than assembling flags from the option list.
Deletions, strict sync and the --delete2 family
The default behaviour is additive: messages on the destination that are not on the source stay where they are. If you want the destination to be a strict copy of the source, you need --delete2, which removes messages in the host2 folder that are not in the corresponding host1 folder. Removing host2 folders that do not exist on host1 is a separate step, --delete2folders, with --delete2foldersonly and --delete2foldersbutnot available to carve out exceptions. INBOX is never destroyed; the README notes it is mandatory in IMAP and imapsync does not even try.
The opposite direction is --delete1, which removes messages from the source after a successful transfer. This is the migration pattern where you want each message to exist only on one side at the end. It is not a standalone flag: --delete1 implies --expunge1, so messages marked \Deleted on host1 are expunged for real. The README is explicit that in IMAP a deleted message is only flagged, and that expunge is the irreversible step. If you also want empty folders cleaned up after their contents move, --delete1emptyfolders does that.
This is the part of imapsync where a mistake is not recoverable from the destination. Run --delete2 and --delete1 against test accounts first, and keep the log files, since a log is written by default unless you pass --nolog.
Where imapsync is the wrong tool
imapsync is not a two-way synchroniser. The README states this directly: it is not adequate for maintaining two active IMAP accounts in synchronization when the user works independently on both sides, and it points to offlineimap and mbsync for that. The reason follows from the design. Identification is by headers, and the default is additive, so a message that exists only on the destination is simply left alone. There is no conflict resolution, because there are no conflicts to resolve in a one-way copy.
A second limitation is the header heuristic itself. Two genuinely different messages that share a Message-Id will be treated as one, and a message whose headers were rewritten in transit may be transferred again on a later run. The README offers --useheader as the remedy, which means the operator has to know something about how their particular servers handle headers. That is a real operational burden, not a detail.
Finally, the per-run interruption behaviour is unusual and worth knowing before you script it. On a terminal, one Ctrl-c makes imapsync reconnect to both servers; two Ctrl-c within two seconds aborts the program. A wrapper that sends a single interrupt expecting the process to stop will instead see it reconnect. The README also notes the tool works well with bad connections and interruptions by design, so restarting after an abort is a normal pattern rather than a recovery procedure.
imapsync vs offlineimap and mbsync
The README names both alternatives itself, which makes the comparison unusually concrete. offlineimap (by John Goerzen) and mbsync (by Michael R. Elkins) are for two-way synchronisation between a local mail store and a server, or between two accounts that a user edits on both sides. imapsync is built for the opposite shape of problem: a one-way, resumable copy between two remote IMAP servers, where the source is authoritative and the destination is a replica or a backup.
That difference shows up in the mechanics. A two-way tool has to track state on both sides and decide what wins when a message changes in two places. imapsync avoids that entirely by identifying messages through headers and never deleting on the destination unless told to. The trade-off is that imapsync gives you no continuous, always-in-step relationship: it is something you run, on a schedule or on demand, and each run is a batch. The examples directory reflects this, with sync_loop_unix.sh, sync_loop_darwin.sh and sync_loop_windows.bat for repeated runs and sync_parallel_unix.sh for running several migrations at once.
If your goal is a mailbox that mirrors a server for offline reading, imapsync is the wrong shape. If your goal is to get 40 GB of mail off a provider that is shutting down, it is the right one.
Licence, maintenance and what a migration actually costs
The repository's LICENSE file is the authoritative source here, and the licence metadata reported for the project is NOASSERTION, meaning no standard identifier was detected. That is not the same as "no licence", and it is not the same as "public domain". If you are deploying imapsync inside a company, read LICENSE and the NOLIMIT file in the repository root before you decide how it fits your policy. Nothing here is legal advice, and the licence text is the thing that governs, not a summary of it.
On maintenance: the default branch is master and the last push was on 2026-09-24, which is recent enough that the project is not dormant. The repository has no published GitHub releases, so versioning appears to run through the VERSION file and the $Revision tag in the documentation, which currently reads 2.314. Practically, that means an upgrade is a pull of the repository plus a re-run of make install, not a package manager transaction, unless your distribution packages it separately.
The upgrade cost that matters more is operational. The option surface is large, the identification heuristic is configurable, and the deletion flags are irreversible in one direction. A migration script built on imapsync is a script built on a specific set of flags; re-reading the option list after an upgrade is cheaper than discovering that a default changed on a mailbox you can no longer restore. The FAQ file and FAQ.d/ directory in the repository are the project's own place to check for behaviour that the README does not cover.
Editorial conclusion
Adopt imapsync when you need a one-way copy of an IMAP account: a migration off an old provider, or a backup that can be re-run without producing duplicates. Do not adopt it to keep two mailboxes that a user edits on both sides in step; the README names offlineimap and mbsync for that job. Before running anything against a real account, verify three things: that the destination is a test account, that your identification header choice (the default is Message-Id and Received) matches what your servers actually rewrite, and that you have decided whether you want --delete2 at all, because without it the destination keeps whatever it already had.
Frequently asked questions
What is the imapsync command used for?
It transfers mailboxes from one IMAP server to another, recursively through the folder hierarchy, and it is used for migrations and for backing up an IMAP account. It also copies message flags, so unread stays unread and flagged stays flagged.
Is imapsync free?
The repository contains a LICENSE file and a NOLIMIT file, and the licence metadata reported for the project is NOASSERTION, so no standard licence identifier was detected. Read LICENSE in the repository root to determine the terms that apply to your use.
how to use imapsync
You supply six credential values, a hostname, username and password for each side, and imapsync copies the folders from host1 to host2. The README's example calls it with --host1, --user1, --password1, --host2, --user2 and --password2, and the examples/ directory has ready-made scripts for Unix, macOS and Windows.
how to install imapsync on ubuntu
The Makefile's usage target documents make testp to show the needed Perl modules from your distribution or CPAN, and make install, run as root, to install.
is imapsync safe
The README documents the flags that change data irreversibly: --delete1 implies --expunge1, which permanently removes messages marked \Deleted on the source. Running with --dry first, and against test accounts, is the way to see what a given set of options would do.
imapsync vs offlineimap
The README states that imapsync is not adequate for maintaining two active IMAP accounts in synchronization when the user works independently on both sides, and names offlineimap for that case. imapsync is a one-way, resumable copy between two IMAP servers.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/imapsync-imapsync)Star history chart for your README
[](https://hysenlabs.com/projects/imapsync-imapsync)Was this useful?