So far the best description i found about Thread-Index is this. There is also an MSDN entry about it but if you check the first link you will know that MSDN description differs from reality. I managed to write a class that will parse the Thread-Index header:
public class OutlookThreadIndex
{
public DateTime Date { get; private set; }
public Guid Id { get; private set; }
public string Raw { get; private set; }
public bool IsValid
{
get { return Date != default(DateTime) && Id != default(Guid); }
}
public OutlookThreadIndex(string threadIndex)
{
Raw = threadIndex;
var bytes = Convert.FromBase64String(threadIndex);
// thread index length should be 22 plus extra 5 bytes per reply
if (bytes.Length < 22 || (bytes.Length - 22) % 5 != 0)
return;
Id = new Guid(bytes.Skip(6).Take(16).ToArray());
var headerTicks = bytes
.Take(6)
.Select(b => (long) b)
.Aggregate((l1, l2) => (l1 << 8) + l2)
<< 16;
Date = new DateTime(headerTicks, DateTimeKind.Utc).AddYears(1600);
var childBlockCount = (bytes.Length - 22) / 5;
for (var i = 0; i < childBlockCount; i++)
{
var childTicks = bytes
.Skip(22 + i*5).Take(4)
.Select(b => (long) b)
.Aggregate((l1, l2) => (l1 << 8) + l2)
<< 18;
childTicks &= ~((long) 1 << 50);
Date = Date.AddTicks(childTicks);
}
}
public override string ToString()
{
return string.Format("Id: {0}, Date: {1}", Id, Date.ToLocalTime());
}
}
public static class MimeHeaderCollectionExtensions
{
public static OutlookThreadIndex ThreadIndex(this MimeHeaderCollection headers)
{
var header = headers["Thread-Index"];
return header != null
? new OutlookThreadIndex(header.Raw)
: null;
}
}
This is a sample result:
- Thread-Index:
Ac52TvSLqL2n1+xFTLyFv0/vTSUlWgyF0E9Q
- Parsed Id:
d7a7bda8-45ec-bc4c-85bf-4fef4d25255a
- Parsed Date:
2013-09-03 07:26:58
Thread-Index can be useful in two cases:
- mail is missing Date in header - we can use thread date
- mail is missing In-Reply-To or References in header - we can use thread id
I have tested this against a series of email and found out that a lot of them are parsed incorrectly. Here is an example:
- Thread-Index:
AQLNahwAkMF4P9Bl8t7dPDytf5aNnA==
- Parsed Id:
3f78c190-65d0-def2-dd3c-3cad7f968d9c
- Parsed Date:
1831-11-05 00:06:01
And here is another one:
- Thread-Index:
Ac6ocXoGclflrAlgQg2VFL1JFq6hyg==
- Parsed Date:
2013-09-03 08:47:37
- Parsed Id:
ace55772-6009-0d42-9514-bd4916aea1ca
The first Thread-Index is invalid (see year 1831). The second one is ok. What is interesing is that both Thread-Indexes are from the same mail message but the first one is from senders Sent folder and the other one is from recipients Inbox folder. I'm using Outlook 2013. Also interesting fact, all indexes that seem invalid have date around year 1800. Has anyone faced this problem before and/or can suggest any solution?