Features
What mccb does with your mailboxes
One image, two services: web (dashboard and API, port 22362) and worker (job queue). State is SQLite and files in ./data.
Sources and targets
- Sources
PST and OST files, Exchange on premises (EWS), Microsoft 365 (Graph), Google Workspace, IMAP, JMAP, CalDAV and CardDAV, and files: mbox, Maildir, EML, MSG, ICS and VCF.
- Targets
IMAP, CalDAV, CardDAV, JMAP and Exchange (EWS or Graph). Not every source is also a target: Google, PST and files are read-only sources.
- Mail, calendars, contacts and tasks
Tasks go where the target can hold them: Exchange, or a CalDAV calendar that accepts
VTODO. - One credential for many mailboxes
Exchange impersonation, Graph app-only and an IMAP master user reach every mailbox with one account of yours.
- Newest first
Mail is imported from the newest to the oldest, across all folders.
- Server to server
No file needed: IMAP to IMAP, or Exchange, Microsoft 365 and Google to any IMAP server, while people keep working.
- Mail rules
Exchange inbox rules are converted to Sieve on a best-effort basis, and uploaded over ManageSieve or offered as a script.
The interface
- Four places
Migrations, Files, Servers and Settings, in a side bar on a computer and a top bar on a phone. Nine languages.
- Servers first
Pick the provider (Gmail, Microsoft 365, iCloud, Fastmail, Infomaniak or any IMAP server) and the form fills itself, with what the provider asks for. Each server shows whether it is verified.
- One form per migration
From: a file or a live server, configured and tested in place. To: the server and the mailbox.
- A panel that says what is next
Each mailbox shows its source, its destination and what to copy, marked ready or not, and a start button that says what is missing.
- Status in words
Every state is an icon and a word, never a colour alone. What needs you comes first in the list.
Getting files in
- Upload queue
One file at a time by default, with the order of your choice. Reorder, pause, resume or cancel.
- Resumable uploads
Large files upload in chunks, each one checked by SHA-256. Free space is checked first.
- Drop folder
Copy files into a folder of the server with rsync or a mount, and the worker picks them up.
- Server-side fetch
The server downloads the file itself over HTTP(S), SFTP or an S3-compatible service.
- Preview
See accents and attachments before anything is written.
Plan and control
- Dry run
Connects, lists and counts, and writes nothing to any target. It warns about quota and oversized messages.
- Folder mapping and filters
Map folders, exclude folders, and filter by date or maximum size, per server or per mailbox.
- Hours and bandwidth
Allowed hours and a bandwidth limit per server.
- Batches
Named batches with group actions and a queue order.
- Final resync and comparison
A last pass for new IMAP messages at cutover, and a comparison of source and target as CSV and in the report.
Built for batches
- Mailboxes by CSV
Add mailboxes one by one, or by CSV (
email;password[;login]). The export never contains a password. - Command line and API tokens
The
mccbcommand uploads with resume, starts migrations and follows them, with no browser. - Notifications
Tell you when uploads, analyses and migrations finish, through ntfy, a webhook or e-mail.
- Reports
Live progress, log and JSON report per mailbox.
Safe to interrupt
- Resume without duplicates
Pause, stop, crash or restart: a resume checks the server and never duplicates a message.
- Crashes stay contained
Every job and every PST analysis runs in its own subprocess, so a crash of the native PST library cannot take the worker down.
- Checks
After the mail phase, each folder's message count is compared to what was sent, and a sample of messages is read back and compared by hash. Exchange targets are counted only.
Running it
- Tuning
Auto or manual tuning of message builders and IMAP connections, per server.
- Mailbox passwords
Stored encrypted. The application can decrypt them, so protect
./dataand theSECRET_KEY. - Backup
Everything is in
./data, includingsecret.key: without it the stored mailbox passwords cannot be decrypted.
What it does not do
- Run on real Exchange or Google, yet
The Exchange, Microsoft 365 and Google connectors have been tested against simulated servers only. Try one mailbox with few items first.
- Keep the received date on Microsoft 365
Mail written through Graph gets the date of the import. IMAP with OAuth2 as target keeps it.
- Write attendees quietly on Microsoft 365
Graph mails every attendee of an event it creates. By default attendees are written as text in the body of the event. Organisers and responses are not kept on an Exchange target.
- Migrate archive mailboxes through Graph
Microsoft 365 archives are not reachable. Move their content to the primary mailbox first.
- JMAP calendars
Not implemented. Use CalDAV for the calendars of a JMAP provider.
- Copy everything
Attachments of events and contact photos are not copied. Bodies of events, contacts and tasks are plain text.
- Stay in sync
A migration copies in one direction. A final resync, started by hand, adds what arrived since, but a change or a deletion at the source after its copy is not carried over.
- Read every file
A Maildir or a folder of messages must be zipped. A
.msgis converted on a best-effort basis, without RTF-only bodies, embedded messages or OLE objects. - Several administrators
A single administrator: one shared password, no accounts or roles. API tokens do not expire, revoke them by hand.
- Several hosts
SQLite on a local disk: a single host, no high availability, no NFS.
- Encrypted PSTs
Encrypted or password-protected PSTs have no dedicated handling. They give errors or are marked invalid. Do not rely on it.
- Survive every corrupted PST
A corrupted PST can crash libpff. Affected items are skipped and reported, and past
MAX_CHILD_CRASHEScrashes the job fails. - Promise delivery of notifications
Delivery is best effort: three attempts, then the message is dropped. A public ntfy topic can be read by anyone who knows its name.
- HTTPS
Port 22362 speaks plain HTTP. Put mccb behind a reverse proxy and do not expose the port directly.
- Other architectures
The published image is for
linux/amd64only. - Decode everything perfectly
Items with no charset information may decode imperfectly in some languages.
- Make up for the target server
Results depend on the target IMAP, DAV, JMAP or Exchange server.
Get mccb running
Open http://<host>:22362 and sign in with the printed password. It is shown once. Details are in the docs.
$ mkdir mccb && cd mccb
$ curl -fsSLO https://raw.githubusercontent.com/selfhostr/mccb/main/docker-compose.yml
$ docker compose up -d
$ docker compose logs web | grep -A2 "Admin password"