~/jcoffey$

Articles

ihasmail, One Year On: I Threw It All Away Except the Name

About a year ago I migrated my mail off Zimbra and onto Stalwart. That part went well. Stalwart gave me mail, calendars, contacts, filters and file storage out of one binary with a configuration file I could actually read, and it spoke JMAP natively — one HTTP and JSON protocol for all of it, instead of the four or five I had been stitching together for years.

Then I needed a webmail, and I did the sensible thing: I installed Roundcube. It worked. It has worked for a very long time for a very large number of people, and there is nothing wrong with reaching for it.

But I had just moved to a server that spoke a modern protocol end to end, and my browser was still talking to it the old way. That gap bothered me more than it should have. I went looking for a JMAP webmail and did not find one I could run. So I started writing one, for me, on my own server, with an audience of exactly one.

The first attempt, and deleting it

For months it was an evenings-and-weekends thing. Some weeks I had time and patience; most weeks I had one or the other. Features got bolted on wherever there was room for them — a folder tree here, a compose window there, each one solving the specific annoyance that had bothered me that week.

That is a fine way to build something for one person. It is a terrible way to build something that has to keep growing. Eventually I was spending more of each session working around the previous session than adding anything, and the shape of the thing was fighting every new idea. I had gone down the wrong road, and I had gone a long way down it.

So I deleted it. All of it, except one thing: the name.

I had already bought ihasmail.com — a joke domain, bought the way you buy a joke domain, which is to say instantly and without thinking about it. Having paid for it, I was not about to let a mere total rewrite take it away from me. The name survived the code by being the only part that had never been a mistake.

The restart was the whole difference. Second time around I knew what the thing was for, what it must never do, and what I had gotten wrong. I found a groove almost immediately, and it has not really let up since.

What it turned into

It is not a mail frontend any more, which is not a sentence I expected to write.

It is groupware. Mail, yes, but also calendars with recurring events, invitations, attendee management and free/busy; an address book; and file storage. All three share properly — you can share a calendar, an address book or a folder with another account on your server, with real permissions behind it rather than a link that anyone with the URL can open.

It speaks nine languages besides English: German, Spanish, French, Dutch, Brazilian Portuguese, Russian, Ukrainian, Simplified Chinese and Japanese. The interface language follows the account rather than the browser, so your mail reads the same on every device you sign in from.

Sieve filtering actually works, with a visual rule builder that compiles down to a real Sieve script on the server, and the ability to run a newly written rule back over messages that are already in the folder.

There is an administration section, and this is the part I am most quietly pleased with: it is gated by the server's own role-based access control. Accounts, groups, mailing lists, roles, tenants and domains each appear only if the signed-in account genuinely holds the permission for them. The client is not deciding what you are allowed to see and hoping the server agrees. It asks, and shows you what the answer permits. An operator who does not want any of it can turn the whole section off.

And there are themes, because a mail client is a thing you stare at all day and it should not be someone else's idea of comfortable.

The two tools that fell out of it

Neither of these was planned. Both exist because I hit a wall and had to build a ladder.

stalwart-migrator came out of struggling with a Stalwart 0.15 to 0.16 upgrade. The upgrade is a real one, with real changes underneath it, and doing it by hand on a server with live mail on it is not a relaxing afternoon. I wrote a tool that does the in-place upgrade properly, and then kept it as its own project because other people were clearly going to hit the same wall.

ihasmail-oneshot came out of the opposite problem. Everything I had written assumed you already ran a Stalwart server. If you didn't, step one was "install and configure a mail server", which is not one step. So: one command, a Docker host, a couple of minutes, and you have a full mail stack — Stalwart, ihasmail in front of it, certificates, your first mailbox, and the list of DNS records to add.

There is more than I can reasonably list here, which is its own kind of answer to "how has the year gone".

The rule that survived everything

Through the first attempt, the deletion, the rewrite and every feature since, one constraint has never moved:

Nothing gets built if it needs a datastore outside of what Stalwart already provides.

No database of its own. No cache that has to be kept honest. No volume to back up. Every piece of state — your settings, your filters, your signature, your calendar, your files — lives in your mail server, because your mail server is the only thing that should be the source of truth about your mail.

It is a genuinely annoying rule. It has killed features I wanted. When something needs to remember something, "put it in a table" is always the easy answer, and I am not allowed to give it. The workaround is usually to find where the state actually belongs on the server and put it there instead, which takes longer and is almost always better.

What I get for the annoyance is a client that can be thrown away and recreated without losing anything, that has no migration path to maintain because it has nothing to migrate, and that cannot drift out of sync with your mailbox because it has no separate idea of your mailbox to drift with. That constraint survived the rewrite because the rewrite was largely about taking it seriously.

Where this goes

A year ago this was a thing I built so I would stop being irritated by my own webmail. Today it is a groupware suite in ten languages, two standalone tools, a documentation site, container images and a weekly release, and the only part of the original that made it through is a domain name I bought as a joke.

I have no grand roadmap to announce. What I have is the distinct feeling — after a year, one total rewrite and a lot of evenings — that this is not the finished article. It might just be getting started.

ihasmail.org · the code · AGPL-3.0-or-later