我在Go中使用net/mail
库,一切都很棒,但我想传入原始电子邮件并保留标题的顺序。这很重要,因为在每个邮件服务器上传递邮件的邮件服务器按顺序添加邮件头。没有订单,很难知道谁收到了每个服务器添加的内容,时间和标题。
net/mail
库stores the headers in a map,根据定义,它没有订单概念。似乎是一个奇怪的选择,因为标题顺序仅基于电子邮件中的订单,但情况确实如此。
任何人都有任何关于如何保留订单标题的建议?
由于
答案 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)。
但是,匹配Received
和Received-SPF
标题稍微复杂一点,
为:
Received
标头都可能有相应的Received-SPF
标头; Received-SPF
标题可能不会显示在Received
标题上方;这是
recommended but not mandated by the RFC(此外,很多节目都没有
甚至遵循RFC,所以无论如何这都不是保证。)因此,您需要解析标头的值并根据它们进行匹配
那,或使用net/textproto
包进行更低级别的访问
头。您可以使用ReadMIMEHeader()
的来源作为起点。