?? 計費郵件服務器研究與實現.txt
字號:
計費郵件服務器研究與實現
石巖 蔣東興 白冰 戚麗
清華大學計算機與信息管理中心(北京 100084)
jdx@cic.tsinghua.edu.cn
摘要:本文在闡述電子郵件原理、相關網絡協議和軟件的基礎上,提出一種按照流量計費的電子郵件服務器解決方案,并給出該方案的實現模型。
關鍵字:電子郵件,計費,SMTP,POP3
1 前言
電子郵件是Internet服務的重要組成部分。隨著Internet技術日新月異的發展,電子郵件以其方便、快速、廉價和可靠的特點越來越贏得人們的喜愛。現在,電子郵件已經成為學術界、商業界最為流行的一種通信方式,和國外進行學術交流更少不了電子郵件。
在國外,電子郵件服務一般是一次性收取服務費,或者是商業廣告性質的免費服務。但是,在CERNET按照網絡流量計費的大前提下,為公眾提供電子郵件服務時,將不得不考慮流量計費的問題。
本文將從Internet電子郵件原理入手,在闡明相關網絡協議和軟件的基礎上,提供一種按照流量計費的電子郵件服務器解決方案,并給出該方案的實現模型。
2 Internet郵件原理
2.1 Internet電子郵件簡介
為了保證電子郵件系統的正常運行,TCP/IP定義了一組協議,SMTP(簡單郵件傳輸協議)、POP3(郵局協議)和IMAP(Internet消息通道協議)是主要的幾個協議。它們的關系如圖1所示:
圖1 Internet郵件傳送示意圖
圖1顯示了電子郵件從發送到接收的一個單向的典型過程。SMTP和POP3服務器是服務器軟件,它們運行在郵件服務器上。SMTP服務器負責接收待發送的郵件,并發送至目標郵件服務器的SMTP服務器,由該SMTP服務器寫入用戶郵箱。實際上,由于SMTP服務器具有中轉(Relay)功能,它并不區分郵件是來自用戶機(如普通PC)還是其他SMTP服務器。如果用戶想在普通客戶機(沒有SMTP服務器的普通主機)上接收郵件的話,他需要通過POP3協議或IMAP協議從郵件服務器上獲取。不同的是,POP3服務器要求用戶將郵件取回本地的普通客戶機進行維護,而IMAP則可以在服務器上直接維護,例如建立不同的郵件夾等。到目前為止,POP3的使用比IMAP要廣泛的多,下面我們主要介紹SMTP協議和POP3協議。
2.2 SMTP協議
SMTP(Simple Mail Transfer Protocol, RFC 821)是一個用7-bit基本ASCII字符傳送簡單信文的郵件協議。它是一個獨立的用戶級協議,它要求一個可靠的數據通道。在TCP/IP協議中,這個通道是8-bit的TCP數據流,因此SMTP的7-bit字節一律按照最高位為零的8-bit字節進行傳輸。如果要傳送8-bit數據,需要用特殊的調制算法(例如MIME)將其轉為7-bit數據,在接收端再用相反的算法將其復原。
SMTP的一個重要特點是“中轉”(Relay)。一般地,用戶可以選擇任意一臺SMTP服務器(如A)來發送郵件(只要能與該服務器建立傳輸層連接),若該服務器與目標SMTP服務器B可以建立直接連接,則郵件將被直接送至目標服務器B;若不能建立直接連接,該SMTP服務器將向其他所知的SMTP服務器詢問路由,假如有一臺SMTP服務器C可以與目標建立直接連接,或知道通向目標的路由,則郵件被轉至服務器C,由服務器C向目標B轉發。不管是從客戶機到服務器的發送還是服務器間的中轉,SMTP使用同一套指令來進行連接和數據的接收發送,從而使得整個過程清晰簡捷。
Sendmail 是由美國加州大學開發的一個基于UNIX的共享SMTP服務器軟件,它支持多種UNIX的CLONE平臺,如Solaris、Linux等,并且兼容很多其他類型的電子郵件系統,如UUCP等。Sendmail模型如圖2所示。
圖2 Sendmail模型
圖2中,客戶方sender與SMTP服務器Sendmail建立連接,將郵件送交Sendmail服務器;Sendmail按照郵件的不同類型,送交不同的郵件發送程序(稱之為mailer)進行發送,例如SMTP mailer,UUCP mailer等等。Sendmail提供一種Local mailer程序mail.local,對郵件目標地址進行認證,若合法則將郵件寫入用戶的郵箱,否則將郵件退回。
2.3 POP3協議
POP3(Post Office Protocol version 3, RFC 1939)定義了客戶機從郵件服務器上獲取郵件的一個簡單的方法,它通過一組簡單指令和應答實現與用戶的交互操作。例如,用戶通過user指令和pass指令實現身份認證,認證成功后可以通過retr指令收取郵件等。
加州大學針對SMTP服務器Sendmail,開發了一個共享的POP3服務器軟件popper,該軟件具有與Sendmail相同的支持多平臺和多種類型郵件的優點,并且在設計上采用結構清晰的狀態機模型,其模型如圖3所示。
圖3 popper狀態機模型
如圖3,系統初始狀態為AUTH,身份認證通過后進入TRANSACT狀態,系統郵箱被拷貝至一個臨時文件。這一狀態中,用戶可以通過list命令列出郵件頭的信息,通過retr指令將指定郵件取回本地機,通過dele命令將指定郵件標識為刪除,等等。接到quit指令后,進入UPDATE狀態,系統將沒有被標識為刪除的郵件反拷貝回系統郵箱,然后進入HAULT狀態退出。
3 計費郵件服務器要解決的問題
3.1 計費信息獲取
1. 流量。流量即郵件的長度,它是我們計費的基準。因為每一個來件都交由mail.local遞送,所以在mail.local里可以容易地得到每個郵件的長度;另外,用戶取信時與popper連接,popper要對信箱中每個郵件制作一個消息頭(包括郵件的長度,在郵箱中的位置,是否被檢索過等信息),同時也會獲得郵箱的總長度,因此在popper中也可以獲得流量,但程序上的開銷會大一些(例如為了避免重復計費,在每次收信時需要判斷郵件是否被檢索過)。
2. 郵件的來源。目前在我國四大網(教育網CERNET,科學院網CASNET,電子部金橋網CHINAGBN和CHINANET)內,網絡流量是不計費的,因此應當根據郵件源地址是免費區域和非免費區域按照不同的標準計費。這需要獲取郵件的源地址,源地址在mail.local和popper中都可以獲得。此外,對于Internet上一些反動或黃色站點的來信,應當禁止寫到用戶信箱里去。由于這個原因,我們應當在mail.local中就獲得來信地址。
3. 用戶取信的時間和客戶機IP地址。這兩種信息主要用于管理,例如,我們可以通過IP地址為用戶限制可取信的客戶機范圍,從而可保護用戶的郵件不被他人獲取。另外,將這兩條信息記入帳表后可為用戶的查詢提供極大的方便。這兩種信息只能在popper中獲得。
從上面的分析可以看到,我們需要一個基于mail.local和popper的綜合解決方案,才能充分利用已有資源,在開銷盡可能小的前提下獲得以上信息。
3.2 帳戶管理問題
1. 為非UNIX用戶提供郵件服務。每一個UNIX的用戶都有一個郵件帳戶,Sendmail的缺省的帳戶管理也是面向這些用戶的,它需要對UNIX用戶進行身份認證。例如,mail.local獲得了一封給jdx的來信,要使用UNIX系統調用對“jdx”進行認證,如果系統沒有一個叫做jdx的UNIX帳號,將返回空值,來信將被退回。在popper中除了以上步驟外,還要檢查用戶輸入的密碼與系統中密碼是否相同。
這樣的機制不適合對大量郵件用戶的管理。首先,每增加一個郵件用戶就需要建立一個UNIX帳號,用戶所享受的將不僅是電子郵件服務,給用戶權限管理帶來不便;其次,對于大量帳號的快速檢索也成問題。另外,所有的郵箱文件存放在一個目錄下,例如/var/mail或/var/spool/mail下,在文件過多時,系統效率降低,還可能給管理帶來麻煩。
因此,我們需要建立自己的帳戶管理機制。這個機制應當能夠實現:
1) 支持沒有UNIX帳號的普通郵件帳戶;
2) 用戶的郵箱文件應能分類寫入不同的目錄;
3) 能夠對用戶信箱按照用戶名進行快速檢索。
2. 用戶表的管理。用戶表包括的信息有帳號,加密的口令,真實姓名,狀態(正常,欠費,不受歡迎等等)。為了提供快速檢索,用戶表應當是一個排序的表。
用戶表是一個動態的表,每天都可能有新用戶加入,也可能有老用戶注銷。而且,計費郵件服務器要能根據用戶的費用情況自動修改用戶的權限。例如,用戶申請帳號時需要預付一定數量的使用費,此時用戶為正常用戶;一旦使用超過限度(收取了大量郵件),系統將其置為欠費用戶,暫時禁止取信,在用戶補交足夠的費用時,系統恢復其取信權利。因此,用戶表應當及時更新。
為了減少管理難度,提供自我服務,應當向用戶提供隨時修改口令的機制。另外,用戶表應當有一個安全可靠的后備,在用戶表出現故障時能夠及時地修復。
3.3 記帳的問題
用戶每次取信的相關信息,例如時間、地點(IP)、取了多少封信、長度是多少等,都應當記錄下來。作為專用郵件服務器,一般都要為大量的用戶提供服務,假設有20000用戶,每人每天取信一次。這樣,一天大約有兩萬條記錄,這些記錄基本集中在從早上8點到晚上10點的14個小時(3600*14=50,400秒)內,即平均每2.5秒一條記錄。在這樣的情況下,同一時刻處理好幾條記錄的可能性非常大。如果將記錄實時地交給數據庫處理,將加重數據庫負荷,延長響應時間,并增加丟失數據的可能性,嚴重時甚至可能導致系統崩潰。
一個解決辦法是,每次的記錄寫入一個日志文件,每天在數據庫負荷最低的時候,對這個文件進行批處理。
4 計費郵件服務器的實現
4.1 解決方案
針對上面提出的問題,我們可以設計如下解決方案:
1. 將計費郵件系統分為兩個模塊,郵件處理模塊和數據庫計費模塊。郵件處理模塊按照用戶表進行常規的郵件收發和計費日志記錄;數據庫計費模塊讀計費日志、處理帳目、并更新用戶表。兩個模塊通過共享用戶表mail-usr-tab,郵件信息表mailmsgtab,和計費日志實現相互通信。
2. 修改mail.local,插入計費模塊,以獲取來信的源地址,識別郵件的長度及是否國外郵件,并將這些信息寫到一個中間表mailmsgtab里;修改popper,插入計費模塊,在用戶使用popper取郵件時,將該郵件的信息從中間表mailmsgtab中取出來,連同用戶的IP及取信時間一同寫入日志文件,并將mailmsgtab中相應條目清空,以避免對同一封郵件的重復計費。這樣,既獲得了郵件的源地址,又獲得了用戶的本地IP。對于不受歡迎站點的來信,可以在mail.local中將其源地址識別出來之后,退回發送者或者丟棄。對于欠費用戶或不受歡迎的用戶,可以在用戶通過popper獲取郵件時拒絕用戶的請求。
3. 如果直接由popper寫計費日志的話,可能會出現幾個進程同時寫一個文件的情況。雖然用互鎖機制可以避免寫丟失,但在一個進程寫的時候其它幾個進程必須等待,延長了響應時間,降低了系統性能。因此采用一個專門的進程寫計費日志,稱為通信守護進程(cmpd,Communication Monitor Process Daemon)。所有的計費信息由popper使用UDP包發送給它,由它寫入日志。
4. 提供自我服務,開發一個自我服務程序,用戶可以通過遠程登錄啟動該程序的一個進程來修改在用戶表中的密碼,象常規的密碼修改程序一樣,普通用戶首先需要使用舊密碼進行身份認證,管理員可以修改任何用戶的密碼。
4.2 計費郵件服務器實現模型
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -