使用Python解析邮件头中的Thread-Index线程索引

11

一些邮件客户端不会设置 References 标头,但会设置 Thread-Index 标头。

有没有办法在 Python 中解析这个标头?

相关问题:电子邮件头字段“thread-index”如何工作?

Mail 1

Date: Tue, 2 Dec 2014 08:21:00 +0000
Thread-Index: AdAOBz5QJ/JuQSJMQTmSQ8+dVs2IDg==

邮件2(与邮件1相关)

Date: Mon, 8 Dec 2014 13:12:13 +0000
Thread-Index: AdAOBz5QJ/JuQSJMQTmSQ8+dVs2IDgE4StZw

更新

我希望能够在我的应用程序中将这两个邮件进行关联。对于已知的 ReferencesIn-Reply-To 标头已经完美地实现了这一点。


你究竟想用Thread-Index做什么?你想检索什么样的信息?似乎没有Python包可以解析这个头文件,你将不得不实现适合自己需求的东西。这篇文章可能作为使用Python解析此头文件的第一指南有所帮助。如果你能说明你的需求,也许我可以帮忙。祝好运! - Lucas Infante
@maccinza 我更新了问题:我想在我的应用程序中能够链接这两封邮件。对于已知的 References 和 In-Reply-To 标头,它已经完美地工作了。 - guettli
2个回答

11

根据这里的信息,我能够整理出以下内容:

import struct, datetime

def parse_thread_index(index):

    s = index.decode('base64')

    guid = struct.unpack('>IHHQ', s[6:22])
    guid = '{%08X-%04X-%04X-%04X-%12X}' % (guid[0], guid[1], guid[2], (guid[3] >> 48) & 0xFFFF, guid[3] & 0xFFFFFFFFFFFF)

    f = struct.unpack('>Q', s[:6] + '\0\0')[0]
    ts = [datetime.datetime(1601, 1, 1) + datetime.timedelta(microseconds=f//10)]

    for n in range(22, len(s), 5):
        f = struct.unpack('>I', s[n:n+4])[0]
        ts.append(ts[-1] + datetime.timedelta(microseconds=(f<<18)//10))

    return guid, ts

给定一个线程索引,它返回一个元组(guid, [日期列表])。对于您的测试数据,结果为:

 > parse_thread_index('AdAOBz5QJ/JuQSJMQTmSQ8+dVs2IDgE4StZw')
('{27F26E41-224C-4139-9243-CF9D56CD880E}', [datetime.datetime(2014, 12, 2, 8, 9, 6, 673459), datetime.datetime(2014, 12, 8, 13, 11, 0, 807475)])

我手头没有足够的测试数据,所以这段代码可能会有错误。欢迎随时告诉我。


非常感谢。运行良好! - guettli
'kp4o6SAzO6Xc19R5OPjnmqbg6v2utA==' 失败:OverflowError:日期值超出范围。 - guettli
@guettli:这看起来不像是有效的标题(第一个字节必须为“1”)。 - georg
1
我找到了另一种解决这个问题的方法,我认为比你的方法更易读。但是目前你的解决方案已经在生产中运行了几年,没有任何问题。因此,如果其他人或我自己将来需要备用解决方案,这只是提供信息而已。[https://technical.nttsecurity.com/post/102enx6/outlook-thread-index-value-analysis] 你可以在链接页面底部找到代码。 - tzanke

1
这是@georg的答案更新到Python 3:
import base64, struct, datetime

def parse_thread_index(index):

    s = base64.b64decode(index)

    guid = struct.unpack('>IHHQ', s[6:22])
    guid = '{%08X-%04X-%04X-%04X-%12X}' % (guid[0], guid[1], guid[2], (guid[3] >> 48) & 0xFFFF, guid[3] & 0xFFFFFFFFFFFF)

    f = struct.unpack('>Q', s[:6] + b'\0\0')[0]
    ts = [datetime.datetime(1601, 1, 1) + datetime.timedelta(microseconds=f//10)]

    for n in range(22, len(s), 5):
        f = struct.unpack('>I', s[n:n+4])[0]
        ts.append(ts[-1] + datetime.timedelta(microseconds=(f<<18)//10))

    return guid, ts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接