1. 介紹
很感謝幾個新的web mail產品(比如像IMP),使得web設計者可以通過這些產品來在他們的網站上提供基于web的郵件服務.盡管采用采用這些產品來實現web方式郵件服務的解決方案已經越來越流行,但是郵件服務可擴展性這個問題已經被提出來.很多web mail系統(包括免費的)都是設計在單個mail和web服務器上,所有的限制都取決于一臺服務器上面.在這種情況下再擴展幾千個用戶是簡單但不容易實現,這就是我為什么開始設計一個在實際應用中可以無限擴展而且實現簡單的系統.
1.1 背景
基于Web的電子郵件系統就像野花一樣迷人,以至于像hotmail和bigfoot這樣的站點變得如此流行,其他的站點看來也是把提供基于web的郵件服務添加到了他們的服務項目表中.事實上,很多像EmuMail和IMP這樣地產品已經被開發出來以幫助人們向他們的客戶提供這項服務.不管怎么樣,基于這些產品之上的站點變得流行起來,同時也在加重了網絡和機器的資源負擔.如果沒有一個可定制的解決方案,就像Hotmail一樣,很多使用了off-the-shelf(我想可能是沒有自己開發或者定制性差那種意思,就靠各位去理解了) webmail系統的站點已經開始感到發展期的困難了.正以為如此,找到一個能夠相對簡單地實現而且可以擴展到數千甚至是數百萬用戶的解決方案的需求變的越來越緊迫.
我是DigitalNation的一名開發人員,現在在為Worldcities工程工作. Worldcities不僅提供世界各地的本地新聞和信息,而且還提供基于web的郵件服務.因為很多非美國的ISP沒有給他們的客戶提供電子郵件服務,Webmail在美國以外的地區是很流行的.正因為 Worldcities不是以美國為中心,所以我們很快意識到郵件服務的可擴展性是很必要的.
我們以前的郵件服務系統是采用兩種服務器,一種是運行Sendmail和UW IMAP,另外一種是運行 IMP, 它是一個使用PHP編寫的開放代碼的webmail系統(應該說是最好的,我認為).這種郵件服務系統很容易實現而且工作得很好.但是,經過兩三個月后,發現我們的郵件系統明顯負載過重,所以我們必須要很快找到一個新的解決方案.而且我們有很多正在使用本系統的用戶,新的方案不能夠遺失他們已經存在的電子郵件.
以前我們選擇IMP是因為它是免費的(比如說我可以在它的基礎上進行一些必要的修改),選擇 Sendmail和UW IMAP是因為它們是標準的工具.很明顯,Sendmail和UW IMAP對我們的用戶來說是太慢了,因此我開始研究其他的MATs和IMAP服務器軟件.
我最后決定采用postfix作為MTA, 因為它至少比Sendmail要快三倍, 采用cyrus是因為它既不需要主機的系統帳號也不需要像UW IMAP那樣消耗很多系統資源.我們保留了IMP,因為它不單是免費的,而且很容易配置.我們也不想用戶受制于新的界面. 在研究的過程中我發現 postfix能夠使用LDAP目錄服務來作為它的別名數據庫(使用maildrop和mailaclearcase/" target="_blank" >cceptinggeneralid屬性),而且有一個補丁程序可以讓Cyrus使用LDAP來進行用戶認證.配合DNS循環解析(譯者注:DNS循環解析是為同一個名字分配多個IP地址,它在Yahoo等相當大的站點應用,實際效果相當不錯),把web請求和發送進來的郵件分散給不同的服務器進行處理,這樣做就是一個具備了高可擴展性的解決方案.剩下的問題是怎么把這些功能集成在一起來.
這個方案的可擴展性主要是postfix能夠根據LDAP中對應用戶目錄項的maildrop屬性值來把郵件轉發到其他的用戶信箱或者別的郵件服務器上.我們要做的只是賦給屬性maildrop一個完整有效的郵件地址作為它的屬性值.例如,如果DNS的MX記錄指定了一組郵件服務器并且從LDAP中檢索的結果是把發送給的郵件轉到,postfix就會把發送給該用戶的郵件轉發到machine44這臺郵件服務器上.有了這個功能,你就可以在你的域內設置無限個郵件帳號.
我想最棘手的就是通過IMP從后臺郵件服務器中讀取郵件.既然IMP已經支持把web服務器和mail服務器分開,現在要做的就是用從LDAP中檢索郵件服務器名來取代在配置文件中指定郵件服務器的方式,在配置文件中只能夠指定在一臺郵件服務器上收發郵件.這樣就使得設置郵件服務器變得很簡單,只需要在一個文件中添加幾行代碼和在IMP的默認配置文件中添加一個新的配置參數就行了.現在我們可以使用postfix來轉發郵件、通過IMP從多個郵件服務器中檢索郵件.
但是,UW IMAP依然是個問題.有下面幾個理由:1、使用平面文件格式.2、對大量的郵件信息不具有可擴展性.3、需要使用主機系統的認證方式和系統帳號,用戶每次登錄都要讀取一次/etc/passwd文件.4、比我們所期望的速度要慢.所以我們決定采用Cyrus, 一個沒有上面那些限制的imap服務器.更值得可喜的是,有了Clayton Donely的LDAP patch for Cyrus,我們就可以利用postfix所使用的LDAP目錄服務來進行用戶認證.這樣就使得我們的整個mail系統除了可擴展性好外,還有輕便性,因為不需要做多份password的拷貝.畢竟這也是LDAP的設計目的之一.
最后,我們需要的是一個采用DNS循環解析的web/mail系統結構.在LDAP目錄服務的基礎上進行郵件的轉發和從相應的后臺郵件服務器上檢索郵件,同時也利用LDAP目錄服務進行用戶認證. 由于LDAP的可復制性,在這個系統結構中,我們就可以利用多臺LDAP來進行互相備份(假設這些服務器間都是高速連接的),如果系統結構中一臺或者某幾臺LDAP服務器down掉后,其他的LDAP服務器能夠及時提供后備服務,不影響整個mail系統的正常運行.
1.2 假設
這份文檔中提到了三種服務器:web服務器、imap服務器和LDAP服務器.這些服務可以安裝在不同的機器上(比如,23臺web服務器,5臺LDAP服務器,10臺imap服務器),或者是單臺機器上.假設你了解在Unix或者Linux環境下進行源代碼軟件安裝的知識.
1.3 需要用到的軟件
下面是在這份文檔中要用到的軟件列表.
Apache 1.3.6
PHP 3.0.12 (需要把IMAP和LDAP編譯進去)
OpenLDAP 1.2
Cyrus 1.5.19 (注意: 不要用1.6版本)
postfix 19990627
pwcheck_ldap patch for cyrus 1.5
IMP (2.0.4, 2.0.10, 2.1.3-dev也測試過)
UW IMAP (提供c-client庫)
注意: cyrys 1.6使用了一種新的認證方式,名為SASL.pwcheck_ldap這個補丁沒有針對這種認證方式進行開發.有人說一個針對SASL的LDAP補丁程序已經在開發了,但那個補丁什么時候能夠應用,現在討論這個問題是沒有意義的.
1.4 特別注意
這份文檔中提出的解決方案中有一點還沒有能夠做到高可擴展性,那就是SQL server.IMP使用SQL server來保存session數據、郵箱配置和地址簿.IMP的作者現在在設計一種讓SQL Server也能夠做到容易擴展的方法.
2. 軟件安裝
2.1 Web服務
在web服務器上,你需要安裝Apache, PHP, postfix, OpenLDAP, UW IMAP, 和 IMP.
安裝Apache和PHP是很快的,安裝的具體步驟在PHP的安裝文檔中有說明.你必須把LDAP和IMAP 的支持模塊編譯到PHP中.
按照postfix附帶的文檔來安裝postfix,特別是LDAP_README這個說明文件.
2.2 LDAP服務
在LDAP服務器上,你需要安裝OpenLDAP,而且需要確定一個root dn(比如:cn=root,dc=rayesmail,dc=com)并且把它添加到LDAP的目錄中.(譯者注:在slapd.conf中指定)
2.3 IMAP服務
在IMAP服務器上,你需要安裝LDAP, postfix, Cyrus, 和專為cyrus開發的pwcheck_ldap補丁程序. 按照postfix的文檔安裝支持LDAP的postfix. 按照Cyrus的文檔來安裝Cyrus和按照pwcheck_ldap的文檔來添加pwdcheck_ldap.c.不要忘記了要更改pwcheck_ldap.c文件中的設置使得與你的LDAP目錄服務器主機和base dn(譯者注:目錄的一部分,比如說是o=mailgroup,dc=rayesmail,dc=com)相符.最后,需要在pwcheck_ldap.c中添加下面的一行:
#include
如果你是使用Linux來作為IMAP服務器,你可能需要在pwcheck_ldap.c中做一些語法更正(我現在忘記了哪是正確的),以保證正常編譯.使用下面的命令來配置cyrus:
./configure --with-login=unix_pwcheck --with-pwcheck=ldap
在pwcheck_ldap的文檔中漏掉了--with-login這個配置參數.編譯,然后按照cyrus的文檔來安裝.
3. 服務配置
3.1 LDAP服務
除了你用到的其他屬性,每一個mail用戶在LDAP目錄中的目錄項必須要有下面的屬性(假設你的basedn是 o=someorg,c=US):
dn: uid=someuser, o=someorg, c=us
uid: someuser
userpassword: somepassword
maildrop:
mailacceptinggeneralid: someuser
(你也可以使用別名,如下所示)
mailacceptinggeneralid: somealias
同時,你需要為cyrus指定一個具有管理員權限的帳號.除非你在imap服務器上配置cyrus,否則你沒有必要擔心這個問題.但是你心里要清楚這一點.另外一點就是不要指定一個已經存在的帳號來作為管理員,問題可能會 出現安全漏洞或者造成該用戶無法收郵件.
3.2 imap服務
配置imap服務器上的postfix,使得它使用LDAP目錄來作為它的別名映射.配置的說明可以在 postfix文檔中的LDAP_README文件中找到.Cyrus的安裝說明已經包含在它的軟件包里面.同時,不要忘了使pwcheck生效和在imap.conf中添加你的管理員帳號.
3.3 web服務
在這一步中,要把web服務器配置成收發郵件的終端.配置postfix,使得它使用LDAP目錄來作為它的別名數據庫.postfix所做的工作就是在LDAP目錄中檢索對應郵件用戶目錄項的maildrop屬性值,并且把郵件轉發到maildrop屬性值所指定的郵件地址中,因此在maildrop屬性中必須指定完整的郵件服務器名稱.
你可能有700,000個用戶分布到不同的服務器上.發送給的電子郵件將轉發到maildrop地址,而發送給的電子郵件將轉發到上.另外,maildrop屬性也可以指定一個其他的轉發地址.比如說user302的maildrop屬性值為,那么發送給user302的電子郵件就會轉發到這個郵件地址中.
按照IMP的文檔把IMP配置好,然后做下面的更改工作:
在config/defaults.php3添加下面幾行:
/* LDAP/IMAP Server Default */
$default->LDAP_server = ldap.dom.ain;
$default->LDAP_dn = o=someorg,c=US;
$default->LDAP_search_field = uid;
$default->ldap_choose_server = true;
對mailbox.php3打一個下面的補丁:
Index: mailbox.php3
===================================================================
RCS file: /home/cvs/imp/mailbox.php3,v
retrieving revision 2.29
diff -c -r2.29 mailbox.php3
*** mailbox.php3 1999/07/29 07:20:00 2.29
--- mailbox.php3 1999/08/04 18:04:10
***************
*** 29,34 ****
--- 29,51 ----
require ./lib/mimetypes.lib;
require ./config/defaults.php3;
+ /************LDAP**************/
+
+ if ($default->ldap_choose_server) {
+ $ldapconnect = ldap_connect($default->LDAP_server);
+ if ($ldapconnect) {
+ print("YES!
");
+ $ldapbind = ldap_bind($ldapconnect);
+ $ldapsearch = ldap_search($ldapconnect, $default->LDAP_dn,
+ $default->LDAP_search_field."=".$imapuser, array("maildrop"));
+ $ldapget = ldap_get_entries($ldapconnect, $ldapsearch);
+ $ldapspl = explode("@", $ldapget[0]["maildrop"][0]);
+ $server = $ldapspl[1];
+ $port = $default->port;
+ }
+ }
+ /**********end ldap************/
+
+
/* Html styles configuration */
require ./config/html.php3;
/* Mailbox configuration */
這些做完后,你已經有了高可擴展性的web mail解決方案了.
注意: 在1999年8月5日后,IMP的開發版本已經包括了這些補丁,因此上面的這些修改就沒有必要進行了.
4. 其他
4.1 添加用戶
下面是一段程序,可以用來在LDAP目錄中添加一個用戶和在cyrus中添加一個mailbox.這是為單個imap服務器設計的,但可以很容易地改變成為應用多臺服務器的方式.
注意:因為還存在一個BUG,所以沒有能夠可靠地支持encrypted密碼,現在是用明文密碼來代替.