我的郵箱客戶端程序Popmail


05年的時候寫了一個郵箱客戶端程序。當時主要目的是研究POP3和SMTP協議,同時鍛煉自己的網絡編程能力。當然了,如果自己寫的郵箱客戶端能夠滿足自身的日常工作需要,而不是頻繁的登錄不同的網頁郵箱,那就再好不過了。時隔16年,給popmail增加了SSL(TLS 1.2)會話,感覺安全了一點,郵件再也不用裸奔了,看到16年前的代碼,非常感慨,隨便寫寫,特此紀念。

POP3和SMTP這兩個協議本身都很簡單,但實現起來還是有很大難度,尤其是你希望把它寫的健壯、易用或者產品化的時候。
比如HTTP協議也很簡單,寫個簡單的socket程序通過GET命令就能把網頁給down下來。但接收大的網絡資源就復雜多了。何時解析、如何解析完整的HTTP響應頭,就是個頭疼問題。因為你不能指望一次recv就能接收完所有響應數據,也不能指望服務器先發送HTTP響應頭,然后再發送響應數據。只有把HTTP響應頭徹底解析了,我們才能知道后續接收的Body數據有多大,何時才能接收完畢。
比如通過響應頭的"Content-Length"字段,才能知道后續Body的大小。這個大小可能超過了你之前開辟的接收數據緩存區大小。當然你可以在得知Body大小后,重新開辟一個與"Content-Length"一樣大小的緩存區。但這樣做顯然是不明智的,比如你get的是一部4K高清藍光小電影,藍光電影不一定能get到,藍屏電腦倒有可能get到。。。。。。
遇到服務器明確給出"Content-Length"字段,是一件值得額手稱慶的大喜事,但不是每個IT民工都這么幸運。如果遇到的是不靠譜的服務器,發送的是"Transfer-Encoding: chunked",那你就必須鍛煉自己真正的解析和組織能力了。這些分塊傳輸的數據,顯然不會以你接收的節奏到達你的緩沖區,比如先接收到一個block塊大小,然后是一個完整的塊數據,很有可能你會接收到多個塊或者不完整的塊,這就需要你站在宏觀的角度把他們拼接起來。

如果你遇到的是甩的一米的服務器,它不僅給你的是chunked,而且還增加了"Content-Encoding: gzip",那么你就需要拼接后進行解壓,當然你也可能遇到的是"deflate"壓縮。
題外話:我一直困惑的是HTTP協議為何不是對分塊數據單獨gzip壓縮然后傳輸,而只能是整體gzip壓縮后再分塊傳輸。這個對大資源傳輸很關鍵,比如上面的4K高清藍光小電影,顯然不能通過gzip+chunked方式傳輸,土豪服務器例外。
當然你也可以用開源的llhttp來解析收到的http數據,從而避免上述可能會遇到的各種坑。最新版本的nodejs中就使用llhttp代替之前的的http-parser,據說解析效率有大幅提升。為此我下載了nodejs源碼,並編譯了一把,這是一個快樂的過程,因為你可以看到v8引擎,openssl,zlib等各種開源庫。。。。,不過llhttp只負責解析,不負責緩存,因此你還是需要在解析的過程中,進行數據緩存。這是我寫的通過llhttp解析http響應數據的案例:

基於SSL(TLS)的HTTPS網頁下載——如何編寫健壯的可靠的網頁下載

這里面有我封裝好的sslite.dll庫可以方便的幫助你進行SSL客戶端通信,目前支持TLS1.2,我的popmail因為使用sslite庫才把衣服穿上避免了裸奔。

花開兩朵各表一枝,還是回到POP3/SMTP上來。
相較而言,實現POP3要比實現SMTP復雜,這個復雜不是指協議本身有多復雜,也不是POP3比SMTP多了幾個命令,而是指用代碼實現協議的難度,尤其是解析難度。POP3是接收協議,SMTP是發送協議,總體而言發送比接收要簡單很多。
因為發送數據的時候你可以耍流氓,不管服務器的死活,可以變態的1個字節1個字節發數據,也可以忽長忽短的發數據,從而讓服務器猜不透你,直到把數據全部發送完畢。但接收數據就復雜多了,比如上面提到的如何接收HTTP響應數據,現在需要你來面對猜不透的服務器了,因為服務器也可能耍流氓。

早期的email協議只支持ASCII碼這種純文本傳輸,后來隨着富文本的出現,圖像、文件也迫切需要通過email進行傳輸。這時MIME協議誕生了,MIME的出現更多的是一種向下兼容的無奈,而不是革命。通過對二進制數據或非ASCII碼數據進行base64或quoted-printable編碼,來實現純ASCII碼的傳輸。顯然這種方式會讓你的郵件體變大,傳輸效率下降。
傳輸下降只是一方面,解析MIME格式的郵件也是一件頭疼的事,對於"Content-Type: multipart/mixed"來說,需要根據boundary值,將不同mixed part郵件體給解析出來。同時你要面臨各種編碼格式,否則你的郵件標題、附件名稱就會出現亂碼,比如這種:"=?gb2312?B?=",比如這種:"=?gb2312?Q?",又比如這種"=?unicode-1-1-utf-7?q?"。。。。,當時還還遇到過"Content-type: message/rfc822",或者"content-disposition : inline"字段,完全處於懵B狀態。05年的時候,網上資料特別少,也不認識張小龍,張小龍不僅是微信之父,更是Foxmail之母。如果當時能聯系上,可能會發微信咨詢一下,或者qq加好友哦。。。。。。,但在當年只能連蒙帶猜,遇到一次亂碼就猜測着解析看看,敢於在踩雷中解析,在解析中踩雷。

當年寫郵箱客戶端使用的是經典的VC6.0,也許很多90后、00后、10后沒有聽說過它,沒關系,沒關系,下面就是用VC6編寫的popmail,不高調,不奢華,一眼就能看出vc6的影子。它支持多郵箱賬戶、郵件自動接收、快速查看郵件列表、遠程刪除郵件,自動回復等人民群眾喜聞樂見卻基本不用的功能。

Popmail客戶端下載地址

1、主界面

2、多郵箱賬戶配置

3、賬戶配置

4、自動規則設定

5、接收郵件

6、快速查看

為什么不能把界面寫的多姿多彩呢?VC6寫的程序就是這樣的,古朴大方。。。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM