Go(lang)解析电子邮件标题并保持秩序

时间:2017-05-05 14:44:53

标签: email go email-headers

我在Go中使用net/mail库,一切都很棒,但我想传入原始电子邮件并保留标题的顺序。这很重要,因为在每个邮件服务器上传递邮件的邮件服务器按顺序添加邮件头。没有订单,很难知道谁收到了每个服务器添加的内容,时间和标题。 net/mailstores the headers in a map,根据定义,它没有订单概念。似乎是一个奇怪的选择,因为标题顺序仅基于电子邮件中的订单,但情况确实如此。 任何人都有任何关于如何保留订单标题的建议?

由于

1 个答案:

答案 0 :(得分:1)

net/mail包使用net/textproto包来解析标头 (见ReadMessage())。具体来说,它使用ReadMIMEHeader() 标题,记录为:

  

返回的地图m将CanonicalMIMEHeaderKey(键)映射到一系列值   在输入中遇到的顺序相同。

如果需要,您可以view the full source,但基本流程是:

headers = make(map[string][]string)
for {
    key, value := readNextHeader()
    if key == "" {
        return headers // End of headers
    }

    if headers[key] == nil {
        headers[key] = []string{value}
    } else {
        headers[key] = append(headers[key], value)
    }
}

消息中出现的标题的原始顺序是正确的 失去了,但我不知道任何真正重要的场景。什么 isn&#t; t 丢失的是多值标头的顺序。切片确保它们的重要性 与电子邮件中出现的顺序相同。

你可以用一个简单的程序验证这一点,该程序循环标题和 比较值(such as this one in the Playground)。

但是,匹配ReceivedReceived-SPF标题稍微复杂一点, 为:

  1. 并非每个Received标头都可能有相应的Received-SPF标头;
  2. Received-SPF标题可能不会显示在Received标题上方;这是 recommended but not mandated by the RFC(此外,很多节目都没有 甚至遵循RFC,所以无论如何这都不是保证。)
  3. 因此,您需要解析标头的值并根据它们进行匹配 那,或使用net/textproto包进行更低级别的访问 头。您可以使用ReadMIMEHeader()的来源作为起点。