前言廢話:很早以前就打算寫博客,可是一直由於在創業,抽不出時間。現在朝九晚五,打算利用晚上的時間,開始寫博客。html
本類博客是一個系列,將完整的講述純手工開發一個郵件服務器的過程,並附有關鍵代碼。演示地址 做者郵箱: longge93@cliyun.comjava
這一篇先說整個系統的架構。郵箱系統主要分爲幾個模塊,根據消息發起與傳遞的對象不一樣。我把它們分爲如下幾類:web
客戶端(手機、foxmail等)發起,目的地是各大郵箱服務商的服務器。(協議:SMTP,端口:25)redis
各大郵箱服務商的服務器發起,到該郵件的收件人所在郵箱服務商的服務器。(協議:SMTP,端口:25)算法
有客戶端請求,從郵箱服務商服務器商拉取郵件信息或內容。(協議:POP、IMAP,端口:110等)數據庫
以上步驟,按照序號依次就是一封郵件從你手機或電腦發出,到達對方終端的過程。服務器
因此,若是要完成一個郵箱服務器,第一步就是實現各類協議。所謂協議,就是在創建socket鏈接以後,按照事先規定好的「暗號」,傳遞信息。具體每種協議的規矩,百度能夠輕鬆知道。也可訪問協議制定機構的網站獲取。網絡
而後咱們來整理一下,實現一個郵件服務器,咱們須要幾個模塊:架構
郵件接收器:在服務器上創建socket服務端,監聽25端口。接收其餘郵件服務器經過SMTP協議發過來的郵件。一般垃圾郵件過濾就是從這裏開始的。socket
郵件發送器:當有用戶要發送郵件時,在服務器上創建socket客戶端,鏈接到目的郵箱的郵件接收器,經過SMTP協議發出郵件。
POP、IMAP服務器:收到郵件後,還得讓客戶經過客戶端能拉取到,這個模塊的做用就是從數據庫讀取已經收到的郵件,傳遞給客戶端。不能主動推,只能被動的等待拉取。若是要主動推,能夠研究一下微軟的exchange協議。
郵件轉發器:當客戶要經過手機等客戶端發送郵件時,會先把郵件經過socket傳遞給你的服務器,而後再由郵件發送器發出。那麼,郵件轉發器的做用就是從客戶端手裏接收郵件,傳遞給發送器發送。該過程使用SMTP協議。
以上幾個模塊均使用JAVA實現。那麼第一個問題來了,當用戶使用WEB端,在網頁上寫好一封郵件,當他點擊發送後,咱們如何觸發JAVA寫的郵件發送器呢?這時候就要引入咱們的消息中間件模塊了。
消息中間件模塊是基於redis的,消息發佈、訂閱機制。阿里雲的KVstore對其作了封裝。簡單的說,就是你能夠建立一個管道,這個管道有不少不少分支,你往這個管道里丟什麼東西,全部分支都將及時收到這些東西。
利用消息中間件,咱們經過WEB端發佈管道,JAVA發件器訂閱該管道。便可實施觸發郵件發送動做。
第二個問題是郵件附件、郵件原EML文件的保存問題。直接保存成文件對服務器壓力很大,並且不利於查詢等動做。因此我把這些所有推到阿里雲的OSS存儲上去。把存儲路徑保存下來。
第三個問題是郵件EML文件的解析、生成的問題。衆所周知的javamail遇到中文後,其實蠻多問題。須要慢慢優化,作到更高的效率和正確率。
第四個問題是如何經過WEB端上傳大附件。一般的解決辦法是安裝控件,我這裏採用百度的開源項目webuploader,該項目容許用戶選擇flash和HTML5兩種方式之一,來上傳附件。而且具備大文件切片、文件上傳前HASH驗證等功能。
第五個問題是垃圾郵件的過濾問題,參考了不少過濾算法後,打算從神經網絡算法延伸一套垃圾郵件過濾算法出來。具體的後面慢慢講。
第六個問題是如何防止郵件攻擊。天天都有大量的垃圾IP試圖發送過來,若是每次都在創建socket以後再經過算法判斷該IP是否在黑名單等等,太浪費資源。應該自動將其加入防火牆,之後就不用再處理該IP了。
正文從下一篇開始~