電子郵件的組成:信封、首部和正文
電子郵件由三部分組成,下圖是 Client 發送的整個數據:
-
信封(envelope)
信封是 MTA 用來交付的,在上例中由兩個 SMTP 命令指明;
MAIL From: rstevens@sun.tuc.noao.edu
RCPT To: estevens@noao.edu -
首部(header)
首部由用戶代理使用,上例中可以看到 9 個首部字段:Recived、Message-Id、From、Date、Reply-To、X-Phone、X-Mailer、To 和 Subject
(以 X- 開頭的是用戶定義的字段,其他是由 RFC 822 定義的,詳見 4.1 節) -
正文(body)
正文是發送用戶發給接收用戶報文的內容,RFC 822 指定正文為 NVT ASCII 文字行,用 DATA 命令發送的各行都必須小於 1000 字節
用戶接收我們指定為正文的部分,加上一些首部字段,並把結果傳到 MTA;MTA 加上一些首部字段,加上信封,並把結果發送到另一個 MTA
(更多實現細節,詳見 RFC 2821)
用 TCP 進行的郵件交換是由報文傳送代理 MTA(Message Transfer Agent)完成的。
TCP/IP 交換電子郵件示意圖:
郵件基礎協議
郵件基礎的網絡協議有以下三個,一般我們使用 SMTP 協議來發送郵件,POP3 和 IMAP 協議來接收郵件(從服務端接收郵件至客戶端)
- 下表中 IMAP 協議支持發送郵件並不是郵件投遞,而是通過 append 指令將郵件從客戶端上傳到服務端
協議 | 工作端口(括號內為 SSL) | 支持發送郵件 | 支持接收郵件 |
---|---|---|---|
SMTP | 25(465) | True | False |
POP3 | 110(995) | False | True |
IMAP | 143(993) | True | True |
SMTP
兩個 MTA 之間通過 NVT ASCII 進行通信,客戶向服務器發出命令,服務器用數字應答碼和可選的人可讀字符串進行響應
下圖是 SMTP 的一個交互會話過程:
- 鍵入 mail -v 啟動用戶代理; 鍵入 subject(主題)和正文
- 主動打開 port:25 ;等待從 Server 返回的問候報文(應答碼220)
- HELO:標識自己(參數必須是合格的主機名)
- MAIL:標識報文發起人
- RCPT:標識接收方(可發多次,標識多個接收方)
- DATA:郵件報文內容
- QUIT:結束郵件交換
下圖是發送方 SMTP(Client)和接收方 SMTP(Server)之間的一個 SMTP 連接:
SMTP 指令
最小SMTP支持 8 個命令,除了上述 5 個命令還有:
- RSET:異常中止當前的郵件事務並使兩端復位。丟掉所有有關發送方、接收方或郵件的存儲信息
- VRFY:使客戶詢問發送方以驗證接收方地址,而無需向發送方發送郵件(通常用與管理員查找郵件交付差錯中使用)
- NOOP:強迫服務器響應一個OK應答碼(200)
(另外還有一些附加可選命令)
SMTP 用半雙工的形式使用 TCP,客戶發送一個命令后停止等待應答;實際上 Client 可以一次發多個命令,稱為流水線技術(pipelining)
如果使用了這種技術,Client 則不能丟棄報文直到所有的應答都已檢查過,確認報文被服務器接收了
使用 Telnet 模擬 SMTP 發送郵件
POP3
POP3 協議相對 SMTP/IMAP 要簡單一些,協議的指令也不多
POP3 的生命周期
POP3 命令以 CRLF 對結束,特定命令多行響應,以 CRLF.CRLF 結束
在服務器打開郵件后,它為每個消息指定一個消息號,並以八進制表示每個消息的長度。第一個消息被指定為 1,第二個消息被指定為 2,以此類推,第 N 個消息被指定為 N
在POP3命令和響應中,所以的消息號和長度以十進制表示
AUTHORIZATION
- USER :客戶確認身份(參數:username)
- PASS :身份確認完成
- QUIT :終止 POP3 會話
- APOP :用於替代 USER 和 PASS 命令,它以 MD5 數字摘要的形式向POP3郵件服務器提交帳戶密碼(參數:用戶名/密鑰)(該命令實現可選)
安全性:每個 POP3 會話都以 USER/PASS 互換開始,導致了用戶名和口令在網絡上的顯式傳送,當服務連接頻率變大、時間間隔小,就會加大了泄密的可能
(使用APOP:隨着密鑰長度的增加,解讀的難度也會上升)
TRANSACTION
操作狀態下的命令:
- STAT :查詢郵箱中的統計信息(郵件數量和所有郵件大小)
- LIST :列出郵箱中的所有郵件信息(消息號/大小)(參數:MSG 列出對應消息號的郵件信息)
- RETR :獲取某封郵件的內容(參數:MSG)
- DELE :將某封郵件標記為刪除(參數:MSG)(被標記的郵件直到當前會話進入 UPDATE 狀態才被刪除)
- NOOP :檢測連接狀況
- RSET :取消刪除標記
UPDATE
當客戶在 AUTHORIZATION 狀態下發送 QUIT 命令后,會話進入 UPDATE 狀態
如果會話因為 QUIT 命令以外的原因中斷,會話並不進入 UPDATE 狀態,也不從服務器中刪除任何信件
(更多實現細節,詳見 RFC 1939)
IMAP
IMAP 協議通過 port:143 來提供電子郵件的收發服務,和 POP3 被用來提供電子郵件客戶端服務(從服務器檢索電子郵件)
相對於 POP3,IMAP 支持多個電子郵件客戶端同時管理郵箱,並可以通過郵件的標簽/狀態,監測到其他用戶對於郵件的操作
IMAP 還支持在線/離線兩種操作模式,客戶端可以獲得郵件副本存儲在本地
標志消息屬性
與郵件關聯的有一個或多個 token list,將 flag 添加至列表可以設置郵件的屬性,每個 flag 可以設置為永久的或臨時的(當前會話)
\Seen | 郵件已閱讀 |
\Answered | 郵件已回復 |
\Flagged | 郵件被標記為緊急/特別關注 |
\Delete | 郵件被標記刪除(to EXPUNGE) |
\Draft | 郵件被標記為草稿 |
\Recent | 郵件最近到達該郵箱(本次會話是首次收到當前郵件通知) |
具體的實現與服務器相關
狀態和流程圖
Client 和 Server 建立好連接后,IMAP 連接處於四種狀態之一
最初的狀態在服務器的 greeting 報文中標識,客戶端在不當狀態中嘗試的命令服務器都將以 BAD/NO 響應(取決於實現)
- Not Authenticated State :未經認證的狀態,連接啟動時進入該狀態,除非已進行預驗證
- Authenticated State:認證狀態,可選擇郵箱進行訪問
- Selected State:選定狀態,已選擇一個郵箱訪問
- Logout State:退出狀態,連接正在終止(LOGOUT 命令)
服務器必須發送 BYE 響應來關閉連接,同樣的,客戶端應該發送 LOGOUT 命令來關閉連接
如果服務器檢測到客戶端單方面關閉了連接,則可以省略 BYE 響應
IMAP 命令
下面羅列一些常見的 IMAP 命令
客戶端命令 —— 任何狀態
- CAPABILITY:查詢服務器實現的功能
- NOOP:檢測連接
- LOGOUT:終止當前連接
客戶端命令 —— 未經認證的狀態
- STARTTLS:與服務器使用 TLS 進行交互
- AUTHENTICATE:與服務器的認證機制
- LOGIN:鑒權登陸,輸入用戶名與密碼
客戶端命令 —— 認證狀態
- SELECT:選擇郵箱
- EXAMINE:以只讀方式選擇郵箱
- CREATE:創建一個郵箱
- DELETE:刪除一個郵箱
- RENAME:重命名郵箱
- SUBSCRIBE:訂閱指定郵箱
- UNSUBSCRIBE:取消訂閱郵箱
- LSUB:返回訂閱郵箱列表
- APPEND:追加一個State,例如可以保存一封新的郵件
客戶端命令 —— 選定狀態
- CHECK:檢查當前服務器狀態(例如:磁盤,內存等)
- CLOSE:永久刪除所有消息
- EXPUNGE:永久刪除所有消息,與 CLOSE 不同的是,將返回每個消息標識
- SEARCH:類似 find 命令,功能很強大可以按照不同條件搜索郵件
- FETCH:檢索與消息相關數據,例如:獲取正文
- STORE:改變與消息相關數據,例如:設置郵箱已讀、刪除狀態等
- COPY:拷貝指定的消息
- UID:返回 UID 列表用於 FETCH