Home >> Blog >> 了解IMAP網際網路資訊存取協定
了解IMAP網際網路資訊存取協定
在這篇文章中,我們將深入研究 IMAP。IMAP 代表 Internet 資訊存取協定,它是描述如何存取電子email郵箱中的資料的開放標準。雖然 IMAP 是接收電子email的重要組成部分,但它並不總是最容易實現(或理解)的,這就是 Nylas 存在的原因!簡而言之,IMAP 是 Mail.app、Thunderbird 和 Mailspring 等電子email客戶端用來從您的電子email帳戶下載email並進行更改(如存檔email或將它們分類到文件夾中)的協議。
IMAP 簡史
IMAP 最初由 Mark Crispin 在 1980 年代在史丹佛大學創建。Crispin 後來搬到了華盛頓大學,在那裡工作了 20 年,致力於IMAP 規範和參考實現。IMAP 規範以“徵求意見”或 RFC 的形式出現,它基本上是一份備忘錄,描述瞭如何實施已被 Internet 工程任務組作為標准採用的協議。RFC 可能會被修改以進行澄清或更改,而當前描述 IMAP 的 RFC 是2003 年發布的RFC3501。沒錯:大多數email客戶端用於同步電子email的協議已經超過 15 年了!
IMAP 最初的設計目的是作為舊協議 POP 的更好替代方案,其目標是“允許像本地郵箱一樣操作遠程郵箱”——具體來說,POP 的操作模式是將email下載到本地電腦並從伺服器刪除,如果您使用多台電腦,這使得管理您的email變得困難。在以前的大型電腦時代,這不是問題,但隨著個人電腦變得越來越普遍,您可能在家裡和工作中都有一台 PC,並且想從任何一個地方瀏覽您的電子email。
IMAP 的原始版本已失傳,而IMAP2(1988 年發布)是第一個將其納入標準的版本。IMAP 的第一個版本僅支持“線上”操作:它假定您的email客戶端在查看或修改email時將連接到伺服器。您無法使用它在本地同步郵箱副本,然後在重新連接時更新本地副本,因為訊息僅由“序列”號標識,並且序列號在客戶端會話中不持久。可以想像,在那些日子裡,人們總是認為,每當您想查看電子email時,一定要擁有可靠的網路連線。這是因為以前的大型電腦和系統的計算本質上是直接登錄到伺服器機器,
快進幾年到撥號時代,很明顯,不斷佔用您的電話線以便您可以閱讀您的電子email並不會減少輸入對“斷開連接”操作的支持,這在 1994 年隨著IMAP4的引入而被固定到 IMAP 。該協議的修訂添加了持久訊息標識符(稱為“UID”)和一個完整的規範草案,解釋瞭如何同步所做的更改本地緩存數據到使用 IMAP 命令存儲在伺服器上的數據。稍後我們將對此進行更多討論,但隨著時間的推移,協議的這種演變是在現代實現 IMAP 客戶端很複雜的主要原因,因為斷開連接的操作是現代應用程序的必需功能。
基本 IMAP 協議自 1996 年以來一直保持不變,此後所有新功能都在協議的可選擴展中實現,其中一些已成為標準——但即使是最常見的擴展,在電子email服務提供商之間的採用仍然存在很大差異。
IMAP 的工作原理
現在您已經了解了該協議的一些歷史,我們將以交互方式向您介紹它的工作原理。我們將連接到一個電子email帳戶,列出郵箱中所有可用的文件夾,然後下載一條訊息。在此過程中,我們將識別和解釋協議的相關部分,以了解正在發生的事情。
只要您可以存取電腦、openssl命令行實用程序和支持 IMAP(包括 Gmail)的電子email帳戶,您就可以按照我們的協議進行操作。
TCP、HTTP 和 IMAP
許多現代客戶端-伺服器協議發生在 Web 瀏覽器和伺服器之間,或者應用程序和 API 之間。這些 API 都是在基本協議 HTTP(“超文本傳輸協議”)之上實現的,它定義了不同類型請求的語義——GET、PUT、POST 等。HTTP 反過來又在較低級別的之上實現稱為 TCP(“傳輸控制協議”)的協議,它簡單地保證訊息包可靠地傳遞到目的地。
IMAP 與 HTTP 一樣,是在 TCP 之上實現的——它定義了不同類型請求的語義,稱為 IMAP 命令。IMAP 通常比 HTTP 簡潔得多,後者是 90 年代初期 IMAP 的關鍵,因為網路連接的頻寬非常低。
IMAP 讓我們一步一步來操作
在家中跟隨您的電腦通過鍵入命令,並在相關的地方添加您的電子email帳戶的詳細訊息。請注意,如果您使用的是 Gmail,您可能需要禁用針對“不太安全的應用程序”登錄的保護功能才能正常工作。
任何客戶端需要做的第一件事就是在特定端口上與遠程伺服器建立連接。這些端口可能會有所不同,因為email伺服器首先接受純文本連接,然後添加了對安全加密連接的支持。您通常可以通過查看他們的幫助文章找到您的提供商的設置。例如,在這裡可以找到 Gmail 的設置。
設置好建立安全連接了嗎?
在命令行上,我們可以使用openssl命令行實用程序進行連接。我們必須使用openssl而不是telnet,否則我們最終可能會通過網路以明文形式發送敏感數據,例如密碼和私人電子email,從而使它們容易被攻擊者嗅探到網路。openssl通過建立安全連接並在繼續之前驗證遠程伺服器的證書來保護我們的連接。
在上面的命令中,s_client意味著我們正在調用openssl的功能來充當基本的 SSL/TLS 客戶端,-connect指定要連接的主機名和端口,並-crlf在您在電腦中按“Enter”時轉換為 IMAP 預期的字符伺服器正確結束一行。連接後,openssl檢查伺服器上的 SSL/TLS 證書以確保我們的連接沒有被劫持,並且 IMAP 伺服器顯示一個問候語,表示它已準備好接收來自客戶端的請求。
命令
IMAP 命令通常如下所示:
<標籤> <命令> [
我們將在一個名為 CAPABILITY 的示例命令的上下文中解釋這些部分。CAPABILITY 允許您詢問伺服器它支持哪些 IMAP 擴展:
我們剛剛與 IMAP 伺服器通信!讓我們解釋一下我們發送了什麼以及我們返回了什麼。
命令類似於 HTTP 中的請求。它告訴伺服器做某事或向它詢問訊息。在這種情況下,我們要求伺服器告訴我們它支持哪些功能。更多關於功能的訊息。
CAPABILITY 命令沒有參數,但如果有,我們只需在命令名稱之後和按回車鍵之前輸入它們。
標記
標籤(tag1在本例中)由客戶端生成,伺服器將標籤發送回命令響應的最後一行。標籤可以包含任何字母數字字符甚至一些符號,並且不需要包含升序整數——儘管這可能是生成唯一整數的便捷方式。以開頭的伺服器響應*稱為未標記響應,這意味著它們不代表客戶端請求的命令的完成。在這種情況下,未標記的響應是能力列表,而標記的響應是OK命令的狀態和伺服器程式設計師留下的有趣訊息。
這種標記能力意味著伺服器可以同時處理來自同一連接上的客戶端的多個請求,並通過發回適當的標記來指示它們的完成。在實踐中,許多客戶端不支持這種發送並發請求的能力,而只是在發送命令後阻塞等待數據到達打開的套接字。
能力
那麼這個“能力”列表到底是什麼意思呢?“能力”是伺服器支持的功能的簡稱。其中一些功能,例如AUTH=PLAIN,包含在基本 IMAP4rev1 規範中,而其他功能則由擴展啟用。擴展允許將新命令添加到 IMAP 協議而不需要新版本的協議規範。在登錄之前,伺服器上支持的功能列表將與登錄後的功能不同,因為列出與註銷或登錄狀態無關的功能幾乎沒有用處。
驗證
以下是向 IMAP 伺服器驗證email帳戶的方法:
伺服器響應
如您所見,伺服器響應並不總是說OK. 以下是允許伺服器響應命令的快速指南:
OK=成功!
NO=失敗!
BAD=我沒聽懂你說的!
如果需要,伺服器可以在響應後自由添加更多訊息,例如[AUTHENTICATIONFAILED] Invalid Credentials (Failure).
如您所見,成功登錄後,伺服器再次向客戶端發送功能列表,顯示登錄後哪些新功能已解鎖,哪些舊功能已消失。此列表中的一些標準擴展是UIDPLUS,MOVE和CONDSTORE. Gmail 支持但其他地方不支持的一些自定義擴展是ESEARCH和X-GM-EXT-1.
列出文件夾
好的,現在我們已經登錄了,讓我們嘗試做一些有用的事情。首先,讓我們檢查郵箱中存在哪些文件夾:
哎呀!如您所見,如果您對命令的參數錯誤,伺服器將拒絕它並說BAD客戶端!
文件夾標誌
在這裡,我們可以看到郵箱中存在的文件夾層次結構。文件夾有特殊的標誌,用括號表示。其中一些標誌對於遍歷文件夾層次結構很有用,例如HasNoChildren和HasChilden,而其他標誌用於表示給定文件夾的特殊特徵,例如它是否包含草稿 ( Drafts) 或已發送訊息 ( Sent)。這些標誌允許客戶端根據郵箱調整他們的行為,並執行諸如將發送的訊息保存到正確的文件夾之類的操作,無論用戶郵箱使用哪種語言。
會話
好的,現在讓我們閱讀一些電子email。SELECT首先,因為 IMAP 連接是有狀態的,所以我們需要使用以下命令在我們關心的文件夾上打開一個會話:
伺服器在這裡向我們發送了很多訊息!會話是 IMAP 工作方式的關鍵組成部分,會話從您SELECT使用郵箱一直持續到您使用UNSELECT它、SELECT另一個郵箱或註銷。
- 郵箱中email使用的活動標誌列表
- 可用於郵箱中email的受支持標誌列表
- UIDVALIDITY- 稍後再詳細介紹
- 郵箱中的email數量
- 郵箱中有多少“最近”訊息,這意味著有多少訊息帶有Recent標記
- “預測的下一個 UID”
- 一個HIGHESTMODSEQ價值——稍後會詳細介紹
其中一些項目需要更多解釋。首先,UID。
UID 和序列號
提醒:很久很久以前,有 IMAP2,在 IMAP2 中,訊息由序列號標識。序列號實際上就是這樣:單調遞增的數字,郵箱中的每條訊息都有一個:
每次選擇郵箱時,如果有新email,就會有更多的序列號。如果您移動訊息並開始新會話,則分配給訊息的序列號可能與舊會話中的序列號不同。
如果您所做的只是連接、線上閱讀email並斷開連接,那麼這個非常簡單的方案非常有效。但是,如果您想連接,在本地下載所有SEO 相關的email以供離線存取,然後稍後重新連接並讓您的客戶端將其本地狀態與伺服器上的狀態同步,則它不起作用——因為這些非持久序列號沒有t 允許客戶端將本地郵箱狀態映射到遠程郵箱狀態,因為每一端的訊息可能有不同的 ID!
輸入 IMAP4 和 UID。只要 UID(唯一 ID)位於同一文件夾中並且伺服器的 UIDVALIDITY 整數沒有增加,它就對訊息是持久的。因此,當客戶端在郵箱上啟動新會話時,它必須檢查 UIDVALIDITY 並將其與本地緩存值進行比較,如果伺服器的 UIDVALIDITY 更高,則必須丟棄所有緩存的本地 UID 並從頭開始重新同步。但除此之外,它可以自由地將其本地緩存數據與伺服器上的數據進行比較,並且只同步更改。
為了保持向後兼容性,IMAP4 支持序列號和 UID,您可以通過在返回訊息標識符的任何命令前加上以下前綴來請求 UID UID:
正如您所看到的,與序列號不同,UID 不能保證以 1 為增量增加——當email到達並在文件夾之間移動時,分配給郵箱的 UID 會出現間隙。
有狀態
當我們在這裡時,關於狀態性的問題:一般來說,狀態性不是協議中理想的特性。狀態性使得在 IMAP 中使用連接池變得更加棘手,因為該SELECT命令可能非常慢,並且每次池使用者簽出新連接時,它都需要確保選擇了正確的郵箱。有狀態還意味著應用程序代碼必須跟踪狀態並確保它與連接的實際狀態同步,否則每次需要訊息時都會讓另一個客戶端-伺服器來回切換。通常,使用無狀態協議編程比使用有狀態協議更容易。
獲取訊息數據
好的,讓我們終於從訊息中下載數據!
IMAP 提供了許多允許客戶端請求有關訊息的部分數據的旋鈕,包括訊息的大小、標誌(例如Seen表示該訊息已被閱讀,以及Answered表示該訊息已被回复)、單獨的標頭和單獨的 MIME MIME 訊息中的部分,它允許客戶端通過僅下載他們需要的數據來優化他們的頻寬使用。例如,客戶端可以快速下載文件夾中所有訊息的基本標頭,以便生成訊息列表供用戶瀏覽,然後按需獲取訊息正文。
在結束之前,我們還想介紹幾個關於 IMAP 的概念。
不請自來的回覆和空閒
在前面的示例中,您可能已經註意到一些奇怪的未標記響應:
* 55 EXPUNGE * 54 EXISTS
這實際上是關於一條訊息從郵箱中消失而另一條訊息在我們打開郵箱時出現的通知。在 IMAP 中,伺服器可以隨時將這些未經請求的訊息發送到連接的客戶端。還有一種可以放入 IMAP 連接的模式,稱為IDLE,它本質上僅用於處理有關郵箱更改的通知,並且客戶端經常使用它來快速同步傳入的新訊息。
斷開同步
斷開連接的同步允許電子email應用程序在面對飛機 wifi 和不良的蜂窩連接時正常工作。它與其說是 IMAP 的一流特性,不如說是您可以在協議之上構建的東西,需要付出巨大的努力,因為 IMAP 最初並不是為了支持它而設計的。
以原始形式與 IMAP4 進行斷開同步的方法非常簡單:您必須獲取每個文件夾在本地擁有的 UID 列表,並將其與伺服器上文件夾中當前的 UID 列表進行比較,並且根據差異獲取新訊息並刪除舊訊息。隨著郵箱的增長,客戶端處理變得越來越複雜,後來的擴展如CONDSTORE 和 QRESYNC改進了斷開連接重新同步的流程。但是即使有了這些擴展,實現斷開連接重新同步的過程也很複雜——即使在今天,許多 IMAP 伺服器實現也不支持更新的擴展,因此通用客戶端必須包含不同伺服器的條件邏輯。如何在 IMAP 之上實現斷開同步的一般參考是RFC4549。
概括
好吧,我們做到了!通過閱讀本文,您了解了 IMAP 的歷史和主要組件,這是一種用於存取和操作遠程郵箱的開放協議。我們已連接到 IMAP 伺服器,登錄到我們的電子email帳戶,列出遠程伺服器上的文件夾,並下載訊息數據。這正是您瀏覽郵箱時在電子email應用程序中發生的事情。我們還了解到,由於 IMAP 多年來的發展方式,斷開連接的同步對於客戶端來說是相當複雜的,這就是我們構建delta API以簡化流程的原因。
下一次,我們將深入研究另一個重要的電子email開放協議:SMTP,它是電子email的發送方式。我們希望您能留下來,一起享受樂趣!