1. 程式人生 > >通過 JavaMail 訪問 Hotmail 郵箱(hotmail不提供smtp和pop3服務)

通過 JavaMail 訪問 Hotmail 郵箱(hotmail不提供smtp和pop3服務)

簡介: 相信許多人都有 MSN 聊天工具的帳號,例如 [email protected] ,這個賬號其實也是一個郵件地址,可以進行正常的郵件收發功能,你可以通過網址 http://www.hotmail.com 來訪問和操作這個郵箱進行郵件的收發。但是這個郵箱有一個限制就是它並不提供 POP3 或者 SMTP 服務,也就是說一般的郵件客戶端工具無法使用這個郵箱,雖然現在有不少的郵件工具可以支援 Hotmail 郵箱,但是如果我們需要在我們的 Java 專案中增加對 Hotmail 郵箱的支援,那往往會不知從什麼地方開始入手,因為 SUN 公司提供的 JavaMail 本身並不提供對除了 POP3/IMAP 以及 SMTP 外其他協議的支援。

但事實上,JavaMail 只是定義了一組平臺無關、獨立於通訊協議的郵件程式框架,或者說是介面,它是作為 Java 的可選包存在的。因此可以這樣說:JavaMail 並不關心所使用的協議,不管是 POP3、SMTP、IMAP 當然還有 Hotmail 用的 HTTP 協議。對於 JavaMail 的客戶端而言也是這樣的,下圖就是一個最簡單的 JavaMail 結構圖,通過 Transport 進行郵件的傳送,通過 Store 實現對郵件的收取,而不同協議的實現,JavaMail 裡的概念叫做 Provider,只需要根據 JavaMail 定義的介面實現自己的 Provider 即可。



為了實現通過 JavaMail 訪問 Hotmail 郵箱,我們就需要架起 JavaMail 介面與 Hotmail 服務所提供的訪問介面之間的橋樑。在這之前我們必須首先了解 Hotmail 所使用的介面協議。

Hotmail 通過地址 http://services.msn.com/svcs/hotmail/httpmail.asp 提供基於 HTTP 協議的服務,它不同於我們通過瀏覽器訪問http://www.hotmail.com的這個地址,後面這個地址是提供給使用者一個基於瀏覽器的訪問介面以便對郵箱進行操作,你當然可以通過編寫 HTTP 客戶端程式來解析頁面並獲取郵件的資訊,但是這樣做不僅實現的複雜程度非常高,而且每次頁面風格發生變化後程序都要做相應的調整,因此不具備通用性,顯然是不可行的。而地址 http://services.msn.com/svcs/hotmail/httpmail.asp 則不同,它提供了固定的應用程式介面。當你使用瀏覽器訪問該地址的時候,會彈出下面要求登入的窗體:



而當輸入正確的使用者名稱和口令後會再彈出一次或兩次該提示視窗,但提示資訊不同,操作完成後出現頁面無法顯示的錯誤,錯誤碼是 405 (資源不允許)。因此該服務並不允許通過瀏覽器來訪問。

事實上 Hotmail 使用的是 WebDAV 來提供基於 HTTP 協議的應用程式設計介面,WebDAV(Web 分散式創作和版本控制)已經成為重要的 Web 通訊協議。WebDAV 所要解決的問題是:

1. 改防寫:HTTP 1.1 無法確保客戶端可以保護資源,並且可以在其他客戶端同時編輯它們的情況下進行更改。 使用 WebDAV,可以通過多種方式來鎖定資源,以便讓其他客戶端知道您對所討論的資源感興趣,或者防止其他客戶端訪問該資源。

2. 資源管理:HTTP 只能直接訪問單個資源。 WebDAV 提供一種更有效地組織資料的方法。 WebDAV 引入了可包含資源 的集合(類似於檔案系統資料夾)概念。 通過 WebDAV 進行的資源管理包括如下功能:建立、移動、複製和刪除集合,以及集合中的資源或檔案。

3. 文件屬性:不同型別的資料具有唯一的屬性,這有助於描述資料。 例如,在電子郵件中,這些屬性可能是發件人的姓名和接收郵件的時間。 在協作文件中,這些屬性可能是文件原始作者的姓名和最後一個編輯者的姓名。 因為人們使用的文件型別各不相同,所以可能的屬性型別列表也變得無限大。 XML 是 WebDAV 所需的一種可擴充套件通訊工具。

關於 WebDAV 的更多資料可以參閱本文最後的參考資料。

相對於自行解析 Hotmail 的瀏覽器頁面而言,基於特定協議 WebDAV 的介面使 Hotmail 郵件客戶端程式的實現更加穩定和可靠。在瞭解了 JavaMail API 的基本介面以及 Hotmail 所提供介面的協議,本文的題目就變得非常具體了,就是如果編寫基於 WebDAV 的 JavaMail Provider(JavaMail 提供者)並使用這個提供者來實現 Hotmail 郵件收發功能,但這題目太大而且已經超過了一篇文章所能敘述的範圍,因此我們接下來將引入一個開放原始碼專案 JDAVMail,並詳細介紹如何通過這個專案實現 Hotmail 郵件的收發功能。

JDAVMail 是一個開放原始碼的 JavaMail 的提供者專案,可以通過它來訪問基於 WebDAV 協議的郵件服務,有如 Hotmail 郵箱。你可以到http://sourceforge.net/projects/jdavmail這個網址下載到最新版本的程式。JDAVMail 使用了 Jakarta 上的 commons httpclient 作為 HTTP 客戶端元件與伺服器進行通訊,同時使用了 jdom 進行 XML 資料的解析,另外由於 httpclient 專案用到了 commons logging 進行日記的輸出,因此 commons-logging 也是必須的,這三個元件都可以在 JDAVMail 的壓縮包中的 lib 目錄中找到,壓縮包中同時還包括已編譯的 jar 檔案以及所有的原始碼。

為了讓大家對 JDAVMail 有個大概的認識,下面我們給出兩段程式碼用於 Hotmail 郵件的收發:

1. 郵件收取

/* 
* 檔名:HotmailDemo.java 
* 建立時間:2004-9-14 
* 建立者: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 郵件的收發器
* @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(); 
        } 
    } 
} 
     

從上面這段程式碼我們發現除了 Store store = ses.getStore("davmail");這個語句,同時不需要指定伺服器地址外,其他的都跟一個普通的 JavaMail 應用程式沒有兩樣,也沒有引入任何跟 JDAVMail 有關的類。沒有指定伺服器地址這個比較容易理解,因為 Hotmail 提供 HttpMail 服務的地址是固定的。事實上僅有 getStore 這個語句跟常規郵件客戶端程式有點不同的是它使用 davmail 字串作為引數,而我們在使用 JavaMail 連線 POP3 伺服器的時候指定引數值為 pop3。怎麼回事呢?因為 JavaMail 是通過協議名來載入 Provider 類的。開啟 JDAVMail.0.9.006.jar 這個 jar 檔案就會發現在 META-INF 目錄下有一個檔案 javamail.providers,該檔案內容如下:

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; 

因此當我們指定協議名為 davmail 時,JavaMail 就會自動載入 com.posisoft.jdavmail.JDAVMailStore 類進行處理,因此通過傳入 davmail 字串所得到的 store 例項實際上是類 com.posisoft.jdavmail.JDAVMailStore 的一個例項,這樣我想大家應該瞭解了前面這段程式的工作原理。

我們再來看 JDAVMail 傳送郵件的程式碼片段:

/** 
* 郵件傳送
*/ 
protected static void send() { 
    try { 
        Properties prop = new Properties(); 
        // 郵件傳送者地址
        prop.setProperty("mail.davmail.from","[email protected]"); 
        Session ses = Session.getInstance(prop); 
        // 獲得 JDAVMail 的郵件傳送例項
            
        
        Transport transport = ses.getTransport("davmail_xmit");
        // 連線到 Hotmail 伺服器,請替換為自己的使用者名稱和口令
        transport.connect(null, "
        
        使用者名稱","
        
        口令"); 
        // 準備要傳送的郵件
        MimeMessage txMsg = new MimeMessage(ses); 
        txMsg.setSubject("This is the subject"); 
        // 郵件傳送者地址
        InternetAddress addrFrom = new InternetAddress("[email protected]"); 
        txMsg.setFrom(addrFrom); 
        // 郵件接收者地址
        InternetAddress addrTo = new InternetAddress("[email protected]", "cdef");
        txMsg.addRecipient(Message.RecipientType.TO, addrTo); 
        // 郵件內容
        txMsg.setText("Hello world !"); 
        txMsg.setSentDate(new Date()); 
        // 傳送郵件
        transport.sendMessage(txMsg, txMsg.getAllRecipients()); 
    } catch (Exception ex) { 
        ex.printStackTrace(); 
    } 
} 
     

同樣這段程式碼使用了 davmail_xmit 協議來獲取 JDAVMail 的郵件傳送例項,通過前面提到的 javamail.providers 檔案不難知道 JDAVMail 使用類 com.posisoft.jdavmail.JDAVMailTransport 進行郵件的傳送處理。

在實際測試中發現不管是 JDAVMail 還是其他的郵件工具,使用 Hotmail 進行郵件的傳送速度比較慢,差不多有幾分鐘後才能收到相應的資訊,因此如果測試中發現該問題請耐心等待。

我想通過本文介紹如何利用 JDAVMail 收發 Hotmail 郵件,以及研究 JDAVMail 的原始碼,不僅可以更加深入瞭解 JavaMail 的體系結構,對編寫 JavaMail Provider 也有更加具體的參照。另外希望為正困撓於如何在 Java 程式中訪問 Hotmail 郵件的朋友們排憂解難。同時也非常歡迎通過我的網站http://www.javayou.com跟我交流在使用中遇到的問題。