Duplicate Emails Piling Up in Your IMAP Client? Here Is Why
Three copies of every email since the migration. Duplicates in IMAP have three causes — imapsync, POP3 overlap, sent-folder double-writes. Here's how to tell which one you've got.
Three copies of every email since the migration. Duplicates in IMAP have three causes — imapsync, POP3 overlap, sent-folder double-writes. Here's how to tell which one you've got.
You finished the IMAP migration on a Friday. Monday morning, someone from accounts asks whether you meant to send them that invoice three times.
You open Apple Mail. Three copies. Same subject, same body, timestamps within a second of each other. You scroll down. It's not one invoice — it's the whole inbox, tripled. Eleven thousand messages became thirty-three thousand overnight, your storage graph looks like a hockey stick, and search results now show every result three times over.
Here's the thing about duplicate emails in IMAP: it almost never has a mysterious cause. There are three mechanisms that produce it, they leave different fingerprints, and once you know which one you're looking at the fix takes about ten minutes. The panic is the expensive part.
By the end of this you'll be able to look at a duplicated mailbox, read the headers, and say which of the three causes you've got:
Then you'll dedupe safely, without eating the fourteen identical newsletters that are supposed to be there.
imapsync if you're cleaning up a migration — brew install imapsync on macOS, or grab it from imapsync.lamiral.infoimapdedup for the cleanup pass — it's a single Python script, pip install imapdedupPorts tripping you up? Our breakdown of 25, 465, 587 and 993 covers which one belongs where.
Open two copies of the same duplicated message side by side and look at the full headers. Gmail: three dots → Show original. Thunderbird: Ctrl/Cmd+U. Apple Mail: View → Message → All Headers.
You're checking exactly two things.
Compare the Message-ID. If both copies carry the identical Message-ID, the copies came from the same original message being written into the mailbox more than once — that's a migration or a double-write. If the Message-IDs differ, the message was genuinely sent or received twice, or one copy passed through something that regenerated the header.
Compare the Received chain and the internal date. Copies created by a migration share the entire Received chain (it's a byte-for-byte copy of the original) but land with different internal dates — the APPEND time, not the send time. Copies created by a sent-folder double-write have no Received chain at all on one of them, because it was never received; the client APPENDed it directly.
Quick lookup table:
| Fingerprint | Cause | Folder it shows up in |
|---|---|---|
| Same Message-ID, same Received chain, different APPEND time | imapsync run twice | Every folder, or one folder that failed mid-sync |
Same Message-ID, one copy missing Received entirely | Client + server both saving Sent | Sent only |
| Different Message-ID, near-identical body | POP3 re-download reimported | INBOX, usually a big contiguous block |
| Same message visible in two folders | Gmail labels exposed over IMAP | All Mail + the labelled folder |
That last row catches a lot of people who think they have a duplication bug and don't. Gmail exposes labels as IMAP folders, and a message with two labels appears in two folders — it's one message stored once. Uncheck "Show in IMAP" for All Mail in Gmail's settings and the phantom disappears.
This is the big one. Tripled mail after a cutover usually means imapsync ran more than once and couldn't match what it had already copied.
imapsync doesn't naively copy everything — it builds a list of messages on both sides, matches them by header, and only transfers what's missing. The matching is the fragile part. By default it matches on Message-ID plus Received, and with --usecache it also keeps a local record of what it already transferred. Kill the process halfway through a mailbox with fifteen years of mail in it, restart it on a different machine, and that record is gone — everything now rests on the header match.
Unpopular opinion: imapsync is the best tool that exists for this and has one of the worst interfaces of any terminal tool. Both things are true.
Worse: some servers rewrite or strip Message-ID on APPEND. Now the destination copy doesn't match the source copy on the header imapsync is keying on, so every single message looks missing, and it copies the whole mailbox again. That's your tripling.
Servers that rewrite Message-ID should be embarrassed. Globally unique is the entire job of that header, and rewriting it breaks every dedupe tool downstream.
The re-run that doesn't duplicate:
imapsync \
--host1 imap.oldhost.com --user1 you@yourdomain.com --password1 'xxx' \
--host2 mail.justemails.app --user2 you@yourdomain.com --password2 'yyy' \
--usecache \
--useheader "Message-ID" --useheader "Received" \
--skipcrossduplicates \
--dry
Note the --dry at the end. Run it. Read the transfer count. If it says it wants to copy 11,000 messages into a mailbox that already has 11,000 messages, your header matching is broken — do NOT drop the --dry yet. Swap the two --useheader lines for --useheader "Date" --useheader "Subject" and try again until the count drops to something believable.
Cleaning up duplicates that already landed:
imapsync --host1 ... --host2 ... --delete2duplicates --dry
--delete2duplicates removes duplicate messages on the destination side, keeping one of each. Again: dry run first, read the output, then re-run without --dry.
One caveat: --delete2duplicates only touches the folders the sync is configured to walk. If your duplicates are in a folder that got excluded by a --folder or --exclude flag, they'll sit there untouched and you'll swear the command did nothing.
If you're mid-migration and want the flag list that actually preserves folder structure and labels, our Google Workspace migration walkthrough has the full invocation. JustEmails' own migration tooling handles Google Workspace, Zoho, and generic IMAP sources and keeps labels and folders intact, which spares you writing the flags by hand.
POP3 duplicates look different. They arrive in a big contiguous block — everything from a specific date forward, all at once — and they usually have different Message-IDs from the originals if they've been round-tripped through a local store.
The mechanism: a POP3 client set to leave a copy on server tracks what it's already downloaded using a UIDL list stored locally. That list is fragile. Reinstall the client, create a new profile, change the server hostname, or restore from a backup, and the UIDL list resets. Next check, the client sees a mailbox full of messages it has no record of downloading, and it downloads all of them. Again.
That list lives on the client. Not the server. So the one piece of state deciding whether you get duplicates is sitting in a file on a laptop somebody is about to reimage — and POP3 in 2026 has exactly one honest use left, which is talking to hardware nobody's allowed to replace.
If that client's local store then gets imported into IMAP — which is exactly what happens when someone asks, mid-migration, for their old Outlook PST to be pulled in too — you now have two copies on the server.
The fix, in order of preference:
scanner@yourdomain.com costs nothing.Archive-Imported folder, dedupe, then merge.This one's confined to Sent, and it's the most common ongoing duplication — the other two are one-time events, this one keeps happening forever until you fix it.
When you hit send, two things can save a copy:
Both are reasonable behaviours. Together they produce exactly two copies of everything you've ever sent, with slightly different internal dates and one of them missing a Received header. Every message. Forever.
On JustEmails, outgoing mail goes through mail.justemails.app on port 587 with STARTTLS, using the same host and mailbox password your IMAP client already uses on 993. One thing worth knowing while you're in the sending settings: sends are capped per account per day, and on a newly verified domain the ceiling is no more than 50 a day in the first week, 200 in the second, and up to 500 from day 15, with mailbox sends and API sends counted against the same number. That warm-up runs from domain verification, not signup, so if outgoing mail stops on a recently verified domain, check that number before you go hunting for another duplication bug.
Turn off the client side:
Then send yourself a test message and check Sent. If nothing lands there, your server isn't saving a copy, so turn the client setting back on — it was the only copy you had.
Then delete the existing duplicates in Sent with imapdedup, which matches on Message-ID and is smart enough to keep one:
imapdedup.py -s mail.justemails.app -u you@yourdomain.com -w 'xxx' -x -n "Sent"
The -n is a dry run. Read the list. Then drop -n to actually delete.
Honestly, client-side sent-copy defaults are one of the worst pieces of legacy behaviour still shipping in 2026. Plenty of servers save the copy themselves, and clients still offer to do it again. Nobody's fixed it because nobody owns both sides.
Host2 folder [Sent Messages] does not exist
Folder naming mismatch between providers — Apple calls it "Sent Messages", most servers call it "Sent". Add --automap to let imapsync map special folders itself, or map explicitly with --f1f2 "Sent Messages"="Sent".
--delete2duplicates reports 0 duplicates, but you can clearly see them
The messages don't share a Message-ID, so imapsync doesn't consider them duplicates. Swap your --useheader options for --useheader "Date" --useheader "Subject" --useheader "From" to widen the match. Verify with --dry before deleting — widening the match is how people accidentally delete legitimate same-subject mail.
Duplicates reappear after you delete them
Something is still writing them. Either a POP3 client is re-downloading (Step 3), or a scheduled imapsync is still running on a cron somewhere. Check crontab -l on whatever machine you ran the migration from.
Over quota while deduping
Deletes in IMAP are two-phase: flag as deleted, then EXPUNGE. If the folder is at quota, some servers reject the flag write. Empty Trash first, then dedupe. Our mailbox storage guide covers recovery when you can't get in at all.
Thunderbird still shows duplicates after the server is clean
Local index corruption, not a server problem. Right-click the folder → Properties → Repair Folder. It rebuilds the .msf index from the server state.
Once the mailbox is clean, the thing worth doing is preventing round two. Document which mailboxes use IMAP and which (if any) still use POP3, and make that list something a new laptop setup has to check against. Repeat duplication usually starts with somebody setting up a fresh device from memory.
And if you're mid-migration right now: run the --dry pass. Every time. It costs thirty seconds and it's the difference between this article being useful and being necessary.
Usually an interrupted or repeated imapsync run. If the sync dies partway through a folder and you restart it without the cache directory (or with a different --useheader setting), imapsync can't match the messages it already copied and appends them again. Servers that rewrite or strip the Message-ID header on APPEND make this worse, because header matching is how the dedupe logic works. Re-running with --usecache and --delete2duplicates usually cleans it up.
It can, when both protocols point at the same mailbox. A POP3 client set to leave a copy on server downloads everything, and if its UIDL list gets reset — reinstalled client, new profile, changed hostname — it re-downloads the whole mailbox on the next check. If that client also copies mail into an IMAP folder, or you later import its local store back into IMAP, you get two of everything. Pick one protocol per mailbox, or set POP3 to delete after download.
Your mail client and your mail server are both saving a copy. Many servers write an SMTP-submitted message into Sent automatically, and most clients also do an IMAP APPEND of their own copy. Two writes, two copies, slightly different timestamps. Turn off one of them, then send a test message to confirm a copy still lands in Sent — in Apple Mail, Thunderbird, and Outlook the setting is a Sent folder / store-copy checkbox in the account's outgoing settings.
Run a dry pass first. imapdedup with the -n flag lists what it would delete without touching anything, and imapsync's --dry does the same for a sync. Read that output, confirm the counts look sane, then take an IMAP backup of the folder (drag it to a local folder in Thunderbird, or run imapsync into a local Maildir) before running the real pass. Never dedupe by subject and date alone — same-subject newsletters get eaten.
Unlimited custom domain email hosting for $49/year flat — unlimited domains, unlimited mailboxes, 10 GB storage, full IMAP/SMTP. Built for agencies, freelancers, and anyone managing email across more than one domain.