Mailbox Mirror runs imapsync on a cron schedule so one IMAP mailbox is mirrored into another. Use it when simple forwarding is not available and you want a small self-hosted sync.
If your provider supports server-side forwarding, use that instead. It is simpler and usually more reliable than running your own sync container.
This project started as a practical response to a very specific failure mode in the modern email stack: Gmail is shutting down Gmailify and POP-based fetching for external accounts, while Yahoo keeps simple forwarding behind tighter restrictions on the free tier. That combination removes the two obvious low-effort ways to keep third-party mail flowing into Gmail.
I wanted a replacement that was boring in the good sense: self-hosted, inspectable, cheap to run, and based on proven IMAP behavior instead of another opaque mail bridge. The result is Mailbox Mirror: a small wrapper around imapsync that turns a one-off migration tool into a dependable recurring sync job.
The core idea is straightforward but intentional. If forwarding is available, forwarding is still the smarter choice and should be preferred. But when Gmailify disappears, POP fetching goes away, and Yahoo will not forward for free, a scheduled IMAP-to-IMAP mirror is a clean fallback that keeps control on your side without inventing a custom mail system from scratch.
- Copy
.env.exampleto.env. - Fill in the required source and destination credentials.
- Start the container:
docker compose up -d- Check the first run:
docker compose logs -f mailbox-mirrorRequired values:
HOST1,USER1,PASSWORD1for the source mailboxHOST2,USER2,PASSWORD2for the destination mailbox
Common optional values:
PORT1,PORT2,SSL1,SSL2if you need non-default IMAP settingsCRON_SCHEDULEto change the sync intervalRUN_ON_STARTUP=falseto skip the initial sync on container startDRY_RUN=truefor a safe first test without writing mail
Advanced-only values:
LOCK_FILEto share one lock across multiple containersFOLDER_FILTERto sync only selected folders such asINBOXMAXAGE_DAYSto limit how much old mail is scannedHEALTHCHECK_MAX_AGE_MINUTESto fail health checks when sync is too oldIMAPSYNC_EXTRA_ARGSfor extraimapsyncflags
The container validates required variables and the cron schedule on startup, so bad config fails fast.
The repo includes docker-compose.multi-mailbox.yml for three staggered mailbox mirrors that share one lock file. It is meant for low-RAM setups where only one imapsync process should run at a time.
- Open
.env. - Uncomment and fill the
MAILBOX_A_*,MAILBOX_B_*, andMAILBOX_C_*values in the advanced section. - Start the advanced stack:
docker compose -f docker-compose.multi-mailbox.yml up -dThe advanced example keeps these defaults:
RUN_ON_STARTUP=falsefor all three containers- staggered schedules with 5-minute offsets
FOLDER_FILTER=INBOX- one shared
LOCK_FILEvolume
If all three source mailboxes mirror into the same destination account, reuse the same MAILBOX_*_HOST2, MAILBOX_*_USER2, and MAILBOX_*_PASSWORD2 values for each service.
