In short
You can usually take your mail with you when you leave a provider. What you get is a pile of files: a mailbox file or two, a folder of contacts, a calendar per calendar. Every one of them is in an open format, and every one of them opens somewhere else. What doesn't come with them is the account. Which folder was Sent and which was Archive. Which address book new contacts went into. Which filter was running. What you signed your mail with, and which addresses you sent from.
Those are the parts people notice when they're gone. So we wrote down a layout for a whole mail account as plain files, with one small JSON manifest for what the open formats can't hold, and published it as a specification. Our migration tool, inbuxa-migrate, has written it since October. As of 27.1.0-rc.10 it reads the whole thing back too, manifest and all. This paper explains why the layout looks the way it does, what reading it back takes, and where it still falls short.
The formats exist. The account doesn't.
Mail has had open formats for decades. Maildir keeps one message per file, with its flags in the file name, and Dovecot and Courier both serve it. vCard (RFC 6350) holds contacts, iCalendar (RFC 5545) holds calendars, and Sieve (RFC 5228) holds filters. Files are files. None of this needs inventing.
The trouble is everything in between. Take a folder named "v1.0 notes". Maildir uses the dot to separate levels, so on disk the name has to change, and the real one is gone unless something writes it down. Take an address book marked as the default: vCard has no idea it lives in an address book at all, let alone the default one. Take two Sieve scripts: the files say nothing about which one was running. Take the address you reply from, its reply-to, its signature: no file format holds those.
Data-portability rules ask for exactly this kind of thing. Article 20 of the GDPR, for one, gives people the right to their data "in a structured, commonly used and machine-readable format" and to hand it to someone else. A folder of open files meets the letter of that. Whether the account survives the trip is another matter.
There's a live alternative. JMAP (RFC 8620 and RFC 8621) moves all of this between two running servers, and it's what we use when both ends are up. But a move doesn't always have both ends up. The old provider may be closing. The new server may not exist yet. Or you may just want a copy that outlasts both, and that you can open in ten years without a tool.
The layout
The layout is a directory with five parts and a manifest:
export/
mail/ Maildir++: the inbox here, other folders as .Parent.Child
contacts/*.vcf one file per address book
calendars/*.ics one file per calendar
sieve/*.sieve one file per script
files/ the file tree
manifest.json what the formats above don't hold
A few decisions shaped it.
Every part stands on its own. You don't need the manifest to read the mail, the contacts or the calendars. Point Dovecot at mail/ and it serves it. Import a .vcf into any contacts app. The manifest adds to the files; nothing in them depends on it. A reader that only knows the open formats gets most of an account, and one that reads the manifest gets all of it.
The manifest is written last. A tree without one is unfinished, and a reader must not treat it as an export. That makes "did the export finish?" a question with a yes-or-no answer.
Missing and empty are different things. If a writer didn't export the calendars, the manifest leaves them out. If it exported them and there were none, the manifest says so with an empty list. A reader has to tell the two apart: one says nothing about the account, the other says it had no calendars.
Names on disk are made safe; real names live in the manifest. Every name comes from the source, so none is used as a path as it stands. Separators, characters some file systems refuse and names Windows reserves are replaced, and clashes are numbered. The manifest keeps every real name: folders, address books, calendars and scripts, and any file or directory whose name had to change.
Links are listed, never made. The source chose where a link points, and a link in an unpacked tree could point anywhere on the machine that unpacked it. So the manifest lists links, and the tree has none.
No secrets go in. The layout has no place for passwords, tokens or keys, and a writer must not add one. The new server sets its own.
The format is named by its address. The manifest's format is the specification's URL, so the name belongs to no one tool and can't clash with anything else. It carries a version number, and readers ignore members they don't know, so later writers can add to it without breaking older readers. A change a reader has to know about comes with a new version, and a reader should refuse a version it doesn't support rather than guess.
Reading it back
Writing an export is the easy half. Until 27.1.0-rc.9, the only way to read one back into inbuxa was to use inbuxa-migrate's importers for Maildir and for mbox/vCard/iCalendar trees, which is to say, to throw the manifest away. That was the gap. A format with one writer and no reader for its most important part is a format in name only.
inbuxa-migrate import files closes it. It reads an export into an archive, the same local file every other importer fills, and from there export writes it into a server. Along with the mail, contacts, calendars, scripts and files, it restores:
- every folder's real name, its place in the tree, its role (Inbox, Sent, Archive, Trash and so on) and whether it was subscribed;
- which address book and which calendar was the default, and each calendar's description, color and time zone;
- which Sieve script was active;
- the files' media types, links and real names;
- the identities, with their reply-to, bcc and signatures, and the addresses used for calendar invitations.
Two parts of reading it back took more thought than the rest.
The same message in several folders. The layout writes a message to every folder it's in, because Maildir has no way to say "this file is also over there." Read naively, one message in two folders comes back as two messages. The specification lets a reader treat files that are identical byte for byte as one message kept in each of their folders, and that's what this one does. It matches copies by their content, not their file names, because nothing in a file name but the Maildir flags can be relied on. Cards in two address books and events in two calendars come back the same way.
Paths are data. The manifest is a file someone else wrote, so every path in it is treated as untrusted. The reader checks that each one stays inside its own part of the export and climbs nowhere, and it doesn't follow a symbolic link anywhere along the way. A link it finds in the tree is skipped with a warning, because the account's real links come from the manifest. A tree without a manifest is refused, and so is a later version of the layout than the reader knows.
A second run brings the archive up to date with the export: flags that changed, a different active script, a renamed folder. It never deletes. That makes an interrupted run safe to repeat.
How we know it works
The test that matters is the round trip. We take an archive with everything the manifest exists for: a folder whose name Maildir can't hold, files whose names a disk can't hold, roles, an unsubscribed folder, a message in two folders, custom keywords, a default address book and calendar, a card and an event in two collections, colors and time zones, an active script, media types, a link, identities with signatures. We export it, read it back and export it again. The second export comes out the same as the first, and the account read back is the same account.
Around that sit the cases that should fail safely. One export plants a folder path that climbs out of the tree, a folder that's a link to somewhere else, a message that's a link, a contacts file at an absolute path, a contacts file that's a link, a link inside the file tree and a link entry that climbs out. Another gives files real names that would climb out of their directory or take a sibling's place. The tests check that nothing from outside the export ends up in the archive, that no entry takes another's place, and that everything inside still comes in. The rest check that a second run changes nothing, that a changed export updates what changed, and that unfinished or newer exports are refused.
Where it falls short
Some limits come with the formats, and some are ours.
- Keywords. Maildir gives each folder 26 letters for keywords beyond the standard flags. A folder that needs more loses the rest, and the manifest counts how many, so a reader can say so.
- Copies on disk. A message in several folders takes space in each, because Maildir has no other way to show it.
- Order within a calendar. iCalendar gives the order of events in a file no meaning, and parsers don't keep it, so a calendar read back may list its events in a different order.
- One of each. So far there is one writer and one reader, and both are ours. A format becomes useful when someone else writes it, or reads it, and finds it works. That hasn't happened yet.
What it isn't
It isn't a protocol, and it doesn't need a registry: it's a layout of files. It isn't a backup format for a whole server, since it holds one account and nothing about the server it came from. And it doesn't replace JMAP. When both servers are running, use JMAP. The layout is for when they aren't, or for a copy you want to keep.
Using it
The specification is at coffeylabs.org/specs/account-export. It's version 1, Coffey Labs LLC is its change controller, and it covers the tree, the manifest, the names on disk, and the security and privacy considerations. inbuxa-migrate writes it with export-files and reads it with import files, and it's open source under Apache-2.0 or MIT, so its code is there to read or borrow.
If you build a mail server, a client, an archiver or a migration tool, we'd like to hear whether this layout works for you, and what it's missing. Write to specs@coffeylabs.org.
How we checked
The figures and behavior here are from inbuxa-migrate 27.1.0-rc.10 and version 1 of the specification as of October 31, 2026. "Open formats" counts Maildir++, vCard, iCalendar, Sieve and plain files. "Members in the manifest" counts its top-level members. The round trip and the hostile export are integration tests in inbuxa-migrate's repository (tests/import_files.rs), run on every change.
About Coffey Labs
Coffey Labs LLC is an Arizona company that builds, owns and maintains open-source infrastructure software: the inbuxa mail suite, ihasmail webmail, the ihasvpn WireGuard server, Cairn OBS log aggregation and the HotDog CMS website builder, plus the tools around them. Its software runs on the user’s own hardware, is published in full under a copyleft license, and has no paid tier. It also runs LINUXexpert, a certification study service at linuxexpert.net. Coffey Labs started in 2018 as LINUXexpert.org and was organized as an LLC in 2026. Learn more at coffeylabs.org.