电子邮件的唯一标识符

3
我正在编写一个C#应用程序,允许用户将电子邮件存储在MS SQL Server数据库中。很多时候,客户会将同一封电子邮件抄送给多个用户。如果他们都试图将相同的电子邮件添加到数据库中,我希望确保该电子邮件只被添加一次。
MD5似乎是一种实现这一点的方法。我不需要担心恶意篡改,只需确保相同的电子邮件将映射到相同的哈希值,并且不会有两个具有不同内容的电子邮件映射到相同的哈希值。
我的问题实际上归结为如何将多个字段组合成一个MD5(或其他)哈希值。其中一些字段将每封电子邮件具有单个值(例如主题、正文、发件人电子邮件地址),而其他字段将具有多个值(不同数量的附件、收件人)。我想开发一种唯一标识电子邮件的方式,它将是平台和语言无关的(不基于序列化)。有什么建议吗?

你有调查过已经实现这个功能的现有解决方案吗?这种方法被称为去重,例如在Symantec Vault中实现:http://www.symantec.com/business/enterprise-vault - Marek
3个回答

2

你是否看过其他邮件头,比如(在我的邮件中,OS X Mail):

X-Universally-Unique-Identifier: 82d00eb8-2a63-42fd-9817-a3f7f57de6fa
Message-Id: <EE7CA968-13EB-47FB-9EC8-5D6EBA9A4EB8@example.com>

至少需要Message-Id,对于同一封邮件(发送给多个收件人),该字段可以是相同的。这比哈希更有效。

虽然不是问题的答案,但可能是解决问题的答案 :)


这种方法的问题在于它依赖于邮件客户端。我想找到一种策略,只要你知道发送时间、发件人电子邮件地址、主题、正文、收件人和附件,就可以工作。 - Skywalker
如果电子邮件是通过MS Exchange服务器发送的,则可能会缺少Internet标头。因此,这不是建议使用的技术。原则上很好,但在现实世界中不起作用。 - UnDiUdin

2

您计划存档多少电子邮件?如果您不期望归档需要很多TB,我认为这是一种过早的优化。

由于每个字段都可以表示为字符串或字节数组,因此它包含多少值并不重要,对哈希函数而言,它们都看起来相同。只需将它们全部哈希在一起,就会得到一个唯一标识符。

编辑 伪代码示例

# intialized the hash object
hash = md5()

# compute the hashes for each field
hash.update(from_str)
hash.update(to_str)
hash.update(cc_str)
hash.update(body_str)
hash.update(...) # the rest of the email fields

# compute the identifier string
id = hash.hexdigest()

如果您将所有的更新调用替换为,您将获得相同的输出
# concatenate all fields and hash
hash.update(from_str + to_str + cc_str + body_str + ...)

提取字符串和界面的方法因您的应用程序、语言和API而异。

即使不同的电子邮件客户端在给定相同输入时可能为某些字段产生不同的格式,这也将给您一个与原始电子邮件唯一对应的哈希值。


3
我注意到这份伪代码存在一个主要缺陷。为了简化,我们假设只有两个字段,string1和string2。使用你的伪代码,{string1 = "foo", string2 = "bar"} 和 {string1 = "foob", string2 = "ar"} 会得到相同的哈希值。也许可以通过对各自哈希值之和进行哈希来解决这个问题? - Skywalker
1
哈希值并不保证唯一。不同的输入可能会生成相同的哈希值。如果哈希值匹配,你仍应该进行内容比较。通常情况下,你会使用哈希桶,每个桶都包含具有相同哈希值的所有消息。(在表结构中,这将是2个表,一个(hash=unique),另一个(id=unique, foreign key to hash not unique),存储消息+标头) - extraneon
1
使用具有大哈希值的加密哈希函数(例如MD5和其128位哈希值),您可以几乎保证不会发生哈希冲突。但是,这种方案的问题在于它会产生易于预测的情况,其中哈希值会发生冲突。 - Skywalker
1
@Skywalker,@mikerobi,你们真的想要发布存在潜在问题的软件吗?一年后,你们可能会接到报告说它已经崩溃了,而你们却不知道该去哪里寻找原因。如果你们决定不处理哈希碰撞,至少在日志中打印出来“检测到...的哈希碰撞”。这样你们或者维护人员就至少知道发生了什么。 - extraneon
3
避免 Skywalker 指出的碰撞问题的常见技巧是在连接字符串之前在每个字段前加上长度,或者使用一个在字段中未使用的明显分隔符。 - abc
显示剩余5条评论

1
为什么不直接对原始消息进行哈希处理呢?它已经编码了除信封发件人和收件人之外的所有相关字段,您可以在哈希之前自己添加这些头部。它还包含所有附件、整个消息正文等,并且是一种自然而易于表示的方式。它也不会受到mikerobi提议中容易生成哈希冲突的影响。

1
很不幸,我之前说过希望它能够跨平台,但实际上至少需要支持 Outlook。因为微软的无限智慧,Outlook 并不存储原始消息。 - Skywalker

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