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.


An aside on and the Xbox 360 is a fine library. High DWIM factor. So I was happy when Microsoft suggested that I use instead of the class Microsoft had previously suggested as the best-supported, JavascriptSerializer.

Starting with the July 2012 release, the Xbox ADK contains an integrated version of Unfortunately it seems dynamic types don't work on the Xbox 360, so they removed all the dynamic parts of JSON (ie. JS and most of the O).

Thus, for using on the Xbox, the following three rules apply: Use using Json.Net.Adk; instead of the proper package name. Use only JsonTextReader and its helpers (JsonToken, IJsonLineInfo) to parse. Use printf to write JSON.

Should you feel tempted to use's excellent higher-level functionality, forget it. It's not there. The Microsoft Help page spends six sentences describing, and that really is everything you can use.

I do wonder why dynamic doesn't work, and why that and the lack of the Microsoft.Csharp assembly isn't documented.


A Nokia Lumia arrived

I need it for testing some compatibility blah.

Although it looks modern and snazzy and so on, and they've clearly tried to make it iOS-like, the visual design somehow communicates that the next screen may be this:

(Note: I copied that from MSDN without permission.)

Update: Later it told me an update is available, and to please connect the phone to a computer, which would tell me more and allow me to update the phone. I connected it to my desktop. The phone did nothing and there's no apparent way to make it do something or ask what the problem might be. The computer supplies power, so it cannot be fear of running out of power in the middle of the upgrade.

I suspect that computer actually means computer that runs the right version of Windows and has the right software installed. But they don't want to say that, because it would sound complicated. Windows phone can be complicated but it must never sound complicated. Plonk.

Update: I gave the phone to an ex-Nokia colleague who willingly began using it.


Silverlight video streaming on the Mac

The Silverlight streaming has a tendency to pick a very low frame rate on some hosts, particularly on the Macintosh. Microsoft has promised a fix in Silverlight 5, but that doesn't help now.

The workaround is to disable WindowSizeHeuristicsEnabled in the player configuration file. Of course that may have negative consequences.