Though I have no complaints about the way they went about implementing it (open standards hooray!), as a mail client author and someone with lots of experience with mail in general - I'm NACK to JMAP. I think that it comes with some questionable design decisions (HTTP? JSON?) which on their face I imagine look fine to the typical HNer, but in many ways is a regression from IMAP. I would prefer to see the limitations of IMAP addressed with a few carefully written extensions to the spec - which is already extensible and has a thriving set of useful extensions in the wild.
By no means is IMAP a particularly good protocol, but it is extremely broadly supported and designed more with email in mind than JMAP appears to be, which seems to focus more on bringing shiny web tech to email regardless of its utility in such a context. It's also one of many closely interlinked mail-related specifications, and JMAP fails to integrate well with many related specs imo.
You might not like it, but every programming language in existence has easy to use HTTP and JSON parsing libraries. It's basically a solved problem.
As a software developer I dread working with protocols that are not via HTTP because most often then not the clients are badly designed, leaky and I can't fix it by changing the client.
And I love JSON in spite of its inefficiencies, because it is easy to debug and there are really good JSON parsing libraries for the statically typed languages I'm using (Scala, Haskell). You basically declare your high level types and the library will derive (de)serialization and validation logic for you.
Also consider that this isn't necessarily about building full fledged email clients. Maybe you want an automated way to read an Inbox and import certain messages in your database. Maybe you build a browser extension that counts the number of unread messages. There are many, many micro tasks that developers would be interested in doing, if they had an easy way to do it.
And do you know what protocol does NOT have good libraries for every language in existence? IMAP.
It's basically not a competition from my perspective, HTTP/JSON wins by default.
"We have libraries for these technologies" is a poor substitute for "These technologies don't really solve the problems that need to be solved."
The nice thing about the old internet protocols is that they tried to distinguish between abstraction and implementation layers. (Not always successfully or effectively, but they did at least try.)
Modern protocol designs seem to do the opposite. They start from a default implementation layer - usually REST, HTTP, and JSON - and then try to build the abstraction layer out of that.
This isn't necessarily a good approach. But it is a reflection of the difference in culture - the change from hackers who were comfortable with open-ended bottom-up development, and modern developers who seem to prefer snap-together development using standard libraries.
> They start from a default implementation layer - usually REST, HTTP, and JSON - and then try to build the abstraction layer out of that.
Also known as the Unix philosophy ;-)
This isn't about comfort, but about doing what needs to be done.
Every webmail interface in existence has implemented their own half baked, proprietary protocol that does what JMAP is doing. Or do you think Google's Gmail web interface is using IMAP?
---
> "hackers who were comfortable with open-ended bottom-up development"
That's because they lacked basic tools. Hackers in those days weren't getting much work done either.
I grew up with ZX Spectrum, MS-DOS, Windows 3.x, started programming in secondary school and while in high school watched as the Internet took over the world.
Well if you're really going to go down that route, you should remember that the "unix philosophy" favours plain text as the data-passing mechanism. JSON itself does not have rules for how things like malformed UTF8 decoding should work, which means that every implementation of this JMAP protocol is going to need to refer to a specific JSON spec for starters, which is already destroying the credibility of the "simple" argument. Also, I don't see how your claims about hackers "in those days" has any basis other than speculation here.
> every programming language in existence has easy to use HTTP and JSON parsing libraries
That argument doesn't hold much water. Every programming language in existence also has easy to use socket libraries. Are you implying that HTTP and JSON are less error-prone than whatever-over-TCP? There's nothing magical about either HTTP or JSON that makes them the right tool for every job. But I guess when all you have is a hammer ...
I would be willing to put a lot of money that the same application built on HTTP/JSON will be much much less error prone than the same app built on TCP sockets.
The tooling is better; debugging is easier; the interfaces are less finnicky; the transfer is less brittle; dealing with objects and documents is much easier conceptually than streams; very powerful performance optimizations and catching can just be turned on while being transparent to the app; crappy networking equipment won't ruin your day; corporate firewalls won't get in your way; encryption is basically drop-in with transparent tooling support.
In no way is HTTP/JSON the best protocol for every situation but thinking you can do better with something home grown on top of TCP is ignoring all the human effort that's gone into solving the problems with straight-tcp protocols. So yes any protocol that's had as much love put into it would probably be just as good but few things have.
You're very welcome to join the EXTRA working group at IETF and propose the extensions that you think would make IMAP better. Apart from working on JMAP, I have also written an extension to IMAP and may write another one next year bringing some of the push stuff from JMAP back to IMAP as well. But JMAP is based on many years of working on servers, middleware and (at least on the web) clients.
We did actually extent IMAP with some experimental stuff first (cross folder threading and thread collapsing for example) but it never solved the batching and proxying difficulties and the cost of instantiating message numbers per-session that are un-avoidable parts of the IMAP model. By the way, engineers who work on other servers have said similar things to us - IMAP is costly to implement in terms of server resources when you're doing true concurrency, high availability, etc.
> IMAP is costly to implement in terms of server resources when you're doing true concurrency, high availability
Yes, IMAP requires expensive coordination among multi-master servers to generate UIDs in such a way that won't mess with client synchronization. In other words, IMAP is not a fully distributed design, it assumes a centralized control plane (think Raft or Paxos), i.e. a single central server with many distributed clients, which is a shame for new systems building on CRDTs.
How does JMAP address this achilles heel of IMAP? Merkle tree sync?
Individual unique IDs and /changes lists all the IDs that might have changed. One good thing about IMAP is that there's a fair bit of data which is immutable, and JMAP retains that - emails with the same ID must have the same content, so there's a limited amount of metadata that you need to resync.
I wrote something about how you fix UID clashes in a split brain while staying within the IMAP data model many years ago...
> I wrote something about how you fix UID clashes in a split brain while staying within the IMAP data model many years ago...
Thanks for this. It was a good read and promoting UIDs instead of bumping UIDVALIDITY is a great idea.
Surely, it would be even better if IMAP had support for distributed Merkle Tree synchronization, so that clients can sync with different server replicas without the server replicas having to coordinate or promote UIDs at all in the first place?
I don't know of any algorithm other than a Merkle Tree that will do this correctly and simply and efficiently in a distributed setting?
Merkle tree would is great for full history - I built something like that with digital signing for tracking clinical data over 15 years ago that would have been fine for email as well - but it's way over-expensive for email.
Which leads back to the key design principle I try to use when working on protocols, which is something like "make the weird edge cases sand and possible, but don't optimise them!" You don't want to build the Merkle tree complexity into a client and have all the servers be completely independent, because it makes the protocol a pain to use for the simple case.
(What we use for IMAP replication in Cyrus is much dumber than all this - it uses a per-message CRC and XORs them together for the whole mailbox to create the sync_crc value. If those don't match, it does a resync. Fixes up split brain just fine while being cheap and dumb for the common case.
> Merkle tree would is great for full history - [...] but it's way over-expensive for email.
Does JMAP then not support syncing full history efficiently as a key design priority?
> That would be a pretty massive change to the entire data model of IMAP. It's never going to happen[tm].
Sure, and that's why I had hoped JMAP would, especially in a distributed master setting, since this was something IMAP overlooked.
I guess it's because JMAP still needs to be backwards-compatible with the strict consistency master-slave restriction of IMAP?
> What we use for IMAP replication in Cyrus is much dumber than all this - it uses a per-message CRC and XORs them together for the whole mailbox to create the sync_crc value. If those don't match, it does a resync. Fixes up split brain just fine while being cheap and dumb for the common case.
You're implementing the first layer of an incremental Merkle tree right there. How many bits are those CRCs just out of interest?
Not full history as in "you can rewind back in time and see every possible past state", no. If I wanted one of those, I'd probably use git as the substrate.
The thing JMAP doesn't have, that I think you're trying to ask for, is the ability to talk to divergent endpoints and resolve the state on the client. JMAP expects to talk to a server which is merging the state into a linear world for it. That linear world view can be different from different servers.
For example, if you implemented your server as a series of git commits, complete with merges whenever you'd had changes on two different servers, then you could just use a commit hash as the state string - and if you got an oldState which was a commit that didn't happen on your server you could still use git to calculate the series of changes on your branch since the fork point plus changes on the remote branch after that commit - and you'd be able to issue a full set of changes. If you DON'T have at least that commit and its predecessors locally, you can't calculate the diff, so you have to return cannotCalculateChanges.
I think what you're wanting here is for the server to get from the client what the last fork point was, and give the client just the changes it knows about since that fork point (like a git fetch) and then the client calculates the merged changes. That's not how JMAP is designed to work. It's an interesting idea, but it does lead to very high client complexity, so it's not what we wanted JMAP to be.
The CRCs are 32 bits, but they're not the only signal. There's also modseq and uidnext, so the CRC doesn't need to be cryptographically strong - if somebody deliberately creates a replica state that comes up with the same CRC but has different content then they could make servers believe they are in sync, but in that attack vector they probably also have enough control to just make the replication layer lie.
We're also using sha1 for message content integrity, which I'd like to move away from eventually. There are plans, but we have other things to finish first. We do insert some randomness into a header on message delivery which makes it much harder for someone to calculate what will be injected when sending somebody an email via SMTP!
> Not full history as in "you can rewind back in time and see every possible past state", no. If I wanted one of those, I'd probably use git as the substrate.
No, not "history" in the git sense, just "history" in the simpler email sense, i.e. "email history", all past emails in their final converged state.
Well, it depends on how you architect your system - you can embed whatever you like in your state. I'd probably do something cheap and nasty like embed a modseq counter for each of the different servers into the state string, and if any of them went backwards I'd reject the /changes with a cannotCalculateChanges error.
I mean, you can do other things - but at the point where you're switching between multiple masters in a split brain from your client, all bets are off - so you're going to need to fall back resyncing any mutable data.
> but at the point where you're switching between multiple masters in a split brain from your client, all bets are off
CRDTs handle split brain fine. They eventually converge. You just don't want your clients flapping in the meantime by resyncing tons of data. That's where a distributed sync algorithm would help keep things working in the interim.
> Yes, IMAP requires expensive coordination among multi-master servers to generate UIDs in such a way that won't mess with client synchronization. In other words, IMAP is not a fully distributed design
JMAP is literally the only positive thing that has happened to email in decades, please don't dismiss it (or do you know of anything else in the works that has any chance of success?).
HTTP and JSON are such an insignificant price to pay for the sliver of hope that email can be saved and not being in complete control of google et al.
The real positive thing that needs to happen to email, is putting an end to near-monopoly of gmail. Email is great. It's decentralized. You can simply roll your own. You can use whatever client you like. Apparently even using HTTP/JSON.
But you can't send mail to anyone using gmail, which is nearly everyone, unless you play by Google's rules. And even then they'll still put you in their spam folder, or just randomly blackhole you without any explanation or recourse.
JMAP vs IMAP vs POP is moot as far as I'm concerned. As long as my mail client continues to work, I'm good. If this gains any traction, I'm sure dovecot and the likes will add support for it (if they haven't already). But no amount of protocol fiddling can fix the fundamental issues of email centralization.
That's what I meant. And we need something better than IMAP/POP to have a fighting chance in challenging google. Because without it IMAP will, without doubt, loose market share even more - further cementing the dominance of larger players.
That is why protocol fiddling is an essential part of it. Not enough, but without something better than IMAP might as well give up yesterday (as most already have done).
> we need something better than IMAP/POP to have a fighting chance in challenging google
How's that? I don't see how messing with IMAP/POP/JMAP will make a difference there. Mail delivery, over SMTP, is what the Gmails and Outlooks of this world are so nasty about. They claim to protect their users from spam, but small mail servers get killed in the crossfire. Mail clients downloading mail over whatever protocol is a trivial problem by comparison, and they have zilch to do with SMTP abuse.
If 99.9% of all mail originate from gmail+outlook then they can (and will) pretty much ignore the rest.
The less dominant they are the more they are forced to be reasonable.
JMAP will help diversify the market as well as simplify the process of creating competing products. And has the potential to vastly increase demand for native clients and proper support from webmail vendors.
All of the above will work towards lessen the dominance of gmail etc.
It isn't anything by itself but I believe it is a requirement going forward.
Because IMAP doesn't cut it, so everyone has to create their own crap, which won't be as "good/easy/cheap" as gmail.
> HTTP and JSON are such an insignificant price to pay for the sliver of hope that email can be saved and not being in complete control of google et al.
How would JMAP accomplish that, in a way that other protocols don't?
The shortcomings of IMAP and POP are reflected in all mail clients and is a large part in what has made webmail so popular.
Another reason is that webmail vendors of today typically deliver a subpar IMAP/POP experience. So combining a native client and webmail when on the go is rarely ideal.
JMAP is the first chance in a long time to get a decent experience that doesn't involve an expert and (even if you are willing to put in the time) tons of compromises.
And aside from all that we have an opportunity and reason to revive native clients that has gone stagnant (which is pretty much all of them).
> The shortcomings of IMAP and POP are reflected in all mail clients and is a large part in what has made webmail so popular.
Could you elaborate on this? I personally find using a mail client like Thunderbird to access my mail account far more responsive and seamless compared to using the webmail interface. If I don't have much bandwidth to work with, the local mail client using IMAP and SMTP will work while the webmail client will experience timeouts.
But syncing mail with IMAP isn't good enough and many features of webmail clients do not map to IMAP clients. There are also tons of caveats during configuration so tons of people, rightfully so, don't bother.
IMAP is incredibly annoying. To send a message, you send via SMTP and then upload that message to your Sent folder, so it's transferred twice. For some reason the IMAP implementation I use means that when I move a message to a different folder, it uploads the message to the new folder, deletes the original message, and then downloads the message from the new folder. I have no idea if it's my server, client or the spec, but very wasteful and often fucks up.
Some interesting work was done on adding prescence and chat to email that im disappointed not to see in jmap. Be great if we could chat to anyone with a name and dns domain instead of being stuck in a silo like facebook.
That would indeed be awesome. Every email server a chat server. But they are not done with JMAP yet, still working on contacts and calendar. Maybe chat could be next.
HTTP is not designed for persistent connections (WebSockets were hacked on later, but JMAP does not use them anyway). This turns a push protocol into a poll protocol, which is a stark regression. It's also got all sorts of other crap built-in which is really not necessary for this use-case but which an intrepid implementer will have to deal with regardless.
JSON does not cope well with binary data, which is common in emails. It fails to elegantly deal with the various email encodings which exist in the wild. Consider as well that all JSON numbers are floating point numbers, despite the fact that floating point numbers provide absolutely nothing of value to this spec and in fact are more likely to introduce bugs than not. And embedded devices can't deal with floats quickly or elegantly, but still need to implement them if they want to use JSON-based protocols. And for what gain!
In short, JMAP reinvents the wheel but worse for the sake of making it easier for web developers to build web shit around email. This kind of stupid change for change's sake is an epidemic in the webshit scene. IMAP is warty but it's fine. Let it be. When your only hammer is JavaScript, everyone else's thumb looks like a nail.
Some remarks as a developer on Fastmail’s webmail, using JMAP daily but not having been much involved in its development:
IMAP really isn’t fine. If it was, mail providers wouldn’t have kept on making their own protocols/APIs for their mobile apps or their webmail. JMAP has various concrete benefits over IMAP. JMAP has been made by people that have been working with IMAP for decades, and have been actively involved in IMAP improvements over that time as well.
Pretty much all of your objections seem to me to either be misinformed, or addressed at https://jmap.io/. Strongly relevant are headings 2, 3, 4, 5, 6 and 8. (I could write more about individual issues, but I’ll just leave it at that.)
The main thing that is only kind-of addressed there is your objection to JSON number representation. JMAP does not state that JSON is the best thing out there; but rather that it is good enough. JMAP doesn’t use floating-point numbers, uses opaque strings for IDs (where many APIs people home-bake would use numbers), and expressly limits its integers to the −2⁵³+1 to 2⁵³−1 range where it does actually use integers. (And none of those places should ever be anywhere near that.)
I will preface this by admitting my only direct experience with IMAP as a protocol was with writing a few scripts to synchronise mail and having to fix bugs in the IMAP libraries I was using.
I must be missing something obvious -- how is IMAP a push protocol? All experiences with IMAP I've had are in the form of basic request-response flows.
Also, regarding JSON floats, most languages have the ability to give you errors if you encounter a float in a JSON field that is meant to be an integer. So it really shouldn't matter at all that JSON's floats are awful. I haven't looked, but does JMAP use floats?
I don't particularly love HTTP nor JSON, but if that's the only problem with JMAP then it's such a massive improvement over IMAP that we should have started switching to it yesterday.
The problem with IDLE is that it requires one TCP connection per folder you want to watch. The better alternative is NOTIFY, but in my experience, it is not as widely supported by server and client implementations.
But that is an extension so you cannot count on it being there. Thus a well-written client would need to handle servers that do not support IDLE. The X11 protocol is similar in that it has a lot of extensions that are theoretically optional but de facto required to deliver a good user experience. It makes implementing such protocols complex because you need to duplicate code paths, one for when the extension is present and one for when it isn't.
The IDLE-command must be a push type of command?
Which is used heavily by clients instead of polling.
As Microsoft does it with RPC is just a mess, they do a http call with 2billion bytes in request size, let the connection terminate at timeout and fire up a new call. I for one hope not that this is how JMAP solves it :(
If submit an app to Apple with IDLE support I would bet will be rejected. JMAP has PushSubscription which will play nice with Apple / Google push services.
JSON explicitly does not require floating point (https://tools.ietf.org/html/rfc8259#page-7). As a data-interchange format, it's not interested in most of the issues surrounding floating point numbers (operations, rounding, exception handling, etc), but it doesn't even use the interchange formats of floating point either.
I'm sure that as a practical matter, it will be a rare implementation that does not work by deserializing non-integer decimal numbers into floating point numbers, but the JMAP spec does not require this behavior, and I believe it uses no decimals.
I do hate this fashion of tunneling everything through HTTP, but then:
- Email protocols are all shit. The email ecosystem still didn't evolve into a format where we can safely transit binary data around. It is still risky to rely even on octet encodings, so there is very little binary data on emails anyway, it's mostly 7bit strings.
- The numbers in emails are nearly all strings. The very few integers are encoding content length and are not necessary with HTTP.
- We have much better odds of having message push that actually works everywhere with an HTTP protocol, mostly because many of our computers are configured to serve ads first, and ads use HTTP push.
That said, I do look forward into all the interesting problems HTTP will create for large emails.
> The email ecosystem still didn't evolve into a format where we can safely transit binary data around.
The only significant characters in email are carriage return, line feed, and period. There's also a line length limit in the SMTP protocol specification. Other than that, bytes sent during the DATA phase are sent unaltered.
Base64 encoding is meant to address this, but it results in a 33% overhead in attachment size. On the usenet side, people came up with an encoding scheme called yenc that actually only escapes those characters mentioned above and only as a 2 to 3% overhead over the original file size.
If you are talking about SMTP, servers may fail on receiving any character larger than 127, unless the client started the session with EHLO and the server announced either the 8BITMIME or the BINARYMIME extensions, where the first one only allows valid UTF8 stings, and the second requires a completely different mechanism that does not use DATA.
> Consider as well that all JSON numbers are floating point numbers, despite the fact that floating point numbers provide absolutely nothing of value to this spec
JMAP seems to not use any float, so implementers do not need floating point logic and can just reject JSON with floats.
Aren't most email attachments base64 encoded anyway? If so, JSON not supporting binary is not really a problem.
Converting to base64 generally increases the payload size. Being able to convert it that way is a workaround - not a solution to being able to transmit binary information.
I received two emails yesterday with application/octet-stream as part of the inner body, compliant with RFC2046 [0]. Having a Content-Transfer-Encoding of base64 is entirely optional.
It's the default for certain larger email hosts - that's the reason you see it frequently, but that in no way means that it is the _best_ option for a protocol that suggests it's solving the problems of the old one.
This isn’t your main point, but FWIW, there is a draft in the IETF for JMAP over websockets. It was approaching trivial to implement; I think our (Fastmail’s) main Cyrus developer wrote it from scratch over a weekend.
By no means is IMAP a particularly good protocol, but it is extremely broadly supported and designed more with email in mind than JMAP appears to be, which seems to focus more on bringing shiny web tech to email regardless of its utility in such a context. It's also one of many closely interlinked mail-related specifications, and JMAP fails to integrate well with many related specs imo.