JavaMail使用教程

阿将邮件工具结合到您独立于平台的 Java 解决方案中吗?再没有比 JavaMail API 更合适的了,它提供了个独立于协议的模块,能用于 IMAPPOPSMTPMIME 和其它涉及因特网的消息传递协议。现在,有了 JavaBeans Activation Framework (JAF)的支持,您的应用程序经由 JavaMail API 就能启用邮件功能啦。

概念

学完这个模块后,您将了解:

·         因特网邮件协议 SMTPPOP3IMAP MIME 的基本知识

·         JavaMail 框架的体系结构

·         JavaMail API JavaBeans Activation Framework 之间的连接

目的

学完这个模块后,您将能够:

·         使用 JavaMail API 发送和阅读邮件

·         处理发送和接受邮件附件

·         处理 HTML 文件格式的消息

·         使用搜索条件搜索消息

先决条件

课程含有如何下载及安装 JavaMail API 的指导。此外,您还需一个开发环境,如 JDK 1.1.6 + Java 2 平台标准版(Java 2 Platform, Standard Edition J2EE1.2.x 1.3.x

有必要对面向对象编程概念和 Java 编程语言大致熟悉。教程 Java 语言要点会有所帮助。

JavaMail API 是什么呢?

JavaMail API 是一个用于阅读、编写和发送电子消息的可选包(标准扩展)。与 Eudorapine Microsoft Outlook 相似,这个包用来创建邮件用户代理(Mail User AgentMUA类型程序。API 的主要用途并不在于传输、发送和转发消息;这一功能范围属于某些应用程序,如 sendmail 及其它邮件传输代理(Mail Transfer AgentMTA)类型程序。MUA 类型的程序能让用户阅读和书写邮件,而它却依赖 MTA 处理实际发送。

JavaMail API 打算将 API 分成两部分来支持独立于协议的发送和接受消息:

·         API 的第一部分是这个课程的焦点基本上来说,是如何发送和接受独立于供应商/协议消息。

·         第二部分谈到特定协议的语言, SMTPPOPIMAP NNTP。有了 JavaMail API,要与服务器通信,还需要每个协议的供应商(provider。此课程不涉及创建特定的协议供应商,因为 Sun 已经为我们免费提供了很充分的一组。

在研究 JavaMail API 的细则之前,让我们回顾用于 API 的协议。基本上,您会逐渐熟悉并喜爱的协议有四个:

·         SMTP

·         POP

·         IMAP

·         MIME

您还将碰到 NNTP 和其它协议。理解所有协议的基本知识将有助于您理解如何使用 JavaMail API。虽然不了解这些协议您照样可以用这个 API,却不能够克服那些基础协议的局限性。如果我们精选的协议不能支持某种性能,JavaMail API 决不能魔术般的将这种性能添加上去。(您很快就会看到,在处理 POP 时这将成为一个难题。)

 

SMTP:简单邮件传输协议(Simple Mail Transfer ProtocolSMTP)由 RFC 821 定义。它定义了发送电子邮件的机制。在 JavaMail API 环境中,您基于 JavaMail 的程序将和您的公司或因特网服务供应商的(Internet Service Provider'sISP'sSMTP 服务器通信。SMTP 服务器会中转消息给接收方 SMTP 服务器以便最终让用户经由 POP IMAP 获得。这不是要求 SMTP 服务器成为开放的中继,尽管 SMTP 服务器支持身份验证,不过还是得确保它的配置正确。像配置服务器来中继消息或添加删除邮件账号这类任务的实现,JavaMail API 中并不支持。

POP: 代表邮局协议(Post Office Protocol)。目前用的是版本 3,也称 POP3RFC 1939 定义了这个协议。POP 是一种机制,因特网上大多数人用它得到邮件。它规定每个用户一个邮箱的支持。这就是它所能做的,而这也造成了许多混淆。使用 POP 时,用户熟悉的许多性能并不是由 POP 协议支持的,如查看有几封新邮件消息这一性能。这些性能内建于如 Eudora Microsoft Outlook 之类的程序中,它们能记住一些事,诸如最近一次收到的邮件,还能计算出有多少是新的。所以当使用 JavaMail API 时,如果您想要这类信息,您就必须自己算。

IMAP 是更高级的用于接收消息的协议。在 RFC 2060 中被定义,IMAP 代表因特网消息访问协议(Internet Message Access Protocol),目前用的是版本 4,也称 IMAP4。在用到 IMAP 时,邮件服务器必需支持这个协议。不能仅仅把使用 POP 的程序用于 IMAP,并指望它支持 IMAP 所有性能。假设邮件服务器支持 IMAP,基于 JavaMail 的程序可以利用这种情况用户在服务器上有多个文件夹(folder),并且这些文件夹可以被多个用户共享。

因为有这一更高级的性能,您也许会认为所有用户都会使用 IMAP。事实并不是这样。要求服务器接收新消息,在用户请求时发送到用户手中,还要在每个用户的多个文件夹中维护消息。这样虽然能将消息集中备份,但随着用户长期的邮件夹越来越大,到磁盘空间耗尽时,每个用户都会受到损失。使用 POP,就能卸载邮件服务器上保存的消息了。

MIME 代表多用途因特网邮件扩展标准(Multipurpose Internet Mail Extensions)。它不是邮件传输协议。但对传输内容的消息、附件及其它的内容定义了格式。这里有很多不同的有效文档:RFC 822RFC 2045RFC 2046 RFC 2047。作为一个 JavaMail API 的用户,您通常不必对这些格式操心。无论如何,一定存在这些格式而且程序会用到它。

因为 JavaMail API 将供应商和所有其它的东西分开了,您就能轻松添加额外的协议支持。Sun 保留了一张第三方供应商列表,他们利用了 Sun 不提供超出(out-of-the-box)支持范围的协议。您会找到 NNTP(网络新闻传输协议)[新闻组]S/MIME(安全多用途因特网邮件扩展)及其它支持。

安装JavaMail:

现在有两种常用的 JavaMail API 版本:1.2 1.1.3 。这一课程的所有示例都能在这两种版本上正常运行。虽然版本 1.2 是最新版,但版本 1.1.3 包含了 Java 2 平台企业版(Java 2 Platform, Enterprise EditionJ2EE)的版本 1.2.1,所以仍然有很多人使用它。您要用的 JavaMail API 的版本取决于您下载和安装的东西,所有这些将在JDK 1.1.6+J2EE 版本 1.2.x J2SE 版本 1.3.x 下工作。

注意:安装完 Sun JavaMail 实现后,您可以在 demo 目录中找到很多示例程序。

要使用 JavaMail 1.2 API,请下载 JavaMail 1.2 实现,解开 javamail-1_2.zip 文件,并将 mail.jar 文件添加到您的 CLASSPATH 中。除了核心类,随版本 1.2 实现一起提供的还有 SMTPIMAP4 POP3 供应商。

安装完 JavaMail 1.2 之后,安装 JavaBeans Activation Framework

JavaMail API 的所有版本都需要 JavaBeans Activation Framework 来支持任意数据块的输入及相应处理。功能似乎不多,但目前许多浏览器和邮件工具中都能找到这种基本的 MIME 型支持。下载完框架后,解开 jaf1_0_1.zip 文件,并将 activation.jar 文件添加到 CLASSPATH 中。

对于 JavaMail 1.2 用户来说,现在您应该已将 mail.jar activation.jar 文件添加到 CLASSPATH 中了。

而对于 JavaMail 1.1.3 用户,现在您应该已将 mail.jarpop3.jar activation.jar文件添加到 CLASSPATH 中了。如果不打算用 POP3,就不必将 pop3.jar 添加到 CLASSPATH 中去。

如果您不想更改 CLASSPATH 环境变量,将 jar 文件复制到您 Java 运行时环境(Java Runtime EnvironmentJRE)目录下的 lib/ext 目录中去。例如,J2SE 1.3 发行版的缺省目录在 Windows 平台的 C:/jdk1.3/jre/lib/ext

如果您使用 J2EE,就没有什么特定的事非要用基本 JavaMail API 来做不可;J2EE 的类就能处理了。只要确保 j2ee.jar 文件已在您的CLASSPATH 中并已全部设置好。

练习 1. 如何设置 JavaMail 环境

在这个练习中,您将安装 Sun JavaMail 相关工具。安装结束后,将介绍符合参考实现的演示程序。

任务 1请下载 Sun JavaMail API 实现 的最新版本。

任务 2请下载 Sun JavaBeans Activation Framework 的最新版本。

任务 3解压缩下载的软件包。您就得到能支持所有平台的两个包的 ZIP 文件。

任务 3 的帮助:你可以使用 jar 工具将包解压缩。

任务 4 JavaMail 1.2 下载软件包中的 mail.jar 文件以及 JavaBeans Activation Framework 下载软件包中的 activation.jar 文件添加到您的 CLASSPATH 中。

任务 4 的帮助:将文件复制到您的扩展库目录下面。Microsoft Windows 的用户使用缺省的安装复制,可输入如下命令:

cd /javamail-1.2

copy mail.jar /jdk1.3/jre/lib/ext

cd /jaf- 1.0.1

copy activation.jar /jdk1.3/jre/lib/ext

如果您不愿意将文件复制到扩展库目录,Sun 提供在 Windows NT 上设置 CLASSPATH 详细指导

任务 5进入 JavaMail API 工具的 demo 目录,编译 msgsend 程序以发送一条测试消息。

任务 5 的帮助:

javac msgsend.java

 

任务 6执行程序,用 -o 选项传入 from 地址、用 -M 选项传入 SMTP 服务器,还有传入 to 地址(没有选项)。然后,您输入主题,消息正文和文件结束符(CTRL-Z)标志消息输入结束。

任务 6 的帮助:务必替换 from 地址、SMTP 服务器和 to 地址。

java msgsend -o from@address -M SMTP.Server to@address

如果您不能确定您的 SMTP 服务器,请联系您的系统管理员或与您的互联网服务供应商核对。

任务 7
用您的标准邮件阅读程序(EudoraOutlook Expresspine...)检查,确保消息已收到。

JavaMail核心类概览:

在采用深入探索 JavaMail 类的入门方法前,这一章向您展示构成 API 的核心类:SessionMessageAddressAuthenticatorTransportStore Folder。尽管您常会发现自己使用的子类在 javax.mail.internet 中,但上述这些类却放在 JavaMail API的顶级包 javax.mail 里。

Session

Session类定义了一个基本邮件会话(session)。所有其它类都是经由这个session 才得以生效。Session对象用 java.util.Properties 对象获取信息,如邮件服务器、用户名、密码及整个应用程序中共享的其它信息。

类的构造器是私有的(private)。您可以得到单个缺省 session,它能用 getDefaultInstance() 方法被共享:

Properties props = new Properties();

// fill props with any information

Session session = Session.getDefaultInstance(props, null);

或者,您还可以用 getInstance() 创建一个独立的 session

Properties props = new Properties();

// fill props with any information

Session session = Session.getDefaultInstance(props, null);

对于这两种情况,null参数都是 Authenticator 对象(在这次没有使用)。

对于大多数情况,共享的 session 已经够用了,即使要处理多个用户邮箱的邮件 session 也一样。您可以在通信过程中稍后的步骤加入用户名和密码组合,让一切保持独立。

Message

一旦获得 Session 对象,就可以继续创建要发送的消息。这由 Message 类来完成。因为 Message 是个抽象类,您必需用一个子类,多数情况下为 javax.mail.internet.MimeMessageMimeMessage是个能理解 MIME 类型和头的电子邮件消息,正如不同 RFC 中所定义的。虽然在某些头部域非 ASCII 字符也能被译码,但 Message 头只能被限制为用 US-ASCII 字符。

要创建一个 Message,请将 Session 对象传递给 MimeMessage 构造器:

MimeMessage message = new MimeMessage(session);

注意:还存在其它构造器,如用按 RFC822 格式的输入流来创建消息。

一旦获得消息,您就可以设置各个部分,因为 Message 实现 Part 接口(且 MimeMessage 实现 MimePart )。设置内容的基本机制是 setContent() 方法,同时使用参数,分别代表内容和 mime 类型:

message.setContent("Hello", "text/plain");

但如果,您知道您在使用 MimeMessage,而且消息是纯文本格式,您就可以用 setText() 方法,它只需要代表实际内容的参数,( MIME 类型缺省为 text/plain):

 

message.setText("Hello");

后一种格式是设置纯文本消息内容的首选机制。至于发送其它类型的消息,如 HTML 文件格式的消息,我们首选前者。

setSubject() 方法设置 subject(主题):

 

message.setSubject("First");

Address

一旦您创建了 Session Message,并将内容填入消息后,就可以用 Address确定信件地址了。和 Message 一样,Address也是个抽象类。您用的是 javax.mail.internet.InternetAddress 类。

若创建的地址只包含电子邮件地址,只要传递电子邮件地址到构造器就行了。

Address address = new InternetAddress("president@whitehouse.gov");

若希望名字紧挨着电子邮件显示,也可以把它传递给构造器:

Address address = new InternetAddress("president@whitehouse.gov", "George Bush");

需要为消息的 from 域和 to 域创建地址对象。除非邮件服务器阻止,没什么能阻止你发送一段看上去是来自任何人的消息。

一旦创建了 address(地址),将它们与消息连接的方法有两种。如果要识别发件人,您可以用 setFrom() setReplyTo() 方法。

message.setFrom(address)

 

需要消息显示多个 from 地址,可以使用 addFrom() 方法:

 

Address address[] = ...;

message.addFrom(address);

 

若要识别消息 recipient(收件人),您可以使用 addRecipient() 方法。除 address(地址)外,这一方法还请求一个 Message.RecipientType

 

message.addRecipient(type, address)

 

三种预定义的地址类型是:

·         Message.RecipientType.TO

·         Message.RecipientType.CC

·         Message.RecipientType.BCC

如果消息是发给副总统的,同时发送一个副本(carbon copy)给总统夫人,以下做法比较恰当:

Address toAddress = new InternetAddress("vice.president@whitehouse.gov");

Address ccAddress = new InternetAddress("first.lady@whitehouse.gov");

message.addRecipient(Message.RecipientType.TO, toAddress);

message.addRecipient(Message.RecipientType.CC, ccAddress);

 

JavaMail API 没有提供电子邮件地址有效性核查机制。虽然通过编程,自己能够扫描有效字符(如 RFC 822 中定义的)或验证邮件交换(mail exchangeMX)记录,但这些功能不属于 JavaMail API

Authenticator

java.net 类一样,JavaMail API 也可以利用 Authenticator 通过用户名和密码访问受保护的资源。对于JavaMail API 来说,这些资源就是邮件服务器。JavaMail Authenticator javax.mail 包中,而且它和 java.net 中同名的类 Authenticator 不同。两者并不共享同一个 Authenticator,因为JavaMail API 用于 Java 1.1,它没有 java.net 类别。

要使用 Authenticator,先创建一个抽象类的子类,并从 getPasswordAuthentication() 方法中返回 PasswordAuthentication实例。创建完成后,您必需向 session 注册 Authenticator。然后,在需要认证的时候,就会通知 Authenticator。您可以弹出窗口,也可以从配置文件中(虽然没有加密是不安全的)读取用户名和密码,将它们作为 PasswordAuthentication 对象返回给调用程序。

Properties props = new Properties();

// fill props with any information

Authenticator auth = new MyAuthenticator();

Session session = Session.getDefaultInstance(props, auth);

Transport

消息发送的最后一部分是使用 Transport 类。这个类用协议指定的语言发送消息(通常是 SMTP)。它是抽象类,它的工作方式与 Session 有些类似。仅调用静态 send() 方法,就能使用类的缺省版本:

Transport.send(message);

或者,您也可以从针对您的协议的会话中获得一个特定的实例,传递用户名和密码(如果不必要就不传),发送消息,然后关闭连接。

message.saveChanges(); // implicit with send()

Transport transport = session.getTransport("smtp");

transport.connect(host, username, password);

transport.sendMessage(message, message.getAllRecipients());

transport.close();

 

后面这种方法在您要发送多条消息时最好,因为它能保持邮件服务器在消息间的活动状态。基本 send() 机制为每个方法的调用设置与服务器独立的连接。

注意:要观察传到邮件服务器上的邮件命令,请用 session.setDebug(true) 设置调试标志。

Store Folder

Session 获取消息与发送消息开始很相似。但是,在 session 得到后,很可能使用用户名和密码或使用 Authenticator 连接到一个 Store。类似于 Transport ,您告知 Store 使用什么协议:

// Store store = session.getStore("imap");

Store store = session.getStore("pop3");

store.connect(host, username, password);

 

连接到 Store 之后,接下来,您就可以获取一个 Folder,您必需先打开它,然后才能读里面的消息。

 

Folder folder = store.getFolder("INBOX");

folder.open(Folder.READ_ONLY);

Message message[] = folder.getMessages();

 

POP3 唯一可以用的文件夹是 INBOX。如果使用 IMAP,还可以用其它文件夹。

注意:Sun 的供应商有意变得聪明。虽然 Message message[] = folder.getMessages(); 看上去是个很慢的操作,它从服务器上读取每一条消息,但仅在你实际需要消息的一部分时,消息的内容才会被检索。

一旦有了要读的 Message,您可以用 getContent() 来获取其内容,或者用 writeTo() 将内容写入流。getContent()方法只能得到消息内容,而 writeTo() 的输出却包含消息头。

 

System.out.println(((MimeMessage)message).getContent());

 

一旦读完邮件,要关闭与 folder store 的连接。

 

folder.close(aBoolean);

store.close();

 

传递给 folder close() 方法的 boolean 表示是否清除已删除的消息从而更新 folder

基本上,对于 JavaMail API 差不多所有内容,了解如何使用这七个类已经足够。JavaMail API 其它功能建立在这七个类的基础上,它们做的事稍有不同,或者方法独特,如内容是附件的情况。某些如搜索之类的任务,是个别情况,我们稍候讨论。

使用JavaMail API

您已经了解如何运用 JavaMail API 的核心部分。在接下来的章节,您会看到如何连接从而实现给定任务块的入门方法。

发送消息

发送电子邮件消息这一过程包括获取一个会话,创建并填充一则消息,然后发送。得到 Session 时,经由设置传递的 Properties 对象中的 mail.smtp.host 属性,可以指定您的 SMTP 服务器:

String host = ...;

String from = ...;

String to = ...;

 

// Get system properties

Properties props = System.getProperties();

 

// Setup mail server

props.put("mail.smtp.host", host);

 

// Get session

Session session = Session.getDefaultInstance(props, null);

 

// Define message

MimeMessage message = new MimeMessage(session);

message.setFrom(new InternetAddress(from));

message.addRecipient(Message.RecipientType.TO,

 new InternetAddress(to));

 message.setSubject("Hello JavaMail");

 message.setText("Welcome to JavaMail");

 

 // Send message

 Transport.send(message);

 

您应该将代码放在一个 try-catch 程序块中,这样创建和发送消息时就能够抛出异常。

练习 2. 如何发送第一条消息

在上一个练习中,您使用 JavaMail 实现提供的演示程序发送了一条邮件消息。在这个练习中,您将亲自创建程序。

需要更多练习的帮助,请参阅关于练习

先决条件:

·         练习 1. 如何设置 JavaMail 环境

框架代码:

·         MailExample.java

任务 1
参照框架代码开始着手,获取系统 Properties

任务 1 的帮助:

Properties props = System.getProperties();

 

任务 2
将您的 SMTP 服务器名添加到 mail.smtp.host 关键字的属性中。

任务 2 的帮助:

props.put("mail.smtp.host", host);

 

任务 3
获取基于 Properties Session 对象。

任务 3 的帮助:

Session session = Session.getDefaultInstance(props, null);

 

任务 4
session 创建一个 MimeMessage

任务 4 的帮助:

 

MimeMessage message = new MimeMessage(session);

 

任务 5
设置消息的 from 域。

任务 5 的帮助:

message.setFrom(new InternetAddress(from));

 

任务 6
设置消息的 to 域。

任务 6 的帮助:

message.addRecipient(Message.RecipientType.TO,

      new InternetAddress(to));

 

任务 7
设置消息主题。

任务 7 的帮助:

message.setSubject("Hello JavaMail");

 

任务 8
设置消息内容。

任务 8 的帮助:

message.setText("Welcome to JavaMail");

 

任务 9
Transport 发送消息。

任务 9 的帮助:

Transport.send(message);

 

任务 10
在命令行上编译并运行程序传递 SMTP 服务器、 from 地址和 to 地址。

任务 10 的帮助:

java MailExample SMTP.Server from@address to@address

 

任务 11
用标准邮件阅读程序(EudoraOutlook Expresspine...)检查,确保消息已收到。

import java.util.Properties;

import javax.mail.*;

import javax.mail.internet.*;

public class MailExample {

 public static void main (String args[]) throws Exception {

    String host = args[0];

    String from = args[1];

    String to = args[2];

    // Get system properties

    Properties props = System.getProperties();

    // Setup mail server

    props.put("mail.smtp.host", host);

    // Get session

    Session session = Session.getDefaultInstance(props, null);

    // Define message

    MimeMessage message = new MimeMessage(session);

    // Set the from address

    message.setFrom(new InternetAddress(from));

    // Set the to address

    message.addRecipient(Message.RecipientType.TO,

      new InternetAddress(to));

    // Set the subject

    message.setSubject("Hello JavaMail");

    // Set the content

    message.setText("Welcome to JavaMail");

    // Send message

    Transport.send(message);

 }

}

消息的提取

为读邮件,您获取一个会话,获取并连接一个用于邮箱的适宜的存储(store),打开适宜的文件夹,然后获取您的消息。同样,切记完成后关闭连接。

 

 String host = ...;

 String username = ...;

 String password = ...;

 

 // Create empty properties

 Properties props = new Properties();

 

 // Get session

 Session session = Session.getDefaultInstance(props, null);

 

 // Get the store

 Store store = session.getStore("pop3");

 store.connect(host, username, password);

 

 // Get folder

 Folder folder = store.getFolder("INBOX");

 folder.open(Folder.READ_ONLY);

 

 // Get directory

 Message message[] = folder.getMessages();

 

 for (int i=0, n=message.length; i<n; i++) {

     System.out.println(i + ": " + message[i].getFrom()[0]

          + "/t" + message[i].getSubject());

          }

 

          // Close connection

          folder.close(false);

          store.close();

 

对每条消息做些什么由您决定。上面的代码块只是显示这些消息的发件人和主题。技术上讲,from地址列表可能为空,而 getFrom()[0] 调用会抛出一个异常。

要显示全部信息,您可以在用户看完 from subject 域之后给出提示,如用户有需要,就调用消息的 writeTo() 方法来实现。

 

          BufferedReader reader = new BufferedReader (

            new InputStreamReader(System.in));

 

          // Get directory

          Message message[] = folder.getMessages();

          for (int i=0, n=message.length; i<n; i++) {

            System.out.println(i + ": " + message[i].getFrom()[0]

              + "/t" + message[i].getSubject());

 

            System.out.println("Do you want to read message? " +

              "[YES to read/QUIT to end]");

            String line = reader.readLine();

            if ("YES".equals(line)) {

              message[i].writeTo(System.out);

            } else if ("QUIT".equals(line)) {

              break;

            }

          }

 

练习 3. 如何检查邮件

在这个练习中,我们创建了一个程序,它能够显示每条消息的 from 地址和主题,并提示消息内容的显示。

需要更多练习的帮助,请参阅关于练习.

先决条件:

·         练习 1. 如何设置 JavaMail 环境

框架代码

·         GetMessageExample.java

任务 1
参考框架代码开始着手,获取(或说创建)一个 Properties 对象。

任务 1 的帮助:

Properties props = new Properties();

 

任务 2
获取基于 Properties Session 对象。

任务 2 的帮助:

Session session = Session.getDefaultInstance(props, null);

 

任务 3
获取电子邮件协议 pop3 imap Store

任务 3 的帮助:

Store store = session.getStore("pop3");

 

任务 4
用恰当的用户名和密码连接到您的邮件主机的 store

任务 4 的帮助:

store.connect(host, username, password);

 

任务 5
获取您要读的 folder。很可能会是 INBOX

任务 5 的帮助:

Folder folder = store.getFolder("INBOX");

 

任务 6
以只读方式打开 folder

任务 6 的帮助:

folder.open(Folder.READ_ONLY);

 

任务 7
获取一个 folder 中的消息目录。将消息列表保存在名为 message 的数组变量中。

任务 7 的帮助:

Message message[] = folder.getMessages();

 

任务 8
显示每条消息的 from 域和主题。

任务 8 的帮助:

System.out.println(i + ": " + message[i].getFrom()[0]

 + "/t" + message[i].getSubject());

 

任务 9
在提示时显示消息内容。

任务 9 的帮助:

System.out.println(message[i].getContent());

 

任务 10
关闭到 folder store 的连接。

任务 10 的帮助:

folder.close(false);

store.close();

 

任务 11
在命令行上编译并运行程序传递 SMTP 服务器、用户名和密码。对于想要阅读的消息,以 YES 响应。反之,敲击 ENTER。如果想在读完所有消息前中止,可以输入 QUIT

任务 11 的帮助:

java GetMessageExample POP.Server username password

 

import java.io.*;

import java.util.Properties;

import javax.mail.*;

import javax.mail.internet.*;

 

public class GetMessageExample {

 public static void main (String args[]) throws Exception {

    String host = args[0];

    String username = args[1];

    String password = args[2];

 

    // Create empty properties

    Properties props = new Properties();

 

    // Get session

    Session session = Session.getDefaultInstance(props, null);

 

    // Get the store

    Store store = session.getStore("pop3");

 

    // Connect to store

    store.connect(host, username, password);

 

    // Get folder

    Folder folder = store.getFolder("INBOX");

 

    // Open read-only

    folder.open(Folder.READ_ONLY);

 

    BufferedReader reader = new BufferedReader (

      new InputStreamReader(System.in));

 

    // Get directory

    Message message[] = folder.getMessages();

 

    for (int i=0, n=message.length; i<n; i++) {

 

       // Display from field and subject

       System.out.println(i + ": " + message[i].getFrom()[0]

         + "/t" + message[i].getSubject());

 

      System.out.println("Do you want to read message? [YES to read/QUIT to end]");

      String line = reader.readLine();

      if ("YES".equals(line)) {

 

        // Display message content

        System.out.println(message[i].getContent());

 

      } else if ("QUIT".equals(line)) {

        break;

      }

    }

 

    // Close connection

    folder.close(false);

    store.close();

 }

}

消息和标志的删除

消息的删除涉及使用与消息相关的 Flags(标志)。不同 flag 对应不同的状态,有些由系统定义而有些则由用户定义。下面列出在内部类 Flags.Flag 中预定义的标志:

·         Flags.Flag.ANSWERED

·         Flags.Flag.DELETED

·         Flags.Flag.DRAFT

·         Flags.Flag.FLAGGED

·         Flags.Flag.RECENT

·         Flags.Flag.SEEN

·         Flags.Flag.USER

仅仅因为存在一个标志,并不意味着所有邮件服务器或供应商都支持这个标志。例如,除了删除消息标志外,POP 协议不再支持其它任何标志。检查是否存在邮件,这不是个 POP 任务,而是内建于邮件客户机的任务。为找出哪些标志能被支持,可以用 getPermanentFlags() folder 提出要求。

要删除消息,您可以设置消息的 DELETED flag

 

message.setFlag(Flags.Flag.DELETED, true);

 

首先,请以 READ_WRITE 模式打开 folder

 

folder.open(Folder.READ_WRITE);

 

然后,当所有消息的处理完成后,关闭 folder,并传递一个 true 值,从而擦除(expunge delete 标志的消息。

 

folder.close(true);

 

一个 Folder expunge() 方法可以用来删除消息。但 Sun POP3 供应商不支持。其它供应商有的或许能够实现这一功能,而有的则不能。IMAP 供应商极有可能实现此功能。因为 POP 只支持单个对邮箱的访问,对 Sun 的供应商来说,您必需关闭 folder 以删除消息。

要取消标志,只要传递 false setFlag() 方法就行了。想知道是否设置过标志,可以用 isSet() 检查。

亲自认证

您已经知道如果需要可以用一个 Authenticator 提示用户输入用户名和密码,而不是将用户名和密码作为字符串传递。在这里您会明确了解怎样更充分的使用认证。

不用主机、用户名和密码与 Store 相连接,而是设置 Properties 来拥有主机,然后告诉 Session 自定义的 Authenticator 实例,如下所示:

 

// Setup properties

Properties props = System.getProperties();

props.put("mail.pop3.host", host);

 

// Setup authentication, get session

Authenticator auth = new PopupAuthenticator();

Session session = Session.getDefaultInstance(props, auth);

 

// Get the store

Store store = session.getStore("pop3");

store.connect();

 

然后,您创建一个 Authenticator 子类并从 getPasswordAuthentication() 方法中返回 PasswordAuthentication 对象。下面就是这样一种实现,其中用户名和密码仅占用一个域。(这不是一个 Swing 工程教程;只要将两部分输入同一个域,用逗号分隔就行。)

 

import javax.mail.*;

import javax.swing.*;

import java.util.*;

 

public class PopupAuthenticator extends Authenticator {

 

 public PasswordAuthentication getPasswordAuthentication() {

    String username, password;

 

    String result = JOptionPane.showInputDialog(

      "Enter 'username,password'");

 

    StringTokenizer st = new StringTokenizer(result, ",");

    username = st.nextToken();

    password = st.nextToken();

 

    return new PasswordAuthentication(username, password);

 }

 

}

因为 PopupAuthenticator 涉及到 Swing,它会启动 AWT 的事件处理线程。这一点基本上要求您在代码中添加一个对 System.exit() 的调用来终止程序。

消息的回复

Message类引入一个 reply() 方法来配置一个新 Message,包括正确的 recipient(收件人)和添加“Re”(如果没有就添加)的正确的 subject。这样做并没有为消息添加新内容,仅仅将 from reply-to(被回复人)头复制给新的收件人。这种方法用一个 boolean 参数指定消息只回复给发件人(false)或回复给全体(true)。

 

MimeMessage reply = (MimeMessage)message.reply(false);

reply.setFrom(new InternetAddress("president@whitehouse.gov"));

reply.setText("Thanks");

Transport.send(reply);

 

在发送消息时要配置 reply to(被回复人)地址,可以用 setReplyTo() 方法。

 

练习 4. 如何回复邮件

在这个练习中,我们创建了一个程序,它能够创建一个固定格式的回复消息,并将纯文本的原始消息附加到消息中。

需要更多练习的帮助,请参阅关于练习

先决条件:

·         练习 3. 如何检查邮件

框架代码:

·         ReplyExample.java

任务 1
框架代码
中已含有代码,以便从 folder 中获取消息清单并提示您创建一条回复消息。

任务 2
如果回答,则基于原始消息创建一个新的 MimeMessage

任务 2 的帮助:

MimeMessage reply = (MimeMessage)message[i].reply(false);

 

任务 3
在您的电子邮件地址上设置 from 域。

任务 4
创建要回复的文本。从引入固定格式的消息开始。若原始消息是纯文本,就在原始消息的每行前添加"> " 字符并添加到回复的消息中。

任务 4 的帮助:
对于纯文本消息,请用 mimeMessage.isMimeType("text/plain") 检查 MIME 类型。

任务 5
一旦消息内容已完全确定,就可以对其进行设置。

任务 6
发送消息。

任务 7
在命令行上编译并运行程序传递邮件服务器、 SMTP 服务器、用户名、密码以及 from 地址。对您将回复的消息,响应 YES。反之,敲击 ENTER。如果想在回复完所有消息前中止,可以输入 QUIT

任务 7 的帮助:

 

java ReplyExample POP.Server SMTP.Server username password from@address

 

任务 8
请检查以确认用标准邮件阅读程序(EudoraOutlook Expresspine...)收到了消息。

import java.io.*;

import java.util.Properties;

import javax.mail.*;

import javax.mail.internet.*;

 

publicclass ReplyExample {

 publicstaticvoid main (String args[]) throws Exception {

    String host = args[0];

    String sendHost = args[1];

    String username = args[2];

    String password = args[3];

    String from = args[4];

 

    // Create empty properties

    Properties props = System.getProperties();

    props.put("mail.smtp.host", sendHost);

 

    // Get session

    Session session = Session.getDefaultInstance(props, null);

 

    // Get the store

    Store store = session.getStore("pop3");

    store.connect(host, username, password);

 

    // Get folder

    Folder folder = store.getFolder("INBOX");

    folder.open(Folder.READ_ONLY);

 

    BufferedReader reader = new BufferedReader (

      new InputStreamReader(System.in));

 

    // Get directory

    Message message[] = folder.getMessages();

    for (int i=0, n=message.length; i<n; i++) {

       System.out.println(i + ": " + message[i].getFrom()[0]

         + "/t" + message[i].getSubject());

 

      System.out.println("Do you want to reply to the message? [YES to reply/QUIT to end]");

      String line = reader.readLine();

      if ("YES".equals(line)) {

 

        // Create a reply message

        MimeMessage reply = (MimeMessage)message[i].reply(false);

 

        // Set the from field

        reply.setFrom(new InternetAddress(from));

 

        // Create the reply content, copying over the original if text

        MimeMessage orig = (MimeMessage)message[i];

        StringBuffer buffer = new StringBuffer("Thanks/n/n");

        if (orig.isMimeType("text/plain")) {

          String content = (String)orig.getContent();

          StringReader contentReader = new StringReader(content);

          BufferedReader br = new BufferedReader(contentReader);

          String contentLine;

          while ((contentLine = br.readLine()) != null) {

            buffer.append("> ");

            buffer.append(contentLine);

            buffer.append("/r/n");

          }

        }

 

        // Set the content

        reply.setText(buffer.toString());

 

        // Send the message

        Transport.send(reply);

 

      } elseif ("QUIT".equals(line)) {

        break;

      }

    }

 

    // Close connection

    folder.close(false);

    store.close();

 }

}

附件的处理

附件是邮件消息的相关资源,如通常不包含在消息正文里文本文件、电子表格或图像等。常见的邮件程序,如 Eudora pine 之类,可以用 JavaMail API 将资源 attach(附加)到您的消息上,就可以在收到消息时得到。

附件的发送:
发送附件非常像转发消息。您建立各部分以组成完整消息。完成第一部件,即消息正文后,您添加其它部件,其中每个 DataHandler 都代表附件,而不是转发消息情况下的共享处理程序。如果从文件中读附件,附件的数据源是 FileDataSource。而如果从 URL 中读时,附件的数据源是 URLDataSource。一旦存在 DataSource,只要先把它传递给 DataHandler 构造器,最后再用 setDataHandler() 把它附加到 BodyPart。假定您要保留附件的原始文件名,最终要做的是用 BodyPart setFileName() 方法设置与附件相关的文件名。如下所示:

 

 // Define message

 Message message = new MimeMessage(session);

 message.setFrom(new InternetAddress(from));

 message.addRecipient(Message.RecipientType.TO,

    new InternetAddress(to));

 message.setSubject("Hello JavaMail Attachment");

 

 // Create the message part

 BodyPart messageBodyPart = new MimeBodyPart();

 

 // Fill the message

 messageBodyPart.setText("Pardon Ideas");

 

 Multipart multipart = new MimeMultipart();

 multipart.addBodyPart(messageBodyPart);

 

 // Part two is attachment

 messageBodyPart = new MimeBodyPart();

 DataSource source = new FileDataSource(filename);

 messageBodyPart.setDataHandler(new DataHandler(source));

 messageBodyPart.setFileName(filename);

 multipart.addBodyPart(messageBodyPart);

 

 // Put parts in message

 message.setContent(multipart);

 

 // Send the message

 Transport.send(message);

 

就消息引入附件时,若程序是个 servlet (小服务程序),除告知消息发送到何处外,还必需上载附件。可以将 multipart/form-data 表单编码类型(form encoding type)用于每个上载文件的处理。

 

<FORM ENCTYPE="multipart/form-data"

    method=post action="/myservlet">

 <INPUT TYPE="file" NAME="thefile">

 <INPUT TYPE="submit" VALUE="Upload">

</FORM>

 

注意:消息大小由 SMTP 服务器而不是 JavaMail API 来限制。如果您碰到问题,可以考虑用设置 ms mx 参数的方法增大 Java 堆大小。

练习:
练习 5. 如何发送附件

附件的获取:
从消息中获取附件比发送它们棘手些,因为 MIME 没有简单的关于附件的概念。当消息包含附件时,消息的内容是个 Multipart 对象。接着,您需要处理每个 Part,获取主要内容和附件。标有从 part.getDisposition() 获得的 Part.ATTACHMENT 配置(disposition)的部件(Part)无疑就是附件。但是,没有配置(以及一个非文本 MIME 类型)和带 Part.INLINE 配置的部件也可能是附件。当配置要么是 Part.ATTACHMENT,要么是 Part.INLINE 时,这个消息部件的内容就能被保存。只要用 getFileName() getInputStream() 就能分别得到原始文件名和输入流。

 

Multipart mp = (Multipart)message.getContent();

 

for (int i=0, n=multipart.getCount(); i<n; i++) {

 Part part = multipart.getBodyPart(i));

 

 String disposition = part.getDisposition();

 

 if ((disposition != null) &&

       ((disposition.equals(Part.ATTACHMENT) ||

          (disposition.equals(Part.INLINE))) {

    saveFile(part.getFileName(), part.getInputStream());

 }

}

 

saveFile()方法仅依据文件名创建了一个 File,它从输入流中将字节读出,然后写入到文件中。万一文件已经存在,就在文件名后添加一个数字作为新文件名,如果这个文件名仍存在,则继续添,直到找不到这样的文件名为止。

 

// from saveFile()

File file = new File(filename);

for (int i=0; file.exists(); i++) {

 file = new File(filename+i);

}

 

上面的代码涵盖了最简单的情况消息中各部件恰当的标记了。要涵盖所有情况,还要在配置为空时进行处理,并且获取部件的 MIME 类型来进行相应处理。

 

if (disposition == null) {

 // Check if plain

 MimeBodyPart mbp = (MimeBodyPart)part;

 if (mbp.isMimeType("text/plain")) {

     // Handle plain

 } else {

     // Special non-attachment cases here of image/gif, text/html, ...

 }

 ...

}

 

练习 5. 如何发送附件

在这个练习中,我们创建了一个程序,它能够发送含附件的消息。

需要更多练习的帮助,请参阅关于练习

先决条件:

·         练习 2. 如何发送第一条消息

框架代码:

·         AttachExample.java

任务 1
skeleton code
中已经包含代码以获取初始邮件 session

任务 2
根据 session 获取一个 Message 并设置它的头部域:tofrom subject(主题)。

任务 3
为消息正文内容创建 BodyPart,并以消息正文为内容。

任务 3 的帮助:

BodyPart messageBodyPart = new MimeBodyPart();

messageBodyPart.setText("Here's the file");

 

任务 4
创建一个 Multipart 从而将正文内容和附件结合。将正文内容添加到 multipart 中。

任务 4 的帮助:

Multipart multipart = new MimeMultipart();

multipart.addBodyPart(messageBodyPart);

 

任务 5
为附件创建第二个 BodyPart

任务 6
获取作为 DataSource 的附件。

任务 6 的帮助:

DataSource source = new FileDataSource(filename);

 

任务 7
?
将数据源设置为消息部分的 DataHandler。同时设置原始文件名。

任务 7 的帮助:

 

messageBodyPart.setDataHandler(new DataHandler(source));

messageBodyPart.setFileName(filename);

 

任务 8
将消息的第二部件添加到 multipart

任务 9
将消息内容设置成 multipart

任务 9 的帮助:

message.setContent(multipart);

 

任务 10
发送消息。

任务 11
在命令行上编译并运行程序传递 SMTP 服务器、from地址、to地址和文件名。这就以附件形式发送了您的文件。

任务 11 的帮助:

java AttachExample SMTP.Server from@address to@address filename

 

任务 12
请用您的标准邮件阅读程序(EudoraOutlook Expresspine...)检查,确保消息已收到。

import java.util.Properties;

import javax.mail.*;

import javax.mail.internet.*;

import javax.activation.*;

public class AttachExample {

 public static void main (String args[]) throws Exception {

    String host = args[0];

    String from = args[1];

    String to = args[2];

    String filename = args[3];

    // Get system properties

    Properties props = System.getProperties();

    // Setup mail server

    props.put("mail.smtp.host", host);

    // Get session

    Session session = Session.getInstance(props, null);

    // Define message

    Message message = new MimeMessage(session);

    message.setFrom(new InternetAddress(from));

    message.addRecipient(Message.RecipientType.TO,

      new InternetAddress(to));

    message.setSubject("Hello JavaMail Attachment");

    // Create the message part

    BodyPart messageBodyPart = new MimeBodyPart();

    // Fill the message

    messageBodyPart.setText("Here's the file");

    // Create a Multipart

    Multipart multipart = new MimeMultipart();

    // Add part one

    multipart.addBodyPart(messageBodyPart);

    //

    // Part two is attachment

    //

    // Create second body part

    messageBodyPart = new MimeBodyPart();

    // Get the attachment

    DataSource source = new FileDataSource(filename);

    // Set the data handler to the attachment

    messageBodyPart.setDataHandler(new DataHandler(source));

    // Set the filename

    messageBodyPart.setFileName(filename);

    // Add part two

    multipart.addBodyPart(messageBodyPart);

    // Put parts in message

    message.setContent(multipart);

    // Send the message

    Transport.send(message);

 }

}

HTML 消息的处理

发送基于 HTML 文件格式消息的工作量比发送纯文本消息多,虽然不一定非要这些多余的工作量。如何选择完全取决于给定的请求。

HTML 消息的发送:
若您所要做的全部事情是发送一份 HTML 文件的等价物作为消息,但让邮件阅读者为不能提取任何内嵌图像或相关片段而担心的话,可以使用 Message setContent() 方法,把内容当作一个 String 传入,并将内容类型设置成 text/html

 

String htmlText = "<H1>Hello</H1>" +

 "<img src=/"http://www.jguru.com/images/logo.gif/">";

message.setContent(htmlText, "text/html"));

 

在接收端,如果您用 JavaMail API 提取消息,API 中没有内建的显示 HTML 消息的东西。 JavaMail API 只把它看成一串字节流。要显示 HTML 文件格式的消息,您必需使用 Swing JEditorPane 或其它第三方 HTML 格式查看器组件。

 

if (message.getContentType().equals("text/html")) {

    String content = (String)message.getContent();

    JFrame frame = new JFrame();

    JEditorPane text = new JEditorPane("text/html", content);

    text.setEditable(false);

    JScrollPane pane = new JScrollPane(text);

    frame.getContentPane().add(pane);

    frame.setSize(300, 300);

    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    frame.show();

}

 

在消息中引入图像:
另一方面,如果您想让 HTML 文件格式内容的消息完整(内嵌的图像作为消息的一部分),您必需把图像作为附件,并且用一个给定的 cid URL 引用图像,其中 cid 是图像附件 Content-ID 头的引用。

嵌入图像的过程与附加文件到消息的过程非常相似,唯一的区别在于您必需通过设置 MimeMultipart 构造器中的子类型(或者说用 setSubType())告知 MimeMultipart 各个相关部件,并且将这个图像的 Content-ID 头设置成随机字符串,作为图像的 src img 标记中使用。完整的演示如下。

 

String file = ...;

 

// Create the message

Message message = new MimeMessage(session);

 

// Fill its headers

message.setSubject("Embedded Image");

message.setFrom(new InternetAddress(from));

message.addRecipient(Message.RecipientType.TO,

 new InternetAddress(to));

 

// Create your new message part

BodyPart messageBodyPart = new MimeBodyPart();

String htmlText = "<H1>Hello</H1>" +

 "<img src=/"cid:memememe/">";

messageBodyPart.setContent(htmlText, "text/html");

 

// Create a related multi-part to combine the parts

MimeMultipart multipart = new MimeMultipart("related");

multipart.addBodyPart(messageBodyPart);

 

// Create part for the image

messageBodyPart = new MimeBodyPart();

 

// Fetch the image and associate to part

DataSource fds = new FileDataSource(file);

messageBodyPart.setDataHandler(new DataHandler(fds));

messageBodyPart.setHeader("Content-ID","memememe");

 

// Add part to multi-part

multipart.addBodyPart(messageBodyPart);

 

// Associate multi-part with message

message.setContent(multipart);

 

练习 6. 如何发送含图像的 HTML 消息

在这个练习中,我们创建了一个程序,它能够发送含图像附件(图像显示在 HTML 消息内部)的 HTML 消息。

需要更多练习的帮助,请参阅关于练习

先决条件:

·         练习 5. 如何发送附件

框架代码:

·         logo.gif

·         HtmlImageExample.java

任务 1
框架代码
已经包含代码以获取初始邮件 session、创建消息正文以及填充消息头(tofrom subject)。

任务 2
创建一个 HTML 文件格式消息内容的 BodyPart

任务 3
创建一个 HTML 文件格式内容的文本字符串。在 HTML 文件中引入一个图像的引用(<img src="...">),它和邮件消息处于同一目录。

任务 3 的帮助:
使用一个 cid URL。图像的 content-id 可以稍后再定。

String htmlText = "<H1>Hello</H1>" +

 "<img src=/"cid:memememe/">";

 

任务 4
设置消息部件的内容。确保将 MIME 的类型定为 text/html

任务 4 的帮助:

messageBodyPart.setContent(htmlText, "text/html");

 

任务 5
创建一个 Multipart 从而将正文内容和附件结合。确保已指定相关部分。然后正文内容将添加到 multipart 中。

任务 5 的帮助:

MimeMultipart multipart = new MimeMultipart("related");

multipart.addBodyPart(messageBodyPart);

 

任务 6
为附件创建第二个 BodyPart

任务 7
获取作为 DataSource 的附件,并把消息部件的数据源设置为该 DataHandler

任务 8
设置 Content-ID 头,使 HTML 文件中给定的部件匹配图像引用。

任务 8 的帮助:

messageBodyPart.setHeader("Content-ID","memememe");

 

任务 9
将消息的第二部件添加到 multipart,并将消息的内容设置成 multipart

任务 10:
发送消息。

任务 11
在命令行上编译并运行程序传递 SMTP 服务器、from地址、to地址和文件名。这样会把图片当作 HTML 文本中内嵌的图片发送。

任务 11 的帮助:

java HtmlImageExample SMTP.Server from@address to@address filename

 

任务 12
请检查邮件阅读程序辨认出的消息是否为 HTML 格式文件,而且消息中显示的是图片,不是外部附件文件的链接。

任务 12 的帮助:
如果邮件阅读程序无法显示 HTML 格式文件的消息,可以考虑把它发给朋友(让他们试试)。

import java.util.Properties;

import javax.mail.*;

import javax.mail.internet.*;

import javax.activation.*;

public class HtmlImageExample {

 public static void main (String args[]) throws Exception {

    String host = args[0];

    String from = args[1];

    String to = args[2];

    String file = args[3];

    // Get system properties

    Properties props = System.getProperties();

 

    // Setup mail server

    props.put("mail.smtp.host", host);

    // Get session

    Session session = Session.getDefaultInstance(props, null);

    // Create the message

    Message message = new MimeMessage(session);

    // Fill its headers

    message.setSubject("Embedded Image");

    message.setFrom(new InternetAddress(from));

    message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

    // Create your new message part

    BodyPart messageBodyPart = new MimeBodyPart();

    // Set the HTML content, be sure it references the attachment

    String htmlText = "<H1>Hello</H1>" +

      "<img src=/"cid:memememe/">";

    // Set the content of the body part

    messageBodyPart.setContent(htmlText, "text/html");

    // Create a related multi-part to combine the parts

    MimeMultipart multipart = new MimeMultipart("related");

    // Add body part to multipart

    multipart.addBodyPart(messageBodyPart);

 

    // Create part for the image

    messageBodyPart = new MimeBodyPart();

    // Fetch the image and associate to part

    DataSource fds = new FileDataSource(file);

    messageBodyPart.setDataHandler(new DataHandler(fds));

    // Add a header to connect to the HTML

    messageBodyPart.setHeader("Content-ID","<memememe>");

    // Add part to multi-part

    multipart.addBodyPart(messageBodyPart);

    // Associate multi-part with message

    message.setContent(multipart);

    // Send message

    Transport.send(message);

 }

}

总结

JavaMail API 是一个 Java 包,用于阅读、编写及发送电子邮件消息(包括附件)。您能用它建立基于标准的电子邮件客户机,它配置了各种因特网邮件协议包括 SMTPPOPIMAP MIME,还包括相关的 NNTPS/MIME 及其它协议。

API 自然的划分为两个部件。第一部件着眼于独立于使用协议的发送、接收及管理消息,而第二部件则着眼于协议的特定用途。本教程的目的在于展示如何利用 API 的第一部分,并不试图涉及协议供应商。

核心 JavaMail API 由七个类组成SessionMessage AddressAuthenticatorTransportStore Folder它们都来自 javax.mail、即 JavaMail API 顶级包。我们用这些类完成了大量常见的电子邮件任务,包括发送消息、检索消息、删除消息、认证、回复消息、转发消息、管理附件、处理基于 HTML 文件格式的消息以及搜索或过滤邮件列表。

最后,提供了大量按部就班的练习来协助说明提出的概念。希望会有助于您将电子邮件功能性添加到独立于平台的 Java 应用程序。

JavaMail API,您所能做的比这里多得多。以下资源是这个课程和练习的补充:

·         JavaMail API home page 下载 JavaMail 1.2 API

·         JavaMail API 版本 1.2 1.1.3 需要JavaBeans Activation Framework 的支持。

·         JavaMail-interest mailing list Sun 的开发者论坛。

·         Sun JavaMail FAQ applet servlet 的形式提出了 JavaMail 的用途,还提出了特定于协议的问题。

·         教程作者 John Zukowski jGuru's JavaMail FAQ 站点进行维护。

·         想知道其它用户怎么使用 JavaMail 吗?请查看 Sun 第三方产品

·         如果您需要更多 JavaMail 的详细信息,请阅读 Rick Grehan "How JavaMail keeps it simple"Lotus Developer Network2000 6 月)。

·         Benoit Marchal 提出如何用 Java XML 实现纯文本及 HTML 文件格式的时事通讯,请参考这个由两部分组成的系列“Managing e-zines with JavaMail and XSLT”第一部分developerWorks2001 3 月)和 2 部分 developerWorks2001 4 月)。

·         "Linking Applications with E-mail"Lotus Developer Network2000 5 月)论述了群件如何促进应用程序间的交流、协作及配合。

 

 

 

 
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值