简介: 相信许多人都有 MSN 聊天工具的帐号,例如 abc@hotmail.com ,这个账号其实也是一个邮件地址,可以进行正常的邮件收发功能,你可以通过网址 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","abc@hotmail.com"); 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("abc@hotmail.com"); txMsg.setFrom(addrFrom); // 邮件接收者地址InternetAddress addrTo = new InternetAddress("cdef@hotmail.com", "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跟我交流在使用中遇到的问题。