Sorry, Maildir, I am breaking up with you

It’s not you, it’s me. But let me start at the beginning…

While I want my IMAP server to be the source of truth for my mailbox, I do like to have my emails available offline on my main computer. For years, I did what pretty much everyone else does: store them in a Maildir.

Maildir checks some major boxes. Every email is a file. Support for it is almost ubiquitous. So what’s not to like? Well, nothing per se. Really, Maildir is great! There is just one giant-ass caveat: it’s great - for the problem space that it was designed for. And if, like me, you are using Maildir on a computer on which no actual mail delivery takes place, then I can tell you with certainty: whatever you are using it for, it is not within the problem space that Maildir addresses.

So, why then does everybody use it? Maybe for some it’s quirks were just bearable enough to not bother. After all, there are at least enough tools to help you deal with it. For me, it now feels more like the German saying “not seeing the forest because of all the trees”. It’s a humorous take on the idea that sometimes you have a take a step - or many steps - back to be able to accurately assess the situation you are in.

Let me provide you with some birds-eye views of the forest that is Maildir. As a baseline, let’s recall that Maildir was invented for qmail (a mail delivery agent) to reliably deliver incoming messages. Now, reliability and incoming messages, that still sounds about right for storing email on your laptop, doesn’t it? Well, consider this:

  • From qmail’s maildir(5):
    • A machine may crash while it is delivering a message

      Does that sound like a problem you are having?

    • A machine may have two programs simultaneously delivering mail to the same user

      If you have two programs simultaneously delivering mail to a single folder from the same IMAP account, then you should indeed continue to use Maildir. And maybe go see a doctor?

    • maildir works without trouble over NFS

      Same as above…

The last point is especially important. Both the man pages as well as the Using maildir format page (which is often cited as the Maildir spec these days) mention NFS multiple times. The historical context is important. At that time, your typical setup for, let’s say, a university was this: every user had a home folder. This home folder was an NFS share, so that workstations were either interchangeable (teachers) or could be shared (students). Every user also had a strict quota, because disk space was a limited resource back then. And so, mail delivery to an NFS share was an important issue. And yes, of course they had multiple SMTP servers, potentially delivering mails at the same time.

Maildir solved several issues elegantly. Having the tmp folder along the cur and new makes even an ongoing delivery count against a user’s quota and does not eat up other, potentially shared disk space. It also ensures that the temporary file, once complete, is on the same filesystem as the final destination (new) - a prerequisite for the final delivery (a move/rename) really being as atomic as desired.

Ok, so Maildir solves some issues that might not apply for the use case at hand. No big deal? I guess this is where things start getting subjective. Let’s take a look at an actual filename from my inbox:

1686653385.#3261M390671128P163708V65024I9218159.serotonin,S=11814:2,RS

Quite a filename, right? Not very handy. But this name was generated according to the spec. So surely, it provides some value? Let’s take a closer look.

The part up to the first . is a timestamp. This is already hilariously stupid, because it is the timestamp of the “delivery”, i.e. when I pulled the email from my IMAP server. However, for $reasons, I occasionally need to re-sync from scratch, and so roughly half of the emails in my inbox currently start with that timestamp. If you re-sync a big folder that takes a few seconds, you’ll have a bunch of very-close-but-not-identical timestamps. Tab-complete that!

The second part is just randomness. But the randomness is important, to have unique filenames! Well, fun fact: since this email was pulled from my IMAP server, it already has a guaranteed-to-be-unique (in this mailbox) identifier: the IMAP UID. My inbox UIDs are currently five digits! That’s 31 additional characters of filename wasted for no gain…

Third part is the hostname. Obviously useless here.

The ,S=11814 part is also hilarious. That’s a trick that was later mandated by the Maildir++ spec (but the original spec leaves room for that). The file size is encoded in the filename, so that tools can avoid an additional call to stat(3). I’m sure it was a reasonable thing to do at some point, in some situation. But having an IMAP mirror on your laptop is not that situation.

The last part encodes the message’s flags. This is in fact quite useful! But that’s two bytes out of many.

“Ok”, you might say, “I get it, the filenames are awful. Who cares? Everyone uses tools that hide them”. Well, maybe. I myself wrote such a tool. If I am looking for a message amongst hundreds of others, I need a tool, no doubt. But if I have a folder with three patches to review, why do I need a dedicated tool to find the right one, just because my arcane storage format requires unmanageable filenames for reasons that do not apply to me?

Also, is the one I am looking for in the new or the cur folder? Did I mention those folders make no sense in this context? The sole purpose of the new folder is that the first application to look at it immediately moves the files over to cur. In the intended use case, this might be your IMAP server. This way it can tell which messages need new UIDs. IMAP-sync tools tend to use the new folder in some fake, made up way, such as delivering messages with the IMAP /Recent flag to the new folder. Heck, even I did that in vsync. But there is simply no reason for it. The tool just pulled the messages from IMAP, it can just tell you that there are X new messages!

Ok, so the filenames are crap, the additional new and cur folders are annoying, and all because of problems we don’t have. But at least you can have a folder structure, like in your IMAP account. Right? Right??

In case you are reading this and not watching the live stream, I am pretty much foaming right now. You see, Maildir doesn’t know anything about folders. There was no such thing at the time. So you can of course have a bunch of folders, and each of them is a Maildir. But then, what happens if you create a folder called new? Do you nest it in the new folder of the parent Maildir? It may or may not work, but the spec is very brief, so it would be easy to create a situation which is not violating the spec, but would probably break or confuse some faithfully Maildir-compliant consumers.

That’s where Maildir++ is supposed to come in. It’s supposed to be the “folders” extension of Maildir. It does solve e.g. the issue of the new folder, but it does so in a rather funny way, though it’s only funny with decades of hindsight, because their goal was backwards compatibility with Maildir, which makes sense. In case you’re not familiar, Maildir++ boils down to two things:

  • There is only one level of nesting
  • To avoid collisions with the Maildir folders, Maildir++ folders start with a .

So if you have the folders foo/a and foo/b in your IMAP, you’d get the following folders in your root Maildir: .foo, .foo.a, and foo.b. I’ll spare you the side track into hierarchy delimiters (both in IMAP and Maildir++, you get to pick your own), and how much of a pain it can be to make sure this works with arbitrary delimiters. Suffice it to say to say that work-arounds were written because this was under-specified.

But let’s stick to the folders. The document has the audacity to state

This is all that there’s to say about folders

A pretty bold claim, given that I know how this worked out. As always, it probably made sense at the time it was written. Let’s take a look at the backward compatibility:

Folders are created as subdirectories under the main Maildir…

A Maildir++ client ignores anything in the main Maildir that starts with a period, but is not a subdirectory.

From this, you sort of get the idea that your “main Maildir” was itself still an actual folder. It is, on those systems that use Maildir++ for good reasons, your main inbox. In IMAP, however, the INBOX is just a folder, and you can have folders in it as well as next to it. But if your main Maildir is INBOX, where does a subfolder bar in it go? Well, the document doesn’t say, but your IMAP server probably handles it something like this (extending the folders example above):

  • .foo
  • .foo.a
  • .foo.b
  • .INBOX.bar

Note how there is no .INBOX, because those mails are in the root. But as Maildir/++ found their way onto laptops like mine, people started to get irritated by this. In IMAP, INBOX is a folder just like foo, so why not have a folder .INBOX? Well, the spec does not say that there can’t be one. And on your laptop the root Maildir doesn’t mean shit, because the only delivery happening is from the tool that syncs your IMAP account over. So that’s what people started doing. And tools adapted, by offering both options.

And so started the proliferation of variations of Maildir++, to the point that some folks even got rid of the initial . for the subfolders, because they want “proper directories”. And today, people use a wild mix of variations of Maildir++ or unspecified mappings of folders to plain Maildirs in some filesytem hierarchy.

And this is extremely frustrating for the authors of Maildir tools, because one does not simply “implement Maildir/++”. There are just too many, too un(der)specified variations out there. I don’t blame the folks who created them, though. They did so, because, like me - and this is the one thing I hope people will realize - they never wanted Maildir/++ in the first place. There just wasn’t anything else. There isn’t.

So, now what? If you’re still reading, you’re probably hoping I have a better solution. Well, yes and no. I have been fiddling, and once I am satisfied, I will write an implementation and, more importantly, a spec. Will people care? I don’t know. But I have decided for myself that I will get rid of Maildir on my laptop, and I will create the tools that I myself need to be happy. That might not be good enough for others, and getting to the level of support that Maildir/++ enjoys seems pretty unlikely. We’ll see.

For now, I just wanted to share this revelation with you. And of course write it down, so I can point people to it when they wonder why I get angry at Maildir sometimes…

If you’ve really read through all this, why not drop a comment in my public inbox? Or message me on IRC, I am bitfehler on libera.chat.