通過JavaMail訪問Hotmail郵箱
作者: zhaozexin
出處: blog
責任編輯: 方舟
[ 2005-02-12 10:40 ]
相信許多人都有MSN聊天工具的帳號,例如abc@hotmail.com ,這個賬號其實也是一個郵件地址,可以進行正常的郵件收發(fā)功能,你可以通過網(wǎng)址 http://www.hotmail.com 來訪問和操作這個郵箱進行郵件的收發(fā)。但是這個郵箱有一個限制就是它并不提供POP3或者SMTP服務,也就是說一般的郵件客戶端工具無法使用這個郵箱,雖然現(xiàn)在有不少的郵件工具可以支持Hotmail郵箱,但是如果我們需要在我們的Java項目中增加對Hotmail郵箱的支持,那往往會不知從什么地方開始入手,因為SUN公司提供的JavaMail 本身并不提供對除了POP3/IMAP以及SMTP外其他協(xié)議的支持。
但事實上,JavaMail只是定義了一組平臺無關、獨立于通訊協(xié)議的郵件程序框架,或者說是接口,它是作為Java的可選包存在的。因此可以這樣說:JavaMail并不關心所使用的協(xié)議,不管是POP3、SMTP、IMAP當然還有Hotmail用的HTTP協(xié)議。對于JavaMail的客戶端而言也是這樣的,下圖就是一個最簡單的JavaMail結(jié)構圖,通過Transport進行郵件的發(fā)送,通過Store實現(xiàn)對郵件的收取,而不同協(xié)議的實現(xiàn),JavaMail里的概念叫做Provider,只需要根據(jù)JavaMail定義的接口實現(xiàn)自己的Provider即可。
為了實現(xiàn)通過JavaMail訪問Hotmail郵箱,我們就需要架起JavaMail接口與Hotmail服務所提供的訪問接口之間的橋梁。在這之前我們必須首先了解Hotmail所使用的接口協(xié)議。
Hotmail通過地址 http://services.msn.com/svcs/hotmail/httpmail.asp 提供基于HTTP協(xié)議的服務,它不同于我們通過瀏覽器訪問 http://www.hotmail.com 的這個地址,后面這個地址是提供給用戶一個基于瀏覽器的訪問界面以便對郵箱進行操作,你當然可以通過編寫HTTP客戶端程序來解析頁面并獲取郵件的信息,但是這樣做不僅實現(xiàn)的復雜程度非常高,而且每次頁面風格發(fā)生變化后程序都要做相應的調(diào)整,因此不具備通用性,顯然是不可行的。而地址 http://services.msn.com/svcs/hotmail/httpmail.asp 則不同,它提供了固定的應用程序接口。當你使用瀏覽器訪問該地址的時候,會彈出下面要求登錄的窗體:
而當輸入正確的用戶名和口令后會再彈出一次或兩次該提示窗口,但提示信息不同,操作完成后出現(xiàn)頁面無法顯示的錯誤,錯誤碼是 405 (資源不允許)。因此該服務并不允許通過瀏覽器來訪問。
事實上Hotmail使用的是WebDAV來提供基于HTTP協(xié)議的應用編程接口,WebDAV(Web 分布式創(chuàng)作和版本控制)已經(jīng)成為重要的 Web 通訊協(xié)議。WebDAV所要解決的問題是:
1.改寫保護:HTTP 1.1 無法確保客戶端可以保護資源,并且可以在其他客戶端同時編輯它們的情況下進行更改。 使用 WebDAV,可以通過多種方式來鎖定資源,以便讓其他客戶端知道您對所討論的資源感興趣,或者防止其他客戶端訪問該資源。
2.資源管理:HTTP 只能直接訪問單個資源。 WebDAV 提供一種更有效地組織數(shù)據(jù)的方法。 WebDAV 引入了可包含資源 的集合(類似于文件系統(tǒng)文件夾)概念。 通過 WebDAV 進行的資源管理包括如下功能:創(chuàng)建、移動、復制和刪除集合,以及集合中的資源或文件。
3.文檔屬性:不同類型的數(shù)據(jù)具有唯一的屬性,這有助于描述數(shù)據(jù)。 例如,在電子郵件中,這些屬性可能是發(fā)件人的姓名和接收郵件的時間。 在協(xié)作文檔中,這些屬性可能是文檔原始作者的姓名和最后一個編輯者的姓名。 因為人們使用的文檔類型各不相同,所以可能的屬性類型列表也變得無限大。 XML 是 WebDAV 所需的一種可擴展通訊工具。
關于WebDAV的更多資料可以參閱本文最后的參考資料。
相對于自行解析Hotmail的瀏覽器頁面而言,基于特定協(xié)議WebDAV的接口使Hotmail郵件客戶端程序的實現(xiàn)更加穩(wěn)定和可靠。在了解了JavaMail API的基本接口以及Hotmail所提供接口的協(xié)議,本文的題目就變得非常具體了,就是如果編寫基于WebDAV的JavaMail Provider(JavaMail提供者)并使用這個提供者來實現(xiàn)Hotmail郵件收發(fā)功能,但這題目太大而且已經(jīng)超過了一篇文章所能敘述的范圍,因此我們接下來將引入一個開放源碼項目JDAVMail,并詳細介紹如何通過這個項目實現(xiàn)Hotmail郵件的收發(fā)功能。
JDAVMail 是一個開放源碼的JavaMail的提供者項目,可以通過它來訪問基于WebDAV協(xié)議的郵件服務,有如Hotmail郵箱。你可以到 http://sourceforge.net/projects/jdavmail 這個網(wǎng)址下載到最新版本的程序。JDAVMail使用了Jakarta上的commons httpclient 作為HTTP客戶端組件與服務器進行通訊,同時使用了jdom進行XML數(shù)據(jù)的解析,另外由于httpclient項目用到了commons logging進行日記的輸出,因此commons-logging也是必須的,這三個組件都可以在JDAVMail的壓縮包中的lib目錄中找到,壓縮包中同時還包括已編譯的jar文件以及所有的源碼。
為了讓大家對JDAVMail有個大概的認識,下面我們給出兩段代碼用于Hotmail郵件的收發(fā):
1. 郵件收取
從上面這段代碼我們發(fā)現(xiàn)除了 Store store = ses.getStore("davmail"); 這個語句,同時不需要指定服務器地址外,其他的都跟一個普通的JavaMail應用程序沒有兩樣,也沒有引入任何跟JDAVMail有關的類。沒有指定服務器地址這個比較容易理解,因為Hotmail提供HttpMail服務的地址是固定的。事實上僅有getStore這個語句跟常規(guī)郵件客戶端程序有點不同的是它使用davmail字符串作為參數(shù),而我們在使用JavaMail連接POP3服務器的時候指定參數(shù)值為pop3。怎么回事呢?因為JavaMail是通過協(xié)議名來加載Provider類的。打開JDAVMail.0.9.006.jar這個jar文件就會發(fā)現(xiàn)在META-INF目錄下有一個文件javamail.providers,該文件內(nèi)容如下:
因此當我們指定協(xié)議名為davmail時,JavaMail就會自動加載com.posisoft.jdavmail.JDAVMailStore類進行處理,因此通過傳入davmail字符串所得到的store實例實際上是類com.posisoft.jdavmail.JDAVMailStore的一個實例,這樣我想大家應該了解了前面這段程序的工作原理。
我們再來看JDAVMail發(fā)送郵件的代碼片段:
同樣這段代碼使用了davmail_xmit協(xié)議來獲取JDAVMail的郵件發(fā)送實例,通過前面提到的javamail.providers文件不難知道JDAVMail使用類com.posisoft.jdavmail.JDAVMailTransport進行郵件的發(fā)送處理。
在實際測試中發(fā)現(xiàn)不管是JDAVMail還是其他的郵件工具,使用Hotmail進行郵件的發(fā)送速度比較慢,差不多有幾分鐘后才能收到相應的信息,因此如果測試中發(fā)現(xiàn)該問題請耐心等待。
我想通過本文介紹如何利用JDAVMail收發(fā)Hotmail郵件,以及研究JDAVMail的源碼,不僅可以更加深入了解JavaMail的體系結(jié)構,對編寫JavaMail Provider也有更加具體的參照。另外希望為正困撓于如何在Java程序中訪問Hotmail郵件的朋友們排憂解難。同時也非常歡迎通過我的網(wǎng)站 http://www.javayou.com 跟我交流在使用中遇到的問題。
但事實上,JavaMail只是定義了一組平臺無關、獨立于通訊協(xié)議的郵件程序框架,或者說是接口,它是作為Java的可選包存在的。因此可以這樣說:JavaMail并不關心所使用的協(xié)議,不管是POP3、SMTP、IMAP當然還有Hotmail用的HTTP協(xié)議。對于JavaMail的客戶端而言也是這樣的,下圖就是一個最簡單的JavaMail結(jié)構圖,通過Transport進行郵件的發(fā)送,通過Store實現(xiàn)對郵件的收取,而不同協(xié)議的實現(xiàn),JavaMail里的概念叫做Provider,只需要根據(jù)JavaMail定義的接口實現(xiàn)自己的Provider即可。
![]() |
為了實現(xiàn)通過JavaMail訪問Hotmail郵箱,我們就需要架起JavaMail接口與Hotmail服務所提供的訪問接口之間的橋梁。在這之前我們必須首先了解Hotmail所使用的接口協(xié)議。
Hotmail通過地址 http://services.msn.com/svcs/hotmail/httpmail.asp 提供基于HTTP協(xié)議的服務,它不同于我們通過瀏覽器訪問 http://www.hotmail.com 的這個地址,后面這個地址是提供給用戶一個基于瀏覽器的訪問界面以便對郵箱進行操作,你當然可以通過編寫HTTP客戶端程序來解析頁面并獲取郵件的信息,但是這樣做不僅實現(xiàn)的復雜程度非常高,而且每次頁面風格發(fā)生變化后程序都要做相應的調(diào)整,因此不具備通用性,顯然是不可行的。而地址 http://services.msn.com/svcs/hotmail/httpmail.asp 則不同,它提供了固定的應用程序接口。當你使用瀏覽器訪問該地址的時候,會彈出下面要求登錄的窗體:
![]() |
而當輸入正確的用戶名和口令后會再彈出一次或兩次該提示窗口,但提示信息不同,操作完成后出現(xiàn)頁面無法顯示的錯誤,錯誤碼是 405 (資源不允許)。因此該服務并不允許通過瀏覽器來訪問。
事實上Hotmail使用的是WebDAV來提供基于HTTP協(xié)議的應用編程接口,WebDAV(Web 分布式創(chuàng)作和版本控制)已經(jīng)成為重要的 Web 通訊協(xié)議。WebDAV所要解決的問題是:
1.改寫保護:HTTP 1.1 無法確保客戶端可以保護資源,并且可以在其他客戶端同時編輯它們的情況下進行更改。 使用 WebDAV,可以通過多種方式來鎖定資源,以便讓其他客戶端知道您對所討論的資源感興趣,或者防止其他客戶端訪問該資源。
2.資源管理:HTTP 只能直接訪問單個資源。 WebDAV 提供一種更有效地組織數(shù)據(jù)的方法。 WebDAV 引入了可包含資源 的集合(類似于文件系統(tǒng)文件夾)概念。 通過 WebDAV 進行的資源管理包括如下功能:創(chuàng)建、移動、復制和刪除集合,以及集合中的資源或文件。
3.文檔屬性:不同類型的數(shù)據(jù)具有唯一的屬性,這有助于描述數(shù)據(jù)。 例如,在電子郵件中,這些屬性可能是發(fā)件人的姓名和接收郵件的時間。 在協(xié)作文檔中,這些屬性可能是文檔原始作者的姓名和最后一個編輯者的姓名。 因為人們使用的文檔類型各不相同,所以可能的屬性類型列表也變得無限大。 XML 是 WebDAV 所需的一種可擴展通訊工具。
關于WebDAV的更多資料可以參閱本文最后的參考資料。
相對于自行解析Hotmail的瀏覽器頁面而言,基于特定協(xié)議WebDAV的接口使Hotmail郵件客戶端程序的實現(xiàn)更加穩(wěn)定和可靠。在了解了JavaMail API的基本接口以及Hotmail所提供接口的協(xié)議,本文的題目就變得非常具體了,就是如果編寫基于WebDAV的JavaMail Provider(JavaMail提供者)并使用這個提供者來實現(xiàn)Hotmail郵件收發(fā)功能,但這題目太大而且已經(jīng)超過了一篇文章所能敘述的范圍,因此我們接下來將引入一個開放源碼項目JDAVMail,并詳細介紹如何通過這個項目實現(xiàn)Hotmail郵件的收發(fā)功能。
JDAVMail 是一個開放源碼的JavaMail的提供者項目,可以通過它來訪問基于WebDAV協(xié)議的郵件服務,有如Hotmail郵箱。你可以到 http://sourceforge.net/projects/jdavmail 這個網(wǎng)址下載到最新版本的程序。JDAVMail使用了Jakarta上的commons httpclient 作為HTTP客戶端組件與服務器進行通訊,同時使用了jdom進行XML數(shù)據(jù)的解析,另外由于httpclient項目用到了commons logging進行日記的輸出,因此commons-logging也是必須的,這三個組件都可以在JDAVMail的壓縮包中的lib目錄中找到,壓縮包中同時還包括已編譯的jar文件以及所有的源碼。
為了讓大家對JDAVMail有個大概的認識,下面我們給出兩段代碼用于Hotmail郵件的收發(fā):
1. 郵件收取
/* * 文件名:HotmailDemo.java * 創(chuàng)建時間:2004-9-14 * 創(chuàng)建者:liudong */ package com.clickcom.mail; import java.util.Date; import java.util.Properties; import javax.mail.Folder; import javax.mail.Message; import javax.mail.Session; import javax.mail.Store; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; /** * Hotmail郵件的收發(fā)器 * @author liudong */ public class HotmailDemo { public static void main(String[] args) { receive(); } /** * 郵件接收 */ protected static void receive() { try { Properties prop = new Properties(); Session ses = Session.getInstance(prop); //使用JDAVMail Provider Store store = ses.getStore("davmail"); //無需指定服務器地址 store.connect(null, "你的帳號","密碼"); if (store.isConnected()) { Folder inbox = store.getFolder("INBOX"); if (inbox.exists()) { inbox.open(Folder.READ_ONLY); int nCount = inbox.getMessageCount(); System.out.println("Inbox contains " + nCount + " messages"); // 依次顯示收件箱中的每封郵件 for(int i=1;i<=nCount;i++){ MimeMessage msg = (MimeMessage) inbox.getMessage(i); System.out.println("Subject : " + msg.getSubject()); System.out.println("From : " + msg.getFrom()[0].toString()); System.out.println("Content type : " + msg.getContentType()); System.out.println(msg.getContent()); } } } } catch (Exception ex) { ex.printStackTrace(); } } } |
從上面這段代碼我們發(fā)現(xiàn)除了 Store store = ses.getStore("davmail"); 這個語句,同時不需要指定服務器地址外,其他的都跟一個普通的JavaMail應用程序沒有兩樣,也沒有引入任何跟JDAVMail有關的類。沒有指定服務器地址這個比較容易理解,因為Hotmail提供HttpMail服務的地址是固定的。事實上僅有getStore這個語句跟常規(guī)郵件客戶端程序有點不同的是它使用davmail字符串作為參數(shù),而我們在使用JavaMail連接POP3服務器的時候指定參數(shù)值為pop3。怎么回事呢?因為JavaMail是通過協(xié)議名來加載Provider類的。打開JDAVMail.0.9.006.jar這個jar文件就會發(fā)現(xiàn)在META-INF目錄下有一個文件javamail.providers,該文件內(nèi)容如下:
protocol=davmail; type=store; class=com.posisoft.jdavmail.JDAVMailStore; vendor=Positive Software; protocol=davmail_xmit; type=transport; class=com.posisoft.jdavmail.JDAVMailTransport; vendor=Positive Software; |
因此當我們指定協(xié)議名為davmail時,JavaMail就會自動加載com.posisoft.jdavmail.JDAVMailStore類進行處理,因此通過傳入davmail字符串所得到的store實例實際上是類com.posisoft.jdavmail.JDAVMailStore的一個實例,這樣我想大家應該了解了前面這段程序的工作原理。
我們再來看JDAVMail發(fā)送郵件的代碼片段:
/** * 郵件發(fā)送 */ protected static void send() { try { Properties prop = new Properties(); //郵件發(fā)送者地址 prop.setProperty("mail.davmail.from","abc@hotmail.com"); Session ses = Session.getInstance(prop); //獲得JDAVMail的郵件發(fā)送實例 Transport transport = ses.getTransport("davmail_xmit"); //連接到Hotmail服務器,請?zhí)鎿Q為自己的用戶名和口令 transport.connect(null, "用戶名","口令"); // 準備要發(fā)送的郵件 MimeMessage txMsg = new MimeMessage(ses); txMsg.setSubject("This is the subject"); //郵件發(fā)送者地址 InternetAddress addrFrom = new InternetAddress("abc@hotmail.com"); txMsg.setFrom(addrFrom); //郵件接收者地址 InternetAddress addrTo = new InternetAddress("cdef@hotmail.com", "cdef"); txMsg.addRecipient(Message.RecipientType.TO, addrTo); //郵件內(nèi)容 txMsg.setText("Hello world !"); txMsg.setSentDate(new Date()); //發(fā)送郵件 transport.sendMessage(txMsg, txMsg.getAllRecipients()); } catch (Exception ex) { ex.printStackTrace(); } } |
同樣這段代碼使用了davmail_xmit協(xié)議來獲取JDAVMail的郵件發(fā)送實例,通過前面提到的javamail.providers文件不難知道JDAVMail使用類com.posisoft.jdavmail.JDAVMailTransport進行郵件的發(fā)送處理。
在實際測試中發(fā)現(xiàn)不管是JDAVMail還是其他的郵件工具,使用Hotmail進行郵件的發(fā)送速度比較慢,差不多有幾分鐘后才能收到相應的信息,因此如果測試中發(fā)現(xiàn)該問題請耐心等待。
我想通過本文介紹如何利用JDAVMail收發(fā)Hotmail郵件,以及研究JDAVMail的源碼,不僅可以更加深入了解JavaMail的體系結(jié)構,對編寫JavaMail Provider也有更加具體的參照。另外希望為正困撓于如何在Java程序中訪問Hotmail郵件的朋友們排憂解難。同時也非常歡迎通過我的網(wǎng)站 http://www.javayou.com 跟我交流在使用中遇到的問題。