Arnt Gulbrandsen
About meAbout this blog

Threading email using Thread-Index

Microsoft Exchange sends email containing a header field called Thread-Index that does much the same job as References. I've no idea why Exchange does that instead of the normal way. But I have found out how to parse it, and it's not terribly difficult. It's easiest to explain using examples, so here are the Thread-Index fields from four messages:

Thread-Index: Aca8OXuAU3E0OYfxS/­CjgSLFGePpiQAdZqFQACzEh/­AAmOpSkA==
Thread-Index: Ace2UdoJVaeQeVVpS­p2ZxZp3q7pBrg==
Thread-Index: Aca6Q3T3KOXW2RS5E­X9R13340HQWLP==
Thread-Index: AcgB760UE69bP0PFT­52+hzoqOvhDDQAAAo8g

The first 30 characters are different for all of these, which means that the messages belong to different threads. Hoever, three out of the following four messages belong to the same thread:

Thread-index: Acnk7AtURXtW­l9jTRdGX7mDGIxfHtw==
Thread-Index: AcZJXMEg7BHm/I­X0SSuMswWV9Kglbg==
Thread-index: Acnk7AtURXtWl9jT­RdGX7mDGIxfHtwAAAo8g
Thread-index: Acnk7AtURXtWl9jT­RdGX7mDGIxfHtwAAAo8gqFQACz

The value is really base64-encoded entropy, but parsing and using it doesn't require decoding. Just take the first 30 characters (ie. 176 bits). If they are the same for two messages, then those messages belong to the same thread. Within a thread, a reply's Thread-Index is the same as that of its parent, with a random suffix added. In my second example, the fourth message is a reply to the third, and the third is a reply to the first.

Here is some code that converts Thread-Index to References.

Generating Thread-Index is almost as simple, you just need 176 bits of high-quality entropy and a base64 encoder. Why bother, though? Exchange doesn't dominate the market any more. Gmail is king of the hill now and it sends References, so Exchange has to parse References just like the rest of us.


Lack of PGP support in aox

I'm not eager to add any PGP support in Archiveopteryx. That shouldn't be needed, but is, because PGP's signature checking is much stricter than e.g. DKIM's. DKIM thinks a duck is a duck, PGP cares deeply about the details. A quoted-printable duck is not the same as a plaintext duck, and two quoted-printable ducks may not be the same either. Archiveopteryx faithfully implements sixty email-related RFCs and mail stored in or processed by aox frequently cannot be verified by PGP.

However. I care about encryption and privacy, and PGP has the mindshare and is widely considered The Solution. The problem with The Solution is that over the years, it has remained steadily at 0.0% adoption. At the moment slightly below 0.005% of email users have PGP keys, and some fraction of those 0.005% actually use PGP. I infer from that number that PGP has defects that block its adoption almost completely. I have some ideas what those defects are, but that doesn't matter, because whatever they are, their result is to block adoption.

This has been the case for 20 years, and by now I consider PGP to be hopeless. PGP hinders encryption and hurts our privacy, it doesn't help. I don't want to write any code to support that. Perhaps only ten lines of code and a few tests are needed, but I just don't want to write even that.

(Am I doing something else? Yes, I am, actually. I'll write about what later.)

Update: After writing the above, I suddenly remembered this old dystopian novel. The scenes in the 31st floor offices remind me of PGP. Worthwhile ernest people working hard, doing the best work they can.


inSort()'s revenge

Once upon a time, twenty years ago now, Qt's generic data structures included a function called QList::inSort(). Haavard Nord wrote that and didn't really document it, and when I wanted to write about it he only said it was useful sometimes. What was I to write? Use inSort() rather than insert() when that's useful?

There is a chance that I simply deleted it when I couldn't write sensible documentation.

Two decades later I finally understand why inSort() was a good idea after all. It's useful for a particular kind general data structure that only occurs in GUIs: The list that should be mostly sorted, but should not be resorted once it's shown on-screen.

Consider a list of things that the user can select and either open or delete. Sorting by modification time can make sense (for some kinds of things), but if a UI-thing were to move when someone else updates the actual-thing, then it might move an instant before the user selects and deletes that. Oops.

Thus inSort(). Stupid name, but its presence would have been an improvement to some GUIs.


Android boot with animated GIF

I've hated the Cyanogenmod 11 boot animation since I first installed Cyanogenmod on my phone. Admittedly I don't see it often, but I hate it. These walking fingers, possibly drawn by Will Holmes, would be so much better. So I put together a shell script to convert animated GIF files to the format Android needs.

Now and then phones are lost, particularly at schools, and I have two children, so I added an option to add text.

Reddit's mesmerizinggifs is full of suitable input files. To download today's highest-scoring animation and annotate it with Nirmala's phone: (more…)