2017-05-05 142 views
0

我在Go中使用net/mail庫,一切都很好,但是我想傳遞原始電子郵件並保留標題的順序。這很重要,因爲每個傳遞消息的郵件服務器都按順序添加它們的標題。如果沒有訂單,它很難知道誰收到每個服務器添加的內容,時間和標題。 net/mail圖書館stores the headers in a map,它根據定義沒有秩序的概念。由於標題順序僅僅基於電子郵件中的訂單,似乎是一個奇怪的選擇,但情況正是如此。 任何人都有什麼建議,我怎麼可以保留訂單頭被讀取?Go(lang)解析電子郵件標題並保持順序

由於

+0

它將它存儲在'map [string] [] string'('textproto.MIMEHeader')中。關鍵是標題名稱,該值是所有出現該標題的片段,它應該*爲*。我不確定你爲什麼認爲他們沒有訂購?在哪種情況下失敗? – Carpetsmoker

+0

因爲我無法解析郵件標題,並將它們打印出來並獲得原始順序,但我認爲我完全錯過了某些東西。我解析了一封郵件,然後從'net/mail'對象重新生成了郵件,並擔心'Received'和'Received-SPF'會失序,因爲地圖沒有排序,但是您說'Received [0 ]'與'Received-SPF [0]'匹配。正如在電子郵件中,當每個服務器添加它們時,這些將會彼此相鄰,所以當從地圖重新創建標題時,我需要將各個標題對從陣列位置放在一起? – amlwwalker

回答

1

net/mail包使用net/textproto包來解析報頭 (見ReadMessage())。具體而言,它使用ReadMIMEHeader()爲 頭,其被記錄爲:

返回的映射米地圖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) 
    } 
} 

這是真的,因爲他們出現消息 在頭的原始順序是輸了,但我不意識到這真的很重要的任何場景。 不是 lost是多值標題的順序。切片確保它們的順序與電子郵件中顯示的順序相同,爲 。

您可以使用一個簡單的程序對頭進行循環驗證,並且 比較值(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,所以這不會是一個保證)。

所以你要麼需要解析頭的價值,並基於 與它們匹配,或者使用net/textproto包更多低級別的訪問 頭。您可以使用ReadMIMEHeader()的來源作爲起點。