2012-03-06 41 views
7

我正在通過python訪問GMail的IMAP界面。我運行這樣的命令:當搜索文本包含感嘆號(!),和號(&)等時,IMAP「搜索標題」命令失敗

UID SEARCH HEADER Message-ID "[email protected]" 

即成功(返回1 UID匹配的消息,或0,如果它不存在)。但是,如果搜索文本包含某些字符(如&或!),則搜索文本將在該點處截斷。這意味着:

UID SEARCH HEADER Message-ID "[email protected]" 

被視爲同

UID SEARCH HEADER Message-ID "" 

另外:

UID SEARCH HEADER Message-ID "[email protected]" 

被視爲:

UID SEARCH HEADER Message-ID "abc" 

我已經通過IMAP語言消失spec和ABNF語言規範像這些字符的eems應該是有效的。爲什麼gmail將這些搜索短語截斷爲「!」和「&」字符?有沒有辦法逃避他們? (我試過!,作爲編碼不好的字符串失敗)。是否有一個RFC或文檔顯示真正應該被接受的內容?這是gmail的imap實現中的錯誤嗎?

我也試過文字格式,同樣的結果:

UID SEARCH HEADER Message-ID {15} 
[email protected] 

仍被視爲:

UID SEARCH HEADER Message-ID {3} 
abc 

謝謝!

IMAP RFC3501搜索命令:http://tools.ietf.org/html/rfc3501#section-6.4.4 形式語法:http://tools.ietf.org/html/rfc3501#section-9

+0

我可以證實在搜索查詢中使用感嘆號沒有什麼特別之處。這很可能是您在Gmail中發現的一個錯誤。我建議在開發過程中使用幾個不同的IMAP服務器,特別是因爲gmail的IMAP實現不符合IMAP規範。 – nosid 2012-04-01 19:24:16

+0

謝謝nosid。不幸的是,我需要使用這個代碼的IMAP服務器是gmail,所以在別人上測試對於這個bug是沒有幫助的。但很高興知道我沒有閱讀規範錯誤。我會盡力找到一種方法將這個錯誤報告給谷歌。 – rocketmonkeys 2012-04-03 20:57:36

+0

是的,我目前在通過* alpine *郵件客戶端在Gmail上進行IMAP搜索時遇到此問題,嘗試選擇包含'!'的主題的所有郵件。 – 2016-09-13 15:33:12

回答

1

我一直在打這個問題我自己好幾個月了。

查找標題消息ID < - ! &!...>

結束跳過一些以'< - '開頭的MsgId搜索。也看到&!的問題...不知道如何解決這個問題。

你有沒有從谷歌這個錯誤?

感謝很多

2

我主要是立足於在評論中原來的問題的發現(由Max),Gmail的搜索實現使用一個已經分裂的文本內容轉換成文字後備數據庫,我的回答禮物,而非存儲全文並進行子字符串搜索。

所以這裏有一個可能的解決方法,你可以在C#與Gmail一起使用使用我MailKit庫(這是一個相當低的水平IMAP庫,所以這應該很容易轉化爲基本的僞代碼):

// given: text = "[email protected]" 

// split the search text on '!' 
var words = text.Split (new char[] { '!' }, StringSplitOptions.RemoveEmptyEntries); 

// build a search query... 
var query = SearchQuery.HeaderContains ("Message-ID", words[0]); 
for (int i = 1; i < words.Count; i++) 
    query = query.And (SearchQuery.HeaderContains ("Message-ID", words[i])); 

// this will result in a query like this: 
// HEADER "Message-ID" "abc" HEADER "Message-ID" "[email protected]" 

// Do the UID SEARCH with the constructed query: 
// A001 UID SEARCH HEADER "Message-Id" "abc" HEADER "Message-Id" "[email protected]" 
var uids = mailbox.Search (query); 

// Now UID FETCH the ENVELOPE (and UID) for each of the potential matches: 
// A002 UID FETCH <uids> (UID ENVELOPE) 
var messages = mailbox.Fetch (uids, MessageSummaryItems.UniqueId | 
    MessageSummaryItems.Envelope); 

// Now perform a manual comparison of the Message-IDs to get only exact matches... 
var matches = new UniqueIdSet (SortOrder.Ascending); 
foreach (var message in messages) { 
    if (message.Envelope.MessageId.Contains (text)) 
     matches.Add (message.UniqueId); 
} 

// 'matches' now contains only the set of UIDs that exactly match your search query