第第 88 章章 JJaavvaa MMaaiill//JJAAFF((未未完完成成)) JavaMail API 是一个用于阅读、编写和发送电子消息的可选包(标准扩展),可以用来建 立基于标准的电子邮件客户机,它支持各种因特网邮件协,包括 SMTP、POP、IMAP、MIME、 NNTP、S/MIME 及其它协议。JavaMail API 定义在 javax.mail 及其子包内。 通常开发 JavaMail 程序还需要有 Sun 的 JavaBeans Activation Framework(JAF)。JavaBeans Activation Framework 的运行很复杂,这里简单的说就是 JavaMail 的运行必须得依赖于它的支 持,比如 JavaMail 利用 JavaBeans Activation Framework 来处理 MIME 编码的邮件附件。 JavaMail 接口包含在 javax.mail 及其子包中,JavaBeans Activation Framework 接口包含在 javax.activation 包中,其规范是"Glasgow" JavaBeans Specification 的一部分。 本章将按如下如下顺序提供 Java Mail 与 JAF 技术参考。 • Java Mail 技术简介 • javax.activation 包 API 参考 • javax.mail 包 API 参考 • javax.mail.event 包 API 参考 • javax.mail.internet 包 API 参考 • javax.mail.search 包 API 参考 • Java Mail 案例参考 8.1 Java Mail 技术简介 JavaMail API 是一个用于阅读、编写和发送电子消息的可选包(标准扩展)。与 Eudora、 pine 及 Microsoft Outlook 相似,这个包用来创建邮件用户代理(Mail User Agent,MUA) 类 型程序,MUA 类型的程序能让用户阅读和书写邮件,而它依赖邮件传输代理(Mail Transfer Agent,简称 MTA)处理实际消息传输。 8.1.1 JavaMail 分层体系 JavaMail 体系可以分为如下三层,JavaMail API 包括抽象层和 Internet 邮件实现层。 • 抽象层:该层定义了用于邮件处理功能的抽象类、接口和抽象方法,所有的邮件系统 都支持这些功能,它独立于供应商和协议消息。抽象层位于 JavaMail 顶级包(即 javax.mail)内。 • Internet 邮件实现层:该层实现了部分抽象层元素,它遵循 Internet 标准——RFC822 和 MIME。Internet 邮件实现层所定义的类和接口大多位于 javax.mail.internet 包内。 • 协议实现层,该层由服务提供商实现对特定协议的支持,如 SMTP、POP、IMAP 和 J2EE 完全参考手册 (tsl0151@vip.sina.com) NNTP。Sun 为开发者提供了很完备的一组协议的支持。 图 2-1 描述了这种分层体系,JavaMail 客户机使用 JMS API,服务供应商提供 JMS API 的实现。这种体系确保无论使用哪种协议、由哪一家厂商提供对该协议的实现,JavaMail 客 户机都可以使用同样的 JavaMail API 收发邮件。 图 2-1 JavaMail 分层体系 8.1.2 JavaMail 主要对象 核心 JavaMail API 可以分为两部分,一部分由七个类组成:Session、Message、Address、 Authenticator、Transport、Store 及 Folder,它们都来自 JavaMail API 顶级包(但开发者需要 使用的具体子类可能在 javax.mail.internet 包内)。可以用这些类完成大量常见的电子邮件任 务,包括发送消息、检索消息、删除消息、认证、回复消息、转发消息、管理附件、处理基 于 HTML 文件格式的消息以及搜索或过滤邮件列表,这类任务主要属于 MTA 范畴。图 2-2 描绘了 JavaMail 邮件收发过程。 2 第 8 章 Java Mail 图 2-2 JavaMail 邮件收发过程 下面给出这七个核心类的简单介绍,以使读者能对 JavaMail 框架有一个大体了解,关于 这些类的深入说明读者可参考 8.3 节中各个类的介绍。 (1)javax.mail.Session Session 类定义了一个基本邮件会话,它是 Java Mail API 最高层入口类,所有其它类都 必须经由 Session 对象才得以生效。Session 对象管理配置选项和用于与邮件系统交互的用户 认证信息,它使用 Java.util.Properties 对象获取信息,如邮件服务器、用户名、密码及整个应 用程序中共享的其它信息。 Session 类的构造器是私有的,它不能被继承,也不能使用 new 语句来创建实例,但它提 供了两个静态方法 getInstance 和 getDefaultInstance 来获取 Session 实例,前者创建一个独立 的会话,否则获取缺省的共享会话。 (2)javax.mail.Message 获得 Session 对象后,可以开始继续创建要发送的邮件消息。这由 Message 类来完成, Message 实现了 Part 接口,它表示一个邮件消息,包含一系列属性(attribute)和一个消息内 容(content)。消息属性标识了消息地址信息,定义了消息内容的结构(包括内容类型);消 息内容使用 DataHandler 对象包装实际数据。当邮件消息位于目录(folder)中时,系统还使 用一个标志位集合来描述它的状态。 Message 是抽象类,实际使用时必需用一个子类代替以表示具体的邮件格式。比如说, JavaMail API 提供了 MimeMessage(位于 javax.mail.internet.MimeMessage 包)类,该类扩展 自 Message,实现了 RFC822 和 MIME 标准。Message 的子类通常通过字节流构建其实例, 相应的,它们也可以生成字节流来传输自身。 (3)javax.mail.Address Address 类表示电子邮件地址,它是一个抽象类。其子类(最经常使用的子类是 javax.mail.internet.InternetAddress)提供具体实现,且通常可串行化。 3 J2EE 完全参考手册 (tsl0151@vip.sina.com) 在创建了 Session 和 Message,并设置了消息内容后,可以用 Address 确定邮件消息的 发送者和接收者地址。 (4)javax.mail.Authenticator Authenticator 代表一个可以为网络连接获取认证信息的对象,它通常通过提示用户输入 用户名和密码来收集认证信息,使连接可以访问受保护的资源。对于 JavaMail API 来说,这 些资源就是邮件服务器。JavaMail Authenticator 在 javax.mail 包中,它和 java.net 中同名的 类 Authenticator 不同。 要使用 Authenticator,必须先创建一个它的子类实例,并且在会话对象创建时为会话注 册该 Authenticator 对象。在需要认证的时候,就会通知 Authenticator。程序可以弹出窗口, 也可以从配置文件中(虽然没有加密是不安全的)读取用户名和密码,并使用它们作为构造 函数参数创建一个 PasswordAuthentication 对象返回给调用程序。 (5)javax.mail.Transport 消息发送的最后步骤是使用 Transport 类。该类使用指定协议发送消息(通常是 SMTP)。 Transport 是抽象类,它的工作方式与 Session 有些类似,可以通过静态类方法或实例方法发 送消息。Transport 继承自 Service 类,而后者提供了很多通用方法,如命名传输、连接服务 器、监听传输事件等等。 (6)javax.mail.Store Store 是一个抽象类,它模拟了消息存储器(或称为数据库)及其内部目录(Folder)访 问协议,以储存和读取消息,其子类提供具体实现。 Store 定义的存储器包括一个分层的目录体系,消息存储在目录内。客户程序可以通过获 取一个实现了数据库访问协议的 Store 对象来访问消息存储器,绝大多数的存储器要求用户 在访问前提供认证信息,connect 方法执行了该认证过程。大多数情况下,主机名、用户名和 密码已足够认证一个用户,JavaMail API 提供的 connect 方法将这些信息作为输入参数,Store 类也提供了一个缺省的 connect 方法;在任何一种情况下,客户机程序都可以从会话对象属 性中获取认证信息;或者通过访问会话的 Authenticator 对象来与用户交互,要求用户输入认 证信息。 (7)javax.mail.Folder Folder 是一个抽象类,用于分级组织邮件,其子类提供针对具体协议的实现。 Folder 代表的目录可以容纳消息或子目录,它使用这种方式提供了一个类似于树的分层 体系。 存储在目录内的消息被顺序计数(从 1 开始到消息总数),该顺序被称为“邮箱顺序”, 通常基于邮件消息到达目录的顺序。邮件顺序的变动将改变消息的序列号,这种情况仅发生 在客户程序调用 expunge 方法擦除目录内设置了 Flags.Flag.DELETED 标志位的消息时。执行 擦除操作后,目录内消息将重新编号。 客户程序可以通过消息序列号或直接通过相应的 Message 对象引用目录中的消息,因为 消息序列号在会话中很可能改变,因此应尽可能保存 Message 对象而非序列号来反复引用对 象。 扩展了 JavaMail 的客户机程序应该提供轻量级的、可以“按需填充”的 Message 对象, 这样在 Folder 对象上调用 getMessages 方法将不会浪费太多(CPU、内存和网络)资源。 4 第 8 章 Java Mail 核心 JavaMail API 的另一部分的主要接口和类包括 Part、Message、Bodypart、Multipart、 MimePart、MimeMessage、MimiBodypart 和 MimeMultipart,可以用这些类和接口完成电子邮 件的阅读、撰写等任务,这类任务主要属于 MUA 范畴。图 2-3 描述了这些类和接口的层次。 图 2-3 JavaMail 邮件读写类和接口 这些类和接口的使用因为涉及到 JavaBeans 活动框架的一些内容,因此放在 8.1.4 节,读 者可参考该节。 8.1.3 电子邮件有关协议 在深入研究 JavaMail API 的细则之前,有必要首先回顾一下最常见的几个电子邮件协议。 除了下面将谈到的一些协议外,开发者还可能碰到 NNTP 和其它协议,理解所有协议的基本 知识将有助于开发者理解如何更有效的使用 JavaMail API。虽然不了解这些协议照样可以用 这套 API,但程序不能克服那些基础协议的局限性。如果所选择的协议不能支持某种性能, JavaMail API 不可能魔术般的将这种性能添加上去。 1. SMTP 简单邮件传输协议(Simple Mail Transfer Protocol,简称 SMTP)由 RFC 821 定义,它是 最早出现的,也是被普遍使用的最基本的 Internet 邮件服务协议。SMTP 定义了提交和传送电 子邮件的机制,规定了主机之间传输电子邮件的标准交换格式和邮件在链路层上的传输机制; 但它支持的功能比较简单,同时有安全方面的缺陷。通过 SMTP 协议发送的所有电子邮件都 是以普通文本形式传输的,它不能传输诸如图像等非文本信息。在网络上明码传输文本信息 5 J2EE 完全参考手册 (tsl0151@vip.sina.com) 意味着任何人都可以在中途截取并复制这些邮件,甚至对邮件内容进行篡改。为了克服上述 缺陷,后来出现了 ESMTP(Extended SMTP,扩展的 SMTP 协议)。 在 JavaMail API 环境中,基于 JavaMail 的程序将和 ISP(Internet Service Provider,因 特网服务供应商)的 SMTP 服务器通信。SMTP 服务器可将消息中转至接收方 SMTP 服务 器,以便最终让用户经由 POP 或 IMAP 获得。这并非要求 SMTP 服务器成为开放的中继, SMTP 服务器支持身份验证(当然得确保它的配置正确)。JavaMail API 不支持像配置服务器 来中继消息或添加、删除邮件账号这类任务的实现。 2. POP POP(Post Office Protocol,邮局协议)允许用户从邮件服务器收发邮件。它有 2 种版本: POP2 和 POP3,都具有简单的电子邮件存储转发功能。POP2 与 POP3 本质上类似,都属于 离线式工作协议,但是由于使用了不同的协议端口,两者并不兼容,POP3 是目前最常用的 电子邮件服务协议。 POP3 由 RFC 1939 定义,除了支持离线工作方式外,还支持在线工作方式。在离线工作 方式下,用户收发邮件时,首先通过 POP3 客户程序登录到支持 POP3 协议的邮件服务器, 然后发送邮件及附件;接着,邮件服务器将为该用户收存的邮件传送给 POP3 客户程序,并 将这些邮件从服务器上删除;最后,邮件服务器将用户提交的发送邮件,转发到运行 SMTP 协议的计算机中,通过它实现邮件的最终发送。在为用户从邮件服务器收取邮件时,POP3 是以该用户当前存储在服务器上全部邮件为对象进行操作的,并一次性将它们下载到用户端 计算机中。一旦客户的邮件下载完毕,邮件服务器对这些邮件的暂存托管即告完成。使用 POP3,用户不能对他们贮存在邮件服务器上的邮件进行部分传输。离线工作方式适合那些从 固定计算机上收发邮件的用户使用。 当使用 POP3 在线工作方式收发邮件时,用户在所用的计算机与邮件服务器保持连接的 状态下读取邮件。用户的邮件保留在邮件服务器上。 POP 协议规定每个用户只能有一个目录的支持,这造成了许多混淆。使用 POP 时,用 户熟悉的许多性能并不是由 POP 协议支持的,如查看有几封新邮件消息这一性能。这些性 能内建于如 Eudora 或 Microsoft Outlook 之类的程序中,而不是由 POP3 直接支持的。所以 当使用 JavaMail API 时,如果读者想获取这类信息,只能由自己来编程计算。 3. IMAP IMAP(Internet Message Access Protocol,Internet 消息访问协议)是更高级的用于接收消 息的协议,由 RFC 2060 定义。目前使用的 IMAP 版本为 4,通常将它称为 IMAP4。 IMAP4 为用户提供了有选择地从邮件服务器接收邮件、基于服务器的信息处理和共享信 箱功能在 JavaMail 程序用到 IMAP 时,邮件服务器必需支持这个协议。不能仅仅把基于 POP 的程序用于 IMAP,并期望它支持 IMAP 所有性能。 假设邮件服务器支持 IMAP,基于 JavaMail 的程序可以利用这种情况:用户在服务器 上可以有多个文件夹(folder),并且这些文件夹可以被多个用户共享。 虽然有这些更高级的性能,但并不是所有的邮件服务器都支持 IMAP。与 POP 相比,IMAP 需要更多的服务器存储空间,采用 IMAP 邮件系统时,用户会将大量信息及相关附件保留在 服务器中。另一方面,由于用户查阅信息标题和决定下载哪些附件,也需要一定时间,因此 6 第 8 章 Java Mail 链接时间也比 POP 方式长。再者,对于那些具有浓厚商业色彩的 ISP 来说,采用 IMAP 还意 味着花钱购买相关商业软件,而不是下载免费自由软件这么简单。 4. MIME MIME(Multipurpose Internet Mail Extensions,多用途 Internet 邮件扩展标准)不是邮件 传输协议,它只定义了需要传输的消息、附件及其他类型数据的格式。这份定义涉及很多的 RFC 文档:RFC 822、RFC 2045、RFC 2046 和 RFC 2047。使用 JavaMail API 开发者通常不 必关心这些格式。 Internet 上的 SMTP 传输机制是以 7 位二进制编码的 ASCII 码为基础的,适合传送文本 邮件。而声音、图象、中文等使用 8 为二进制编码的电子邮件需要进行 ASCII 转换(编码) 才能够在 Internet 上正确传输。MIME 增强了在 RFC 822 中定义的电子邮件报文的能力,允 许传输二进制数据。MIME 编码技术用于将数据从 8 位都使用的格式转换成数据使用 7 位的 ASCII 码格式。 5. RFC 822 RFC 822 定义了用于电子邮件报文的格式,换句话说,它定义了 SMTP、POP3、IMAP 以及其它电子邮件传输协议所提交、传输的内容。 RFC 822 定义的邮件由两部分组成:信封和邮件内容。信封包括与传输、投递邮件有关 的信息;邮件内容包括标题和正文。 8.1.4 JavaBeans 活动框架 JavaMail 依赖于 JavaBeans 活动框架(JavaBeans Activation Framework,简称 JAF)以判 断 MIME 数据类型和在类型数据上可以执行的操作。 按照 JavaBeans Activation Framework Specification(Version 1.0)的说法,JAF 应该提供 以下服务: • 确定任意数据的类型 • 封装待访问数据 • 寻找在某一数据类型上可用的操作 • 实例化软件组件,这些组件对应于某些数据上期望的操作。 1. JAF 体系 图 2-4 列出了组成 JAF 框架的主要元素,注意:它并不表示一个应用程序框架。下面将 简单介绍一下这些元素。 7 J2EE 完全参考手册 (tsl0151@vip.sina.com) 图 2-4 JAF 主要元素 (1)DataHandler DataHandler 类为基于 JAF 的客户机和其他子系统间提供一个相容性接口,它封装了一 个数据对象,并且提供方法来操作这些数据。 一个 DataHandler 对象只能通过数据实例化。实例化后,DataHandler 对象将试图提供一 种方便的方法来访问其数据,DataHandler 实现了 Transferable 接口以允许对象提供可供选择 的数据表示方法。DataHandler 使用一个 CommandMap 对象来回应对操作数据的 Command 对象的请求。每一个 DataHandler 实例都有一个与之关联的 CommandMap 对象,如果客户程 序没有为 DataHandler 设置 CommandMap 对象,则 DataHandler 可以使用 CommandMap 类静 态方法 getDefaultCommandMap 返回的 CommandMap 对象。 (2)DataSource DataSource(数据源)接口封装了一个包含数据的对象,并且能够返回用于访问数据的 流(stream)和一个表示 MIME 类型的字符串,MIME 类型可用于描述数据。 各种实现了 DataSource 接口的类可以用于描述通用数据源(如文件系统、web、FTP、IMAP 服务器、数据库对象等),DataSource 接口可以被扩展以允许用户定制数据源。 DataHandler 可以使用 DataSource 接口以访问其内部数据,一旦在 DataHandler 对象内设 置了数据源(DataSource 对象),客户程序就可以判断在该类型数据上可用的操作。 为了方便起见,JAF 定义了三个 DataSource 实现类: • FileDataSource:用于访问文件内的数据。 • URLDataSource:用于访问某个 URL 所确定的网络数据。 • MimePartDataSource:用于访问 MIME(RFC2045, Section 2.4)所定义实体内的数据。 (3)CommandMap 一旦 DataHandler 确定了描述其内容的 MIME 类型,它可以通过 CommandMap 对象以查 询该类型数据上可用的操作或指令(command),查询结果将以与这些可用指令关联的 Bean 对象(或 Bean 对象数组)的形式返回。 (4)CommandInfo CommandMap 实现类使用 CommandInfo 来描述指令请求的结果,应用程序可以使用它 8 第 8 章 Java Mail 实例化 Bean 和请求它所描述的动词。 (5)DataContentHandler DataHandler 使用 DataContentHandler 接口将输入流转换为对象(object)。为了完成转换 工作,DataHandler 通常使用一个实现了 Transferable 接口的 DataContentHandler 对象,这个 对象可以通过 CommandMap 查询到。DataContentHandler 使用 DataFlavors 来表示它可以访问 的数据类型。 DataContentHandler 也可以将数据由数据转换为输入流。比如说,如果应用程序需要访 问一个.gif(位图)文件,它可以将文件作为数据源传递给一个 image/gif DataContentHandler 对象,该对象会将图形对象转换为一个 gif 格式的字节流。 (6)CommandObject 专门设计用于与 JAF 体系交互的 Bean 应该实现 CommandObject 接口,以找出它们被要 求执行的指令,并获取封装它们所要操作数据的 DataHandler 对象。 2. JAF 在 JavaMail 中的应用 对于使用 JavaMail 的客户机,邮件消息的读取是一件非常重要的工作。javax.mail.Part 接口允许客户机程序访问消息内容,Part 接口是 Message 和 BodyPart 的父接口,它定义了一 系列属性(attribute)和一个“内容”。通常一个邮件消息有一个或多个主体部分,每部分都 是一个特殊的 MIME 类型。 不管 Part 接口通过 InputStream 还是通过 Java 对象来访问内容,它事实上都用到了 DataHandler 接口,Part 接口定义的方法也往往都回到了这个接口。比如说调用 Part.getDataHandler().getContent()与调用 Part.getContent()方法结果完全相同,都将内容作为 Java 对象返回;同样,调用 Part.getDataHandler().getInputStream()与调用 Part.getInputStream() 方法结果也相同,都将内容作为输入流返回。 返回的内容(不管是作为输入流还是作为 Java 对象)依赖于其 MIME 类型,比如说, 一个包含文本内容的 Part 对象有如下行为: • Part.getContentType 方法将返回”text/plain”。 • Part.getInputStream 方法将返回包含文本字节的输入流。 • Part.getContent 方法将返回 java.lang.String 对象。 若调用 getInputStream 方法获取内容,则输入流返回前将解码任何在邮件传输过程进行 的编码。 若调用 getContent 方法获取内容,返回对象的实际类型取决于消息内容。在 JavaMail API 中,若 Part 对象(可能是一个消息)的内容类型被设置为“Multipart/”,则 Part.getContent 将返回一个 javax.mail.Multipart 对象;若 Part 对象的内容类型被设置为“message/rfc822”, 则 Part.getContent 将返回一个 javax.mail.Message 对象。 下面是一个示例程序,它将遍历一个 Part 对象(可能是一个消息)并输出其中的数据。 public void printParts(Part p) { Object o = p.getContent(); // 如果内容是一个字符串,则直接输出该字符串 9 J2EE 完全参考手册 (tsl0151@vip.sina.com) if (o instanceof String) { System.out.println("This is a String"); System.out.println((String)o); } // 如果内容是一个有多个部分的对象,则循环遍历各个部分 else if (o instanceof Multipart) { System.out.println("This is a Multipart"); Multipart mp = (Multipart)o; int count = mp.getCount(); for (int i = 0; i < count; i++) printParts(mp.getBodyPart(i)) } // 如果内容只是一个输入流,则读入该输入流再输出 else if (o instanceof InputStream) { System.out.println("This is just an input stream"); InputStream is = (InputStream)o; int c; while ((c = is.read()) != -1) System.out.write(c); } } 8.1.5 邮件处理例程 本节将通过代码段示范如何通过 JavaMail API 完成邮件的发送、接收、回复、转发、以 及附件处理、非文本邮件处理等一系列任务,以使读者对 JavaMail API 各元素在邮件框架中 的角色和用法有一个大体了解。读者在阅读代码时若有不解之处,可以参考下文中各个类和 接口的介绍。 1. 发送邮件 为发送电子邮件消息,应该首先获取一个会话,创建并填充一则邮件消息,然后使用 Transport 类发送。得到会话时,经由设置传递给 Properties 对象中的 mail..host 属 性,可以指定用于发送邮件的协议和支持该协议的邮件服务器。 一条邮件消息可以由多个部分(BodyPart)组成;在处理 MIME 消息时,消息中每部分 都是一个 MimeBodyPart 对象。不同的 body part(消息部件)结合成一个容器,名为 Multipart; 处理 MIME 消息时,这个容器就是 MimeMultipart。下面要发送的消息就是由多个部分组成 的,发送邮件代码如下所示。 10 第 8 章 Java Mail // 初始化收件人邮件地址、发件人邮件地址和主机名,下面的各初始化字符串均为任意设置 String to = "receiver@xxx.com"; String from = "sender@xxx.com"; String host ="hostaddress" ; // 创建一个属性对象 Properties props = new Properties(); // 指定发送邮件服务器,使用 smtp 协议 props.put("mail.smtp.host", host); // 获取会话 Session session = Session.getDefaultInstance(props, null); try { // 创建消息,设置邮件发件人地址、收件人地址、主题 MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(from)); msg.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); msg.setSubject("发送邮件示例"); msg.setText("发送成功"); // 开始设置消息内容 msg.setSentDate(new Date()); // 创建并填充消息的第一部分 MimeBodyPart mbp1 = new MimeBodyPart(); mbp1.setText(msgText1); // 创建并填充消息的第二部分 MimeBodyPart mbp2 = new MimeBodyPart(); mbp2.setText(msgText2, "us-ascii"); // 创建 Multipart 对象,并用上面的创建的两个部分填充它 Multipart mp = new MimeMultipart(); mp.addBodyPart(mbp1); mp.addBodyPart(mbp2); // 使用上面的 Multipart 对象作为消息内容 msg.setContent(mp); // 发送邮件 Transport.send(msg); } catch (MessagingException e) { …… //异常处理 } 开发者应该将创建和发送消息的代码放在一个 try-catch 块中,以进行错误处理。 11 J2EE 完全参考手册 (tsl0151@vip.sina.com) 2. 读取邮件 为读取邮件,必须首先获取一个会话,然后获取并连接邮箱所在的存储器(Store 对象), 打开该用户的邮箱,获取所希望阅读的消息,最后应该关闭目录和连接。读取邮件代码如下 所示。 // 初始化主机 String host = ...; String username = ...; String password = ...; // 获取系统属性 Properties props = System.getProperties(); // 获取会话 Session session = Session.getDefaultInstance(props, null); // 获取 Store 对象,使用 POP3 协议,也可能使用 IMAP 协议 Store store = session.getStore("pop3"); // 连接到邮件服务器 store.connect(host, username, password); // 获取该用户 Folder 对象,并以只读方式打开 Folder folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); // 检索所有邮件,按需填充 Message message[] = folder.getMessages(); // 遍历每一个邮件 BufferedReader reader = new BufferedReader (new InputStreamReader(System.in)); for (int i=0, n=message.length; i DataFlavor-> ActivationDataFlavor(Cloneable, Externalizable, Serializable) CommandInfo JAF1.0 javax.activation Serialized CommandMap 实现类通过 CommandInfo 来描述指令请求的结果,应用程序可以使用它 实例化 Bean 和请求它所描述的动词。 类声明: public class CommandInfo { // 构造函数 public CommandInfo(String verb, String className); // 公共实例方法 public String getCommandClass(); public String getCommandName(); public Object getCommandObject(DataHandler dh, ClassLoader loader) throws IOException, ClassNotFoundException; 22 第 8 章 Java Mail } 层次: Object-> CommandInfo 传递给:DataHandler.getBean() 返回自:DataHandler.getCommand(), DataHandler.getPreferredCommands()*, DataHandler.getAllCommands()* getCommandClass 语法:public String getCommandClass() 描述:getCommandClass 方法获取 Command 类名称。注意:该方法返回的类名并不一 定是一个合法名称,因为 CommandMap 实现类很可能为了实现某些功能而子类 化 Command 对象,换句话说,仅通过该方法返回的类名称来创建一个有着恰当 状态的对象很可能是不可行的。 返回:Command 类名称,可能为空。 getCommandName 语法:public String getCommandName() 描述:getCommandName 方法获取该对象所描述的指令动词。 返回:指令动词。 getCommandObject 语法:public Object getCommandObject(DataHandler dh, ClassLoader loader) throws IOException, ClassNotFoundException 描述:getCommandObject 方法获取 JavaBean 组件实例。方法首先调用 Beans.instantiate() 初始化 Bean。若 Bean 实现了 javax.activation.CommandObject 接口,则随后调用 它的 setCommandContext 方法;如果 Bean 没有实现 CommandObject 接口,则方 法检查它是否实现了 Externalizable 接口,若是,则 bean 调用 readExternal 方法。 参数:dh:描述数据的 DataHandler 对象,这些数据将传递给 Command 对象;loader: 被用于实例化 Bean 的 ClassLoader 对象。 返回:JavaBean 组件实例。 23 J2EE 完全参考手册 (tsl0151@vip.sina.com) CommandMap JAF1.0 javax.activation 一旦 DataHandler 确定了描述其内容的 MIME 类型,它可以通过 CommandMap 对象以查 询该类型数据上可用的操作或指令(command),查询结果将以与这些可用指令关联的 Bean 对象(或 Bean 对象数组)的形式返回。 类声明: public abstract class CommandMap { // 构造函数 public CommandMap(); // 静态方法 public static CommandMap getDefaultCommandMap(); public static void setDefaultCommandMap(CommandMap commandMap); // 公共实例方法 public abstract DataContentHandler createDataContentHandler(String mimeType); public abstract CommandInfo[] getAllCommands(String mimeType); public abstract CommandInfo getCommand(String mimeType, String cmdName); public abstract CommandInfo[] getPreferredCommands(String mimeType); } 层次: Object-> CommandMap 子类: MailcapCommandMap 传递给:CommandMap.setDefaultCommandMap(), DataHandler.setCommandMap(), 返回自:CommandMap.getDefaultCommandMap() createDataContentHandler abstract 语法:public abstract DataContentHandler createDataContentHandler(String mimeType) 描述:getCommandClass 方法获取一个对应于指定 MIME 类型的 DataContentHandler 对 象。 参数:mimeType:所指定 MIME 类型。 返回:对应于指定 MIME 类型的 DataContentHandler 实例。 getAllCommands abstract 语法:public abstract CommandInfo[] getAllCommands(String mimeType) 描述:getAllCommands 方法获取对指定 MIME 类型可用的所有指令。 24 第 8 章 Java Mail 返回:表示所有指令的 CommandInfo 对象数组。 getCommand abstract 语法:public abstract CommandInfo getCommand(String mimeType, String cmdName) 描述:getCommand 方法获取对应于特定 MIME 类型上某个可用指令的 CommandInfo 对 象。 参数:mimeType:所指定的 MIME 类型;cmdName:在 mimeType 数据上可用的指令 动词。 返回:对应于一个特定指令的 CommandInfo 对象。 getDefaultCommandMap static 语法:public static CommandMap getDefaultCommandMap() 描述:getDefaultCommandMap 是一个静态方法,它获取缺省的 CommandMap 对象。若 调用该方法之前已使用 setDefaultCommandMap 方法将某个 CommandMap 实例设 置为缺省对象,则方法返回该实例;若之前没有设置缺省实例,则 CommandMap 将创建一个 MailcapCommandMap 实例,并将之设置为缺省对象。 返回:缺省 CommandMap 对象。 getPreferredCommands abstract 语法:public abstract CommandInfo[] getPreferredCommands(String mimeType) 描述:getPreferredCommands 方法获取对特定 MIME 类型可用的指令中优先使用的部分 指令,该方法实际语义(即哪些指令是应该优先使用的)由 CommandInfo 实现类 决定。 返回:代表优先指令的 CommandInfo 对象数组。 setDefaultCommandMap static 语法:public static void setDefaultCommandMap(CommandMap commandMap) 描述:setDefaultCommandMap 是静态方法,它设置缺省 CommandMap 对象。 参数:commandMap:新的缺省 CommandMap 对象。 25 J2EE 完全参考手册 (tsl0151@vip.sina.com) DataHandler JAF1.0 javax.activation DataHandler 类为基于 JAF 的客户机和其他子系统间提供一个相容性接口,它封装了一 个数据对象,并且提供方法来操作这些数据。 一个 DataHandler 对象只能通过数据实例化,这个数据可能的形式有:实现了 DataSource 接口的对象、一个对象和一个关联的内容类型或者一个 URL 对象。实例化后,DataHandler 对象将试图提供一种方便的方法来访问其数据,DataHandler 实现了 Transferable 接口以允许 对象提供可供选择的数据表示方法。Transferable 接口的功能可以通过实现了 DataContentHandler 接口的对象进行扩展,然后可以通过 DataContentHandlerFactory 对象或 CommandMap 对象使这些功能对 DataHandler 可用。 DataHandler 使用一个 CommandMap 对象来回应对操作数据的 Command 对象的请求。 每一个 DataHandler 实例都有一个与之关联的 CommandMap 对象,如果客户程序没有为 DataHandler 设置 CommandMap 对象,则 DataHandler 可以使用 CommandMap 类静态方法 getDefaultCommandMap 返回的 CommandMap 对象。 类声明: public class DataHandler implements Transferable { // 构造函数 public DataHandler(DataSource ds); public DataHandler(Object obj, String mimeType); public DataHandler(URL url); // 静态方法 public static void setDataContentHandlerFactory(DataContentHandlerFactory newFactory); // 公共实例方法 public CommandInfo[] getAllCommands(); public Object getBean(CommandInfo cmdinfo); public CommandInfo getCommand(String cmdName); public Object getContent() throws IOException; public String getContentType(); public DataSource getDataSource(); public InputStream getInputStream()throws IOException; public String getName(); public OutputStream getOutputStream() throws IOException; public CommandInfo[] getPreferredCommands(); public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException; public DataFlavor[] getTransferDataFlavors(); public boolean isDataFlavorSupported(DataFlavor flavor); public void setCommandMap(CommandMap commandMap); 26 第 8 章 Java Mail void writeTo(OutputStream os) throws IOException; } 层次: Object-> DataHandler (Transferable) 传递给:CommandInfo.getCommandObject(),CommandObject.setCommandContext(), Part.setDataHandler(), javax.mail.internet.MimeMessage.setDataHandler(), javax.mail.internet.MimeUtility.getEncoding(), javax.mail.internet.MimeBodyPart.setDataHandler(), javax.xml.soap.SOAPMessage.createAttachmentPart(), javax.xml.registry.LifeCycleManager.createExtrinsicObject(), javax.xml.soap.AttachmentPart.setDataHandler(), javax.xml.registry.infomodel.ExtrinsicObject.setRepositoryItem() 返回自:Part.getDataHandler(), javax.mail.internet.MimeMessage.getDataHandler(), MimeBodyPart.getDataHandler(), javax.xml.soap.AttachmentPart.getDataHandler(), getAllCommands 语法:public CommandInfo[] getAllCommands(); 描述:getAllCommands 方法获取对该 DataHandler 对象所封装数据的 MIME 类型可用的 所有指令,它实际上调用了与该对象关联的 CommandMap 对象上的 getAllCommands(String mimeType)方法,参数 mimeType 使用该对象所封装数据 的 MIME 类型。 返回:表示所有可用指令的 CommandInfo 对象数组。 getBean 语法:public Object getBean(CommandInfo cmdinfo) 描述:getBean 方法实例化一个对应于指定 CommandInfo 对象的指令对象,它通常是一 个 JavaBean 组件。该方法将调用 CommandInfo.getCommandObject,并使用用于 装载该 DataHandler 的 ClassLoader 对象作为参数。 参数:cmdinfo:对应于待获取指令对象的 CommandInfo 对象。 返回:Command 对象。 getCommand 语法:public CommandInfo getCommand(String cmdName) 描述:getCommand 方法搜索与特定指令名称对应的 CommandInfo 对象,它将调用与该 DataHandler 实例关联的 CommandMap 对象上的同名方法,并使用该对象所封装 数据的 MIME 类型作为类型参数。 27 J2EE 完全参考手册 (tsl0151@vip.sina.com) 参数:cmdName:指令名称。 返回:与 cmdName 对应的 CommandInfo 实例。 getContent 语法:public Object getContent() throws IOException 返回:以 Java 语言对象形式返回该对象封装的数据。 getContentType 语法:public String getContentType() 返回:该对象所封装的数据的 MIME 类型。 getDataSource 语法:public DataSource getDataSource() 返回:与该 DataHandler 对象关联的数据源。 getInputStream 语法:public InputStream getInputStream()throws IOException 返回:表示该对象所封装的数据的输入流。 异常:如果出现 I/O 错误,则抛出 IOException。 getName 语法:public String getName() 描述:getName 方法获取该 DataHandler 实例所封装数据对象的名称,若 DataHandler 对 象是通过数据源实例化的,则该方法将调用 DataSource.getName 方法并返回调用 结果;否则该方法返回空值。 返回:数据对象名称。 getOutputStream 语法:public OutputStream getOutputStream() throws IOException 描述:getOutputStream 方法获取一个输出流,DataHandler 对象将通过这个输出流重写 它所封装的数据。若 DataHandler 对象是通过数据源实例化的,则该方法将调用 DataSource.getOutputStream 方法并返回调用结果;否则该方法返回空值。 28 第 8 章 Java Mail 返回:OutputStream 对象。 getPreferredCommands 语法:public CommandInfo[] getPreferredCommands() 描述:getPreferredCommands 方法获取对该对象所封装数据的 MIME 类型可用的指令中 优先使用的部分指令,它将调用与该 DataHandler 实例关联的 CommandMap 对象 上的同名方法。 返回:代表优先指令的 CommandInfo 对象数组。 异常:如果出现 I/O 错误,则抛出 IOException。 getTransferData 语法:public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException 返回:代表将被传输数据的对象,该对象类型由参数 flavor 的表示类定义。 getTransferDataFlavors 语法:public DataFlavor[] getTransferDataFlavors() 返回:DataFlavor 对象数组,该 DataHandle 对象所封装数据可在其内传输。 isDataFlavorSupported 语法:public boolean isDataFlavorSupported(DataFlavor flavor) 描述:isDataFlavorSupported 方法判断该 DataHandle 对象是否支持指定 DataFlavor 对象。 该方法将遍历 getTransferDataFlavors 方法返回的 DataFlavor 对象数组,并比较数 组中的每一个成员与指定 DataFlavor 对象。 参数:指定 DataFlavor 对象。 返回:布尔值,为 true 表示支持该 DataFlavor 对象。 setCommandMap 语法:public void setCommandMap(CommandMap commandMap) 描述:setCommandMap 方法设置与该 DataHandler 实例关联的 CommandMap 对象。 参数:commandMap:将 与 DataHandler 实例关联的 CommandMap 对象,若该值设为空, 则关联的 CommandMap 对象将被设置为 CommandMap.getDefaultCommandMap。 29 J2EE 完全参考手册 (tsl0151@vip.sina.com) setDataContentHandlerFactory static 语法:public static void setDataContentHandlerFactory(DataContentHandlerFactory newFactory) 描述:setDataContentHandlerFactory 是一个静态方法,它设置与该 DataHandler 类关联的 DataContentHandlerFactory 对象,该对象用于搜索可用的 DataContentHandler 实 例。注意:对于一个 DataHandler 类,setDataContentHandlerFactory 方法只能被调 用一次。 参数:newFactory:带设置的 DataContentHandler 类厂对象。 writeTo 语法:void writeTo(OutputStream os) throws IOException 描述:writeTo 方法向指定输出流写入该 DataHandler 对象所封装的数据。 参数:os:待写入的输出流。 FileDataSource JAF1.0 javax.activation FileDataSource 实现 DataSource 接口,它封装了一个文件,并通过 FileTypeMap 对象提 供数据类型服务。FileDataSource 使用 setFileTypeMap 方法设置与其关联的 FileTypeMap 对象; 如果没有设置关联对象,则它将通过 FileTypeMap 的静态方法 getDefaultFileTypeMap 使用系 统缺省的 FileTypeMap 对象。 FileDataSource 类提供了两个构造函数,分别使用 File 对象和文件路径名提供数据源, 构造 FileDataSource 实例。反之,通过 getFile 和 getName 方法,可以获取 FileDataSource 对 象所封装的文件对象和该文件路径名。 此外,FileDataSource 对象还提供了三个方法:getContentType、getInputStream 和 getOutputStream,分别用于获取该对象所封装数据的 MIME 类型、代表封装数据的输入流和 输出流。 类声明: public class FileDataSource implements DataSource { // 构造函数 public FileDataSource(File file); public FileDataSource(String name); // 公共实例方法 public String getContentType(); public File getFile(); 30 第 8 章 Java Mail public InputStream getInputStream() throws IOException; public String getName(); public OutputStream getOutputStream() throws IOException; public void setFileTypeMap(FileTypeMap fileTypeMap); } 层次: Object -> FileDataSource(DataSource) FileTypeMap JAF1.0 javax.activation abstract FileTypeMap 是一个抽象类,它为文件提供数据类型服务。 FileTypeMap 的实现类将提 供 getContentType 方法以判断某个文件或文件对象(File Obect)内数据的类型。 FileTypeMap 类提供了两个静态方法:getDefaultFileTypeMap 和 setDefaultFileTypeMap, 分别用于获取和设置系统缺省的 FileTypeMap 对象,FileDataSource 类可以使用这个缺省对象 以获取类型服务。 类声明: public class FileTypeMap { // 构造函数 public FileTypeMap(); // 静态方法 public static FileTypeMap getDefaultFileTypeMap(); public static void setDefaultFileTypeMap(FileTypeMap map); // 抽象方法 public abstract String getContentType(File file); public abstract String getContentType(String filename); } 层次: Object -> FileDataSource 子类: MimetypesFileTypeMap 31 J2EE 完全参考手册 (tsl0151@vip.sina.com) MailcapCommandMap JAF1.0 javax.activation MailcapCommandMap 扩展自 CommandMap 抽象类,它实现了一个配置基于 mailcap 文 件(RFC 1524,多媒体邮件格式信息的用户代理配置机制)的 CommandMap 对象。 MailcapCommandMap 可以通过编程或配置文件进行配置。 MailcapCommandMap 搜索用户系统的不同位置以寻找 mailcap 文件,当用户请求搜索 MailcapCommandMap 中的指令时(调用 getAllCommands 、 getPreferredCommands 和 getCommand 方法),程序将按如下顺序搜索 mailcap 文件: • 通过编程加入 MailcapCommandMap 实例的 mailcap 条目(调用 addMailcap 方法可以 加入 mailcap 条目); • 用户 home 目录中的.mailcap 文件; • /lib/mailcap 文件; • 名称为 META-INF/mailcap 的文件或资源; • 名称为 META-INF/mailcap.default 的文件或资源(通常在 activation.jar 文件中)。 类声明: public class MailcapCommandMap extends CommandMap { // 构造函数 public MailcapCommandMap(); public MailcapCommandMap(InputStream is); public MailcapCommandMap(String fileName); // 公共实例方法 public void addMailcap(String mail_cap); public DataContentHandler createDataContentHandler(String mimeType); public CommandInfo[] getAllCommands(String mimeType); public CommandInfo getCommand(String mimeType, String cmdName); public CommandInfo[] getPreferredCommands(String mimeType); } 层次: Object -> CommandMap -> MailcapCommandMap MimeType JAF1.0 javax.activation Serializable MIME(多用途 Internet 邮件扩展标准)类型的定义设计了多个 RFC 文档,包括 RFC 822、 32 第 8 章 Java Mail RFC 2045、RFC 2046 和 RFC 2047,它确定了需要传输的消息、附件及其他类型数据的格式, 但使用 JavaMail API 开发者通常不必关心这些具体格式,他们只需了解 MIME 类型的大体结 构和相关 API 即可。 一个 MIME 类型由一个主类型(PrimaryType)和一个子类型(SubType)组成,主类型 声明了消息内容的一般类型,子类型标识了消息内容的专用格式。围绕主类型和子类型, MimeType 类提供了五个方法:getPrimaryType、getSubType、setPrimaryType 和 setSubType, 分别用于获取和设置 MimeType 对象的主类型与子类型;getBaseType 方法返回仅由主类型和 子类型组成的 MIME 类型(字符串形式),即改返回类型不包括下面将提到的可选参数集合。 此外,MimeType 类还提供了两个 match 方法,用于比较两个 MIME 类型的主类型和子类型 是否都相同。 除了主类型和子类型外,MIME 类型还包括特定类型参数的可选集合。getParameters 方 法将返回所有这些参数的列表,getParameter 获取与指定参数名关联的值,setParameter 设置 与指定参数名关联的值,removeParameter 删除与指定参数名关联的值。 MimeType 类提供了三个构造函数,其中一个是缺省的无参构造函数,另外两个分别使 用使用原始数据(字符串形式)形式和 PrimaryType/SubType 对构造 MimeType 实例。 MimeType 通过 readExternal 从输入对象读入数据,通过 writeExternal 方法将自身数据写 入输出对象。 类声明: public class MimeType implements Externalizable { // 构造函数 public MimeType(); public MimeType(String rawdata) throws MimeTypeParseException; public MimeType(String primary, String sub) throws MimeTypeParseException; // 公共实例方法 public String getBaseType(); public String getParameter(String name); public MimeTypeParameterList getParameters(); public String getPrimaryType(); public String getSubType(); public boolean match(MimeType type); public boolean match(String rawdata) throws MimeTypeParseException; public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException; public void removeParameter(String name); public void setParameter(String name, String value); public void setPrimaryType(String primary) throws MimeTypeParseException; public void setSubType(String sub) throws MimeTypeParseException; public String toString(); public void writeExternal(ObjectOutput out) throws IOException; } 33 J2EE 完全参考手册 (tsl0151@vip.sina.com) 层次: Object -> MimeType (Externalizable, Serializable) MimeTypeParameterList JAF1.0 javax.activation MimeTypeParameterList 表示一个 MIME 类型的可选参数列表(定义于 RFC 2045 和 RFC 2046)。 MimeTypeParameterList 提供了多个方法来操作这些参数:getNames 方法将返回所有参数 的列表,size 获取参数列表中名/值对的数目,isEmpty 测试参数列表是否为空,get 获取与指 定参数名关联的值,set 设置与指定参数名关联的值,remove 删除与指定参数名关联的值, parse 是一个保护方法,它解析一个与 RFC 2045, 2046 兼容的参数列表(字符串形式)。 类声明: public class MimeTypeParameterList { // 构造函数 public MimeTypeParameterList() public MimeTypeParameterList(String parameterList) throws MimeTypeParseException; // 公共实例方法 public String get(String name) public Enumeration getNames() public boolean isEmpty() public void remove(String name) public void set(String name, String value) public int size() public String toString(); // 保护实例方法 protected void parse(String parameterList) throws MimeTypeParseException; } 层次: Object -> MimeTypeParameterList 34 第 8 章 Java Mail MimetypesFileTypeMap JAF1.0 javax.activation MimetypesFileTypeMap 继承自 FileTypeMap 类,它使用.mime.types 格式,通过文件后缀 名提供文件数据类型服务。 MimetypesFileTypeMap 搜索用户系统的不同位置以寻找 MIME 类型(MIME types)文件, 当用户请求检索 MimetypesFileTypeMap 中的 MIME 类型时,程序将按如下顺序搜索 MIME 类型: • 通过编程加入 MimetypesFileTypeMap 实例的 MIME 类型条目(调用 addMimeTypes 方法可以加入 MIME 类型条目); • 用户 home 目录中的.mime.types 文件; • /lib/ mime.types 文件; • 名称为 META-INF/ mime.types 的文件或资源; • 名称为 META-INF/mimetypes.default 的文件或资源(通常在 activation.jar 文件中)。 一个 MIME 类型文件的格式如下: # 注释以'#' 开头,至该行结束处 # 每一个条目的格式为: <该类型所对应的文件后缀名列表,以空格隔开 > # 如下所示: text/plain txt text TXT # 上面的条目将后缀为.txt、.text 和 TXT 的文件映射到 MIME 类型 "text/plain" MimetypesFileTypeMap 提供两个 getContentType 方法,均返回指定文件中数据的 MIME 类型。其中 getContentType(File f) 实际执行的是如下调用:getContentType.(f.getName()),即 它间接调用了 getContentType(String filename)方法。后者将根据文件名参数按上文中列出的顺 序搜索文件名后缀所映射的 MIME 类型。 类声明: public class MimetypesFileTypeMap extends FileTypeMap { // 构造函数 public MimetypesFileTypeMap(); public MimetypesFileTypeMap(InputStream is); public MimetypesFileTypeMap(String mimeTypeFileName) throws IOException; // 公共实例方法 public void addMimeTypes(String mime_types); public String getContentType(File f); public String getContentType(String filename); } 35 J2EE 完全参考手册 (tsl0151@vip.sina.com) 层次: Object -> FileTypeMap -> MimetypesFileTypeMap URLDataSource JAF1.0 javax.activation URLDataSource 实现 DataSource 接口,它封装了 URL(同一资源定位)对象。 URLDataSource 简化了处理 URL 对象所描述数据的过程,因为该类实例可以用于创建一个 DataHandler 对象来处理数据。事实上,通过 URL 参数实例化的 DataHandler 对象在其内部创 建了一个 URLDataSource 对象以供使用。 URLDataSource 类提供了五个方法:其中 getURL 方法返回用于创建该实例的 URL 对象, getInputStream 和 getOutputStream 分别调用该 URL 对象的同名方法,getName 调用该 URL 对象的 getFile 方法,getContentType 方法则返回 URL 头的 content-type 字段。 类声明: public class URLDataSource implements DataSource { // 构造函数 public URLDataSource(URL url); // 公共实例方法 public String getContentType(); public InputStream getInputStream() throws IOException; public String getName(); public OutputStream getOutputStream() throws IOException; public URL getURL(); } 层次: Object -> URLDataSource(DataSource) 8.2.3 异常 MimeTypeParseException JAF1.0 javax.activation Serializable MimeTypeParseException 类封装了与 MIME 类型解析相关的异常,它继承自 Exception 类,除了父类的所有方法外,还定义了两个构造函数:MimeTypeParseException()为缺省的无 参构造函数;MimeTypeParseException(String s) 函数构造一个提供标准异常信息的 36 第 8 章 Java Mail MimeTypeParseException 实例。 类声明: public class MimeTypeParseException extends Exception { // 构造函数 public MimeTypeParseException(); public MimeTypeParseException(String s); } 层次: Object -> Throwable -> Exception -> MimeTypeParseException (Serializable) UnsupportedDataTypeException JAF1.0 javax.activation Serializable UnsupportedDataTypeException 类通知调用者它所请求的操作不支持不支持请求数据类 型。除了父类的所有方法外,UnsupportedDataTypeException 类还定义了两个构造函数: UnsupportedDataTypeException() 为缺省的无参构造函数;UnsupportedDataTypeException (String s)函数构造一个提供标准异常信息的 UnsupportedDataTypeException 实例。 类声明: public class UnsupportedDataTypeException extends IOException { // 构造函数 public UnsupportedDataTypeException(); public UnsupportedDataTypeException(String s); } 层次: Object->Throwable->Exception->IOException->UnsupportedDataTypeException (Serializable) 8.3 javax.mail 包 JavaMail API 的核心类均位于 avax.mail 包中,图 2-5 描述了 javax.mail 包的 UML 图,下 面三节将分别介绍其接口、类和异常。 37 J2EE 完全参考手册 (tsl0151@vip.sina.com) 图 7-5 javax.ejb 包接口结构 8.3.1 接口 38 第 8 章 Java Mail MessageAware JavaMail 1.0 javax.mail 接口定义: public interface BytesMessage extends Message { // 公共实例方法 // read boolean readBoolean() throws JMSException; byte readByte() throws JMSException; } 层次: BytesMessage (Message) 返回自:Session.CreateBytesMessage() getBodyLength 语法:long getBodyLength() throws JMSException 描述:消息处于只读模式时,getBodyLength 方法获取消息主体长度(与当前用于读取 消息的指针位于何处无关)。 返回:消息主体的字节数。 异常:若 JMS 供应器因内部错误而不能读取消息,则抛出 JMSException 异常对象;若 调用该方法时消息处于只写模式,则抛出 MessageNotReadableException 异常对 象。 8.3.2 类 Address JavaMail 1.0 javax.mail abstract Serializable Address 类表示电子邮件地址,它是一个抽象类。其子类(最经常使用的子类是 javax.mail.internet.InternetAddress)提供具体实现,且通常可串行化。 在创建了 Session 和 Message,并设置了消息内容后,可以用 Address 确定信件地址。 若创建的地址只包含电子邮件地址,只要将电子邮件地址传递给构造器即可: Address address = new InternetAddress("president@whitehouse.gov"); 39 J2EE 完全参考手册 (tsl0151@vip.sina.com) 若希望名字紧挨着电子邮件显示,也可以把它传递给构造器: Address address = new InternetAddress("president@whitehouse.gov", "George Bush"); 通常需要为消息的 from 域和 to 字段创建地址对象。在创建了 Address 对象后,将它们 与消息连接的方法有两种。 如果要设置发件人(from),可以使用 setFrom 和 setReplyTo 方法(除非邮件服务器需要 认证,否则你可以很轻易的发送一段看上去是来自其他人的消息): message.setFrom(address) 需要消息显示多个 from 地址,可以使用 addFrom 方法: Address address[] = ...; message.addFrom(address); 如果要设置消息收件人(recipient),可以使用 setRecipient(设置单个收件人地址)、 setRecipients(设置多个收件人地址)或 addRecipient(加入一个收件人地址)方法。除 Address 对象外,这些方法还需要一个 Message.RecipientType 类型参数,该参数表示消息收件人类型。 JMS API 提供了三种预定义消息接收者类型: • Message.RecipientType.TO:消息的主要接收者 • Message.RecipientType.CC:抄送对象 • Message.RecipientType.BCC:匿名收件人 比如说,如果消息是发给董事长的(To),同时发送一个副本给首席执行官(CC),则可 以使用如下代码: Address toAddress = new InternetAddress("chairman@soft.com "); Address ccAddress = new InternetAddress("ceo@soft.com"); message.setRecipient(Message.RecipientType.TO, toAddress); message.addRecipient(Message.RecipientType.CC, ccAddress); JavaMail API 没有提供电子邮件地址有效性核查机制。虽然通过编程,开发者能够扫描 有效字符(如 RFC 822 中定义的)或验证邮件交换(mail exchange,MX)记录,但这些功 能不属于 JavaMail API。 类声明: public abstract class Address extends Object implements Serializable { // 构造函数 Address() // 抽象方法 public abstract boolean equals(Object address); public abstract String getType(); public abstract String toString(); } 层次: Object-> Address(Serializable) 子类: InternetAddress, NewsAddress 传递给:使用 Address 对象作为参数的方法太多,不再一一列出。 40 第 8 章 Java Mail 返回自:javax.mail.search.AddressTerm.getAddress() equals abstract 语法:public abstract boolean equals(Object address) 描述:equals 方法测试两个地址是否相同,该方法覆盖了 Object.equals 方法。 返回:true 表示为同一地址,false 表示不同地址。 getType abstract 语法:public abstract String getType() 描述:getType 方法获取一个表示地址类型的字符串。 返回:地址类型字符串。 toString abstract 语法:public abstract String toString() 描述:toString 方法获取该地址的字符串表示,该方法覆盖了 Object.toString 方法。 返回:表示该地址的字符串。 Authenticator JavaMail 1.0 javax.mail abstract Authenticator 代表一个可以为网络连接获取认证信息的对象,它通常通过提示用户输入 用户名和密码来收集认证信息,使连接可以访问受保护的资源。对于 JavaMail API 来说,这 些资源就是邮件服务器。JavaMail Authenticator 在 javax.mail 包中,它和 java.net 中同名的 类 Authenticator 不同。 要使用 Authenticator,可以先创建一个它的子类实例,并且在会话对象创建时为会话注 册该 Authenticator 对象。在需要认证时,系统将调用 Authenticator 子类上的方法(比如 getPasswordAuthentication)获取认证信息。实例代码如下: Properties props = new Properties(); Authenticator auth = new MyAuthenticator(); // 创建新会话,并为会话注册该 Authenticator 对象 Session session = Session.getDefaultInstance(props, auth); 类声明: public abstract class Authenticator extends Object { 41 J2EE 完全参考手册 (tsl0151@vip.sina.com) // 构造函数 Authenticator(); // 保护方法 protected final String getDefaultUserName(); protected final int getRequestingPort(); protected final String getRequestingPrompt(); protected final String getRequestingProtocol(); protected final InetAddress getRequestingSite(); protected PasswordAuthentication getPasswordAuthentication(); } 层次: Object-> Authenticator 传递给:Session.getInstance(), Session.getDefaultInstance() getDefaultUserName final 语法:protected final String getDefaultUserName() 返回:调用者的缺省用户名。 getRequestingPort final 语法:protected int getRequestingPort() 返回:请求连接的端口号。 getRequestingPrompt final 语法:protected final String getRequestingPrompt() 返回:请求者给出的提示字符串。 getRequestingProtocol final 语法:protected final String getRequestingProtocol() 返回:请求建立连接的协议。 getRequestingSite final 语法:protected final InetAddress getRequestingSite() 返回:InetAddress 对象,代表要求认证的站点地址。 42 第 8 章 Java Mail getPasswordAuthentication 语法:protected PasswordAuthentication getPasswordAuthentication() 描述:当需要请求者提供密码时,getPasswordAuthentication 方法被调用以获取密码。该 方法的缺省实现返回空值,Authenticator 的子类必须覆盖该方法。该方法可以弹 出窗口,也可以从配置文件中(虽然没有加密是不安全的)读取密码。如果该方 法的实现使用一个对话框来要求用户输入密码,则对话框应该一直阻塞程序直到 用户提供信息为止,该方法不能在显示对话框后立即异步返回。 返回:PasswordAuthentication 对象,该对象是使用收集到的密码信息作为构造函数参数 创建的。 Folder JavaMail 1.0 javax.mail abstract Folder 是一个抽象类,它表示一个包含消息的目录,其子类提供针对具体协议的实现。 Folder 类包含众多方法,是一个比较庞大的类,我们将从下面几个方面来讨论这个类。 (1)Folder 分层体系 Folder 代表的目录可以容纳消息或子目录,它使用这种方式提供了一个类似于树的分层 体系。程序可以使用 getType 方法来判断某个目录的类型:即它是只能容纳子目录 (Folder.HOLDS_MESSAGES),还是只能容纳目录(Folder.HOLDS_FOLDERS),或者两者都 可以容纳(Folder.HOLDS_MESSAGES| Folder.HOLDS_FOLDERS)。 在分层体系中,目录名称的解释依赖于具体实现,其全名(即路径相对于存储器中的根 目录的名称)中相邻的两层用层次分隔符隔开,通过 getFullName 方法可获取目录全名,通 过 getSeparator 可以获取层次分隔符。大小写敏感的目录全名 INBOX 被 JavaMail API 保留, 它表示该用户在该服务器上的主目录。POP3 可用的目录只有 INBOX;如果使用 IMAP,则 服务器还可以为用户提供其它目录。 在 Store 对象上调用 getDefaultFolder 方法将返回该用户名字空间内分层体系的根目录。 在 Folder 对象上调用 list 方法将列出该目录下的所有子目录;调用 getFolder(String name)方法 将返回该目录下指定名称的子目录。 值得注意的是,即使该目录下并不存在具有 name 名称的目录,getFolder(String name)也 会返回一个目录对象,在返回目录对象上调用 exists 方法可以判断出该目录是否确实存在。 若目录对象在分层体系中实际上并不存在,则它可以调用 create(int type)方法来创建自身;目 录创建成功后,分层体系中相应路径下会出现这个目录,同时目录事件 CREATED 将被发送 给该目录上注册的所有目录监听器和容纳该目录的 Store 对象。 (2)目录状态 目录有打开和关闭两种状态,isOpen 方法可以测试目录当前的开关状态。除了状态测试 方法外,一个关闭的目录可以执行如下操作,包括: 43 J2EE 完全参考手册 (tsl0151@vip.sina.com) • 删除目录,使用 delete(boolean recurse)方法。其参数 recurse 表示删除操作是否影响子 目录,若 recurse 为 true,则 delete 方法首先删除其子目录,然后删除自身;若 recurse 为 false,则 delete 方法行为依赖于目录类型:如果目录只包含消息(type 值为 Folder.HOLDS_MESSAGES),则先删除目录内所有消息,然后删除自身,并发送一 个适当的 FolderEvent 事件;如果目录只包含子目录(type 值为 Folder.HOLDS_FOLDERS),则若该目录为空,即直接删除自身,并发送一个适当的 FolderEvent 事件,否则方法调用失败;如果目录中同时包含子目录和消息(type 值为 Folder.HOLDS_FOLDERS| Folder.HOLDS_FOLDERS),则方法语意依赖于具体实现。 • 重命名目录,使用 renameTo 方法。若重命名成功,则发送一个 RENAMED 目录事件。 • 创建子目录:使用 create 方法。若创建子目录成功,则发送一个 CREATED 目录事件。 • 监视新的邮件:使用 hasNewMessages 判断从上一次调用该方法算起,是否有新的邮 件到达。 • 列出子目录:可以使用 list(String pattern)、listSubscribed(String pattern)、list()和 listSubscribed()方法。上述第三个和第四个方法分别是第一个和第二个方法的简化版本 (将 pattern 参数默认为“%”);第二个方法又是第一个方法的特例,即限定所列出 的子目录必须是订阅目录。因此我们可以重点看一下第一个方法 list(String pattern)。 list(String pattern)方法获取属于该目录名字空间、匹配指定模式的目录列表。模式 pattern 可能包括通配符“%”,它匹配除了层次分隔符和“*”外的所有字符,而通配符“*”则匹配 任意字符。 举例来说,图 2-8 给出了一个目录层次。依图所示,则在 company 目录上调用 list("*") 将返回图中的所有目录,调用 list("%")将返回“SUN”和“Microsoft”目录,调用 list("Microsoft") 将返回“Microsoft”目录,调用 list("J2*")将返回“J2ME”、“J2SE”和“J2EE”目录。 图 2-8 目录层次示例 open 方法可以打开关闭的目录(注意:open 方法只能应用于可以容纳邮件消息的目录), 同时指定打开模式:只读(mode 值为 Folder.READ_ONLY )、读写(mode 值为 Folder.READ_WRITE)或未定(mode 值为-1)。目录打开后,可以通过 getMode 方法测试目 录打开模式。在一个打开的目录上可以执行除了 open、delete、renameTo 外的所有合法操作。 (3)邮件消息的读取 存储在目录内的消息被顺序计数(从 1 开始到消息总数),该顺序被称为“邮箱顺序”, 通常基于邮件消息到达目录的顺序。在每一个新的消息到达邮箱时,它被赋予比之前目录内 邮件总数大 1 的序列号,在一个消息上调用 getMessageNumber 方法将返回其序列号。邮件顺 44 第 8 章 Java Mail 序的变动将改变消息的序列号,这种情况仅发生在客户程序调用 expunge 方法擦除目录内设 置了 Flags.Flag.DELETED 标志位的消息时。执行擦除操作后,目录内消息将重新编号。 客户程序可以通过消息序列号或直接通过相应的 Message 对象引用目录中的消息,因为 消息序列号在会话中很可能改变,因此应尽可能保存 Message 对象而非序列号来反复引用对 象。 扩展了 JavaMail 的客户机程序应该提供轻量级的、可以“按需填充”的 Message 对象, 这样在 Folder 对象上调用 getMessages 方法将不会浪费太多(CPU、内存和网络)资源:它 从服务器上读取每一条消息,但仅在你实际需要消息的一部分时,消息的内容才会被检索。 比如说,一个 IMAP 实现可以返回仅包含 IMAP UID 的 Message 对象。 下面我们来看一段从目录中获取消息的代码: // 连接到 Store 之后,可以获取一个目录,必需先打开它才能读里面的消息。 // POP3 唯一可以用的目录是 INBOX。如果使用 IMAP,还可以用其它目录。 Folder folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); Message message[] = folder.getMessages(); 一旦确定需要处理某个消息,就可以用 getContent()来获取其内容,或者用 writeTo()将 其内容写入流。getContent 方法只能得到消息内容,而 writeTo 方法的输出却包含消息头: System.out.println(((MimeMessage)message[i]).getContent()); 在处理完邮件后,要关闭与目录和存储器的连接,如下所示。 // 传递给 folder.close()方法的 boolean 表示是否清除已删除的消息从而更新 folder。 folder.close(aBoolean); store.close(); (4)事件和监听器 目录创建事件以通知监听器 Folder 本身或其内部的消息发生了变化,客户机可以在关闭 的目录上注册监听器,但通知事件的创建只能在目录已打开的情况下发生。 Folder 类可以向其上相关的监听器发送表 2-1 中所列三类事件: 表 2-1 Folder 发送的三类事件 事件 描述 ConnectionEvent 在目录打开或关闭时产生该事件。当目录关闭(可能是因为客户程序调用了 close 方法,也可能是因为某些外部原因)时,所有属于该目录的消息组件都变为非法 的,通常客户机将试图重新打开该目录以恢复原有状态。 FolderEvent 当客户程序创建一个新目录、删除或重命名一个已存在的目录时产生该类事件。 必须注意的是容纳该目录的 Store 对象在这些情况下也将产生这类信息。。 MessageCountEvent 该类事件通知监听器消息数目有了改变,下列操作可以引发这种改变: 有新的消息的进入目录。这可能是因为传输代理也可能是因为一个 appendMessages 方法调用,新的消息将包括在事件中。 已存在的消息从目录中擦除。在已擦除的消息上调用 isExpunged 方法将返回 true, 调用 getMessageNumber 将返回该消息原来的序列号,在擦除消息上调用除此以 45 J2EE 完全参考手册 (tsl0151@vip.sina.com) 外的任何消息都将抛出 MessageRemovedException。已擦除的消息将包括在事件 中。 Folder 类提供了多个操纵相关监听器的方法,这些方法可以分为三类; • 注册监听器方法: • 卸载监听器方法 • 通知监听器方法 表 2-2 列出了这些方法及其相关描述。 表 2-2 Folder 操纵相关监听器的方法 方法类型 方法名称 描述 addConnectionListener 为该目录注册一个连接监听器(ConnectionListener) addFolderListener 为该目录注册一个目录监听器(FolderListener) addMessageChangedListener 为该目录注册一个消息修改监听器 (MessageChangedListener) 注册监听器方法 addMessageCountListener 为该目录注册一个消息计数监听器 (MessageCountListener) removeConnectionListener 卸载该目录的一个连接监听器(ConnectionListener) removeFolderListener 卸载该目录的一个目录监听器(FolderListener) removeMessageChangedListener 卸载该目录的一个消息修改监听器 (MessageChangedListener) 卸载监听器方法 removeMessageCountListener 卸载该目录的一个消息计数监听器 (MessageCountListener) notifyConnectionListeners 通知该目录上注册的所有连接监听器和容纳该目录 的 Store 对象某个连接事件(ConnectionEvent),Folder 实现类应该使用该方法广播连接事件。 notifyFolderListeners 通知该目录上注册的所有目录监听器和容纳该目录 的 Store 对象某个目录事件(FolderEvent),Folder 实 现类应该使用该方法广播目录事件。 notifyFolderRenamedListeners 通知该目录上注册的所有目录监听器和容纳该目录 的 Store 对象当前目录重命名事件,Folder 实现类应 该使用该方法广播目录事件(FolderEvent)以指示该 目录已被重命名(JavaMail 1.1)。 notifyMessageAddedListeners 通知该目录上注册的所有消息计数监听器和容纳该 目录的 Store 对象有新消息加入了该目录,Folder 实 现类应该使用该方法广播消息计数事件 (MessageCountEvent)。 通知监听器方法 notifyMessageChangedListeners 通知该目录上注册的所有消息修改监听器和容纳该 46 第 8 章 Java Mail 目录的 Store 对象某个消息已被修改,Folder 实现类 应该使用该方法广播消息修改事件 (MessageChangedEvent)。 notifyMessageRemovedListeners 通知该目录上注册的所有消息计数监听器和容纳该 目录的 Store 对象某个消息已从目录中删除,Folder 实现类应该使用该方法广播消息计数事件 (MessageCountEvent)以指示某个消息已被删除。 类声明: public abstract class Folder extends Object { // 常量 static int HOLDS_FOLDERS; static int HOLDS_MESSAGES; static int READ_ONLY; static int READ_WRITE; // 实例字段 protected int mode; protected Store store; // 构造函数 protected Folder(Store store); // 抽象方法 public abstract void appendMessages(Message[] msgs) throws MessagingException; public abstract void close(boolean expunge) throws MessagingException; public abstract boolean create(int type) throws MessagingException; public abstract boolean delete(boolean recurse) throws MessagingException; public abstract boolean exists() throws MessagingException; public abstract Message[] expunge() throws MessagingException; public abstract Folder getFolder(String name) throws MessagingException; public abstract Message getMessage(int msgnum) throws MessagingException; public abstract int getMessageCount() throws MessagingException; public abstract String getFullName(); public abstract String getName(); public abstract Folder getParent() throws MessagingException; public abstract Flags getPermanentFlags(); public abstract char getSeparator() throws MessagingException; public abstract int getType() throws MessagingException; public abstract boolean hasNewMessages() throws MessagingException; public abstract boolean isOpen(); public abstract Folder[] list(String pattern) throws MessagingException; public abstract void open(int mode) throws MessagingException; 47 J2EE 完全参考手册 (tsl0151@vip.sina.com) abstract boolean renameTo(Folder f) throws MessagingException; // 公共实例方法 public void addConnectionListener(ConnectionListener l); public void addFolderListener(FolderListener l); public void addMessageChangedListener(MessageChangedListener l); public void addMessageCountListener(MessageCountListener l); public void copyMessages(Message[] msgs, Folder folder) throws MessagingException; public void fetch(Message[] msgs, FetchProfile fp) throws MessagingException; public int getDeletedMessageCount() throws MessagingException; public Message[] getMessages() throws MessagingException; public Message[] getMessages(int[] msgnums) throws MessagingException; public Message[] getMessages(int start, int end) throws MessagingException; public int getMode(); public int getNewMessageCount() throws MessagingException; public Store getStore(); public int getUnreadMessageCount() throws MessagingException; public URLName getURLName() throws MessagingException; public boolean isSubscribed(); public Folder[] list() throws MessagingException; public Folder[] listSubscribed() throws MessagingException; public Folder[] listSubscribed(String pattern) throws MessagingException; public void removeConnectionListener(ConnectionListener l); public void removeFolderListener(FolderListener l); public void removeMessageChangedListener(MessageChangedListener l); public void removeMessageCountListener(MessageCountListener l); public Message[] search(SearchTerm term) throws MessagingException; public Message[] search(SearchTerm term, Message[] msgs) throws MessagingException; public void setFlags(int[] msgnums, Flags flag, boolean value) throws MessagingException; public void setFlags(int start, int end, Flags flag, boolean value) throws MessagingException; public void setFlags(Message[] msgs, Flags flag, boolean value) throws MessagingException; public void setSubscribed(boolean subscribe) throws MessagingException; public String toString(); // 保护方法 protected void finalize() throws Throwable; protected void notifyConnectionListeners(int type); protected void notifyFolderListeners(int type); protected void notifyFolderRenamedListeners(Folder folder); protected void notifyMessageAddedListeners(Message[] msgs); protected void notifyMessageChangedListeners(int type, Message msg); protected void notifyMessageRemovedListeners(boolean removed, Message[] msgs); 48 第 8 章 Java Mail } 层次: Object -> Folder 传递给:Folder.copyMessages(), Message.Message(), MimeMessage.MimeMessage(), Folder.notifyFolderRenamedListeners() , Folder.renameTo(), Store.notifyFolderListeners(), Store.notifyFolderRenamedListeners(), MessageCountEvent.MessageCountEvent(), FolderClosedException.FolderClosedException(), ReadOnlyFolderException.ReadOnlyFolderException(), FolderNotFoundException().FolderNotFoundException(), javax.mail.event.FolderEvent.javax.mail.event.FolderEvent() 返回自:Session.getFolder(), Folder.getFolder (), Store.getFolder() 备注: 该类虽然属于 JavaMail 核心类之一,但因为过于庞大,在上文中给出解释或实例的 方法不会再逐一介绍。 copyMessages 语法:public void copyMessages(Message[] msgs, Folder folder) throws MessagingException; 描述:copyMessages 方法将指定消息从当前目录复制到另一个目录,目标目录可以保持 在关闭状态。当复制消息追加到目的目录时,一个消息计数事件 (MessageCountEvent)被传递给目的目录上注册的所有消息计数监听器。 返回:msgs:待复制消息数组,这些消息必须属于当前目录;folder:目标目录。 异常:若方法调用出现问题,则抛出 MessagingException;若目标目录不存在,则抛出 FolderNotFoundException;若当前目录未打开,则抛出 IllegalStateException。 fetch 语法:public void fetch(Message[] msgs, FetchProfile fp) throws MessagingException; 描述:fetch 方法为指定消息批量预取 FetchProfile 参数指定的条目,请参考 FetchProfile 类说明。 返回:msgs:指定范围的批量消息;fp:FetchProfile 对象,制定预取内容。 异常:若方法调用出现问题,则抛出 MessagingException;若当前目录未打开,则抛出 IllegalStateException。 getDeletedMessageCount 语法:public int getDeletedMessageCount() throws MessagingException; 描述:getDeletedMessageCount 方法获取当前目录中被删除的消息数目。该方法可以在 目录关闭时调用,但必须注意,在某些实现中,这样的操作代价将很大——它必 49 J2EE 完全参考手册 (tsl0151@vip.sina.com) 须先打开目录;因此供应商可以选择不支持在目录关闭的状态下调用该方法,即 若客户程序在目录关闭时调用该方法则返回-1。该方法的缺省实现(SUN 提供) 在目录关闭时将返回-1;否则它将检查目录内的每一个消息其 DELETED 标志位 是否被设置,并返回 DELETED 标志位被设置的消息的总数。 返回:当前目录中被删除的消息数目,若当前目录被关闭则可能返回-1。 异常:若方法调用出现问题,则抛出 MessagingException;若当前目录不存在,则抛出 FolderNotFoundException。 getFullName abstract 语法:public abstract String getFullName() 描述:getFullName 方法获取目录全名。如果该目录位于当前存储器分层体系下,则方 法返回相对于根目录的的路径名;否则方法返回以层次分隔符开头的绝对路径 名。该方法可以在关闭的目录上调用。 返回:目录全路经名。 getName abstract 语法:public abstract String getName() 描述:getName 方法获取该目录名称,该方法可以在关闭的目录上调用。 返回:目录名称。 getNewMessageCount 语法:public int getNewMessageCount() 描述:getNewMessageCount 方法获取该目录内新消息数目。该方法可以在目录关闭时调 用,但必须注意,在某些实现中,这样的操作代价将很大——它必须先打开目录; 因此供应商可以选择不支持在目录关闭的状态下调用该方法,即若客户程序在目 录关闭时调用该方法则返回-1。该方法的缺省实现(SUN 提供)在目录关闭时将 返回-1;否则它将检查目录内的每一个消息其 RECENT 标志位是否被设置,并返 回 RECENT 标志位被设置的消息的总数。 返回:新消息数目,若当前目录被关闭则可能返回-1。 异常:若方法调用出现问题,则抛出 MessagingException;若当前目录不存在,则抛出 FolderNotFoundException。 getParent abstract 语法:public abstract Folder getParent() throws MessagingException 50 第 8 章 Java Mail 描述:getParent 方法获取该目录的父目录,若该目录是分层体系的根目录,则方法返回 空值。 返回:该目录的父目录。 异常:若方法调用出现问题,则抛出 MessagingException。 getPermanentFlags abstract 语法:public abstract Flags getPermanentFlags() 描述:getPermanentFlags 方法获取该目录支持的所有持久标志,将返回一个包括所有标 志位的 Flags 对象。特别的,Flags.USER 标志位指出该目录是否支持任意的用户 定义的标志。目录支持的持久标志可能必须在该目录打开后才可用。 返回:包括所有标志位的 Flags 对象,可能返回空值。 getStore 语法:public Store getStore() 描述:getStore 方法获取容纳该目录的存储器对象,该方法可以在目录关闭时调用。 返回:容纳该目录的存储器对象。 getUnreadMessageCount 语法:public int getUnreadMessageCount() 描述:getUnreadMessageCount 方法获取该目录内未被阅读消息的数目。该方法原理与 getDeletedMessageCount 类似,在目录被关闭的情况下可能返回-1。方法缺省实现 (SUN 提供)在目录关闭时将返回-1;否则它将检查目录内的每一个消息其 SEEN 标志位是否被设置,并返回 SEEN 标志位未被设置的消息的总数。 返回:未被阅读消息的数目,若当前目录被关闭则可能返回-1。 异常:若方法调用出现问题,则抛出 MessagingException;若当前目录不存在,则抛出 FolderNotFoundException。 getURLName JavaMail 1.1 语法:public URLName getURLName() throws MessagingException 描述:getURLName 方法获取代表该目录的 URLName 对象,读者可参考 URLName 类 说明。注意:返回的 URLName 对象并不包括用于访问存储器的密码。 返回:代表该目录的 URLName 对象。 异常:若方法调用出现问题,则抛出 MessagingException。 51 J2EE 完全参考手册 (tsl0151@vip.sina.com) isSubscribed 语法:public boolean isSubscribed() 描述:isSubscribed 方法测试该目录是否已被订阅,该方法可以在目录关闭时调用。方 法的缺省实现(SUN 提供)仅返回 true。 返回:若该目录已被订阅,则返回 true;否则返回 false。 search I 语法:public Message[] search(SearchTerm term) throws MessagingException 描述:该方法检索目录中匹配指定搜索条件的消息,返回匹配消息数组。 参数:term:搜索条件,读者可参考 SearchTerm 类说明。 返回:匹配指定搜索条件的 Message 对象数组;若找不到匹配消息,则可能返回空数组。 异常:若搜索语句过于复杂以至 Folder 实现类不能处理,则抛出 SearchException;若当 前目录不存在,则抛出 FolderNotFoundException;若 Folder 对象当前未打开,则 抛出IllegalStateException异常;若方法调用出现问题,则抛出MessagingException。 search II 语法:public Message[] search(SearchTerm term, Message[] msgs) throws MessagingException 描述:该方法检索指定消息数组中匹配指定搜索条件的消息,该消息数组中的消息必须 属于当前目录。 参数:term:搜索条件,读者可参考 SearchTerm 类说明;msgs:待搜索消息数组。 返回:匹配指定搜索条件的 Message 对象数组;若找不到匹配消息,则可能返回空数组。 异常:若搜索语句过于复杂以至 Folder 实现类不能处理,则抛出 SearchException;若当 前目录不存在,则抛出 FolderNotFoundException;若方法调用出现问题,则抛出 MessagingException。 setFlags I 语法:public void setFlags(int[] msgnums, Flags flag, boolean value) throws MessagingException 描述:该方法设置成批消息的指定标志位值,这将引发一个 MessageChangedEvent 被传 递给该目录上注册的所有消息修改监听器。某些 Folder 类实现将优化这种成批设 置标志位的操作,所有客户程序可以使用这种方法更好的代替为每个消息调用 Message.setFlags 方法设置标志位的方法。 返回:msgnums:消息序列号数组,表示所有待搜索消息的序列号;flag:包含待设置 标志位的 Flags 对象;value:待设置值。 异常:若方法调用出现问题,则抛出 MessagingException;若目录未打开或以只读模式 52 第 8 章 Java Mail 打开,则抛出 IllegalStateException;若给定数组中的消息序列号越界,则抛出 IndexOutOfBoundsException。 setFlags II 语法:public void setFlags(int start, int end, Flags flag, boolean value) throws MessagingException 描述:该方法语义与 setFlags(I)完全相同,但其消息范围的指定方式与后者不同。本 方法使用 start 和 end 参数分别指定批量消息的起始序列号和终止序列号(从 1 算 起),该范围内的所有消息都将被设置标志位。 返回:start:起始序列号;end:终止序列号;flag:包含待设置标志位的 Flags 对象; value:待设置值。 异常:若方法调用出现问题,则抛出 MessagingException;若目录未打开或以只读模式 打开,则抛出 IllegalStateException;若起始序列号或终止序列号越界,则抛出 IndexOutOfBoundsException。 setFlags III 语法:public void setFlags(Message[] msgs, Flags flag, boolean value) throws MessagingException 描述:该方法语义与 setFlags(I)完全相同,但其消息范围的指定方式与后者不同。本 方法直接指定待设置标志位的 Message 对象数组。 返回:msgs:Message 对象数组;flag:包含待设置标志位的 Flags 对象;value:待设置 值。 异常:若方法调用出现问题,则抛出 MessagingException;若目录未打开或以只读模式 打开,则抛出 IllegalStateException。 setSubscribed 语法:public void setSubscribed(boolean subscribe) throws MessagingException 描述:setSubscribed 方法订阅或退订当前目录,该方法可以在关闭的目录上调用。不是 所有的存储器都支持订阅,缺省实现仅抛出 MethodNotSupportedException 参数:subscribe:为 true 表示订阅该目录;为 false 表示取消对该目录的订阅。 异常:若该目录不存在,则抛出 FolderNotFoundException;若存储器不支持订阅,则抛 出 MethodNotSupportedException ;若方法调用出现问题,则抛出 MessagingException。 toString 语法:public String toString() throws Throwable 53 J2EE 完全参考手册 (tsl0151@vip.sina.com) 描述:getDefaultFolder 方法获取 Store 对象为客户提供的缺省名字空间的根目录。 返回:Folder 对象,表示缺省名字空间内的最顶层目录。 异常:若方法调用出现问题,则抛出 MessagingException;若 Store 对象当前未连接,则 抛出 IllegalStateException 异常。 Message JavaMail 1.0 javax.mail abstract 获得 Session 对象后,可以开始继续创建要发送的邮件消息。这由 Message 类来完成, Message 实现了 Part 接口,它表示一个邮件消息,包含一系列属性(attribute)和一个消息内 容(content)。消息属性标识了消息地址信息,定义了消息内容的结构(包括内容类型);消 息内容使用 DataHandler 对象包装实际数据。 Message 是抽象类,实际使用时必需用一个子类代替以表示具体的邮件格式。比如说, JavaMail API 提供了 MimeMessage(位于 javax.mail.internet.MimeMessage 包)类,该类扩展 自 Message,实现了 RFC822 和 MIME 标准。Message 的子类通常通过字节流构建其实例, 相应的,它们也可以生成字节流来传输自身。 一个 Message 子类实例包括消息内容、标识发送者和接收者的地址属性、消息的结构信 息和消息内容的类型,当邮件消息位于目录(folder)中时,系统还使用一个标志位集合来描 述它的状态。图 2-9 描述了 Message 类的对象层次,图 2-10 描述了消息的结构。 图 2-9 Message 类的对象层次 54 第 8 章 Java Mail 图 2-10 邮件消息结构 Message 对象可能包含多个部分(part),其中每一部分都有它自己的属性集和内容。一 个含多个部分的消息的内容是一个 Multipart 对象,Multipart 包含多个 BodyPart 对象,每一 个 BodyPart 表示一个独立的部分。Message 和 BodyPart 均继承自 Part 接口,这使得它们在结 构和语义上有很大程度的相似性,读者可参考图 2-3。 继承自 Part 接口的 ContentType 属性标识了消息内容的数据类型,该类型遵循 MIME 类 型规范(RFC 2045)。一个 MIME 类型由一个主类型和一个子类型组成,主类型声明了消息 内容的一般类型,子类型标识了消息内容的专用格式;此外 MIME 类型还包括特定类型参数 的可选集合。 JavaMail API 组件可以通过下述机制访问消息内容: 表 2-3 JavaMail API 访问消息内容机制 访问机制 描述 作为输入流 Part 接口的 getInputStream 方法将消息内容作为输入流返回。注意:Part 接口 的实现在输入流返回前将解码任何在邮件传输过程进行的编码。 作为 DataHandler 对象 Part 接口的 getDataHandler 方法将返回一个包装了消息内容的 javax.activation.DataHandler 对象。访问 DataHandler 对象的方法请参考本章对 55 J2EE 完全参考手册 (tsl0151@vip.sina.com) JAF 技术的介绍。 作为 Java 语言的一个对象 Part 接口的 getContent 方法将消息内容作为 Java 语言的一个对象(Object)返 回,返回对象的实际类型取决于消息内容的数据类型。如果内容包括多个部分, 则 getContent 方法返回一个 Multipart(或其子类)的实例;若内容类型未知, 则 getContent 方法返回一个输入流。事实上,getContent 方法使用了 getDataHandler 方法以获取消息内容的原始形式。 如图 2-5 所示,除了继承自 Part 接口的属性外,Message 类加入了另一些标准属性,这 些属性包括发送者和接收者地址(From、Recipients)、主题(Subject)、标志(Flags)和发 送与接收日期(SentDate、ReceivedDate)。Message 类也支持非标准的头属性,但并不是所 有的消息系统都支持任意形式的消息头。 Message 对象要么从 Folder 对象读取得到,要么由某一子类通过构造函数实例化得到。 存储在 Folder 内的 Message 对象被顺序计数(从 1 开始),Folder 内的 Message 数目在执行擦 除(expunge)操作时将改变,该操作删除 Folder 内设置了 Flags.Flag.DELETED 标志位的消 息。从 Folder 中获取的消息只是对实际消息的一个轻量级引用,只有在实际需要某条消息时, 消息的内容才被检索。下面的代码示范了后一种创建方法。 //要创建一个 Message,请将 Session 对象传递给 MimeMessage 构造器: MimeMessage message = new MimeMessage(session); 一旦创建了消息,开发者就可以设置消息的各个部分。因为 Message 实现 Part 接口(且 MimeMessage 实现 MimePart 接口),设置内容的可以使用 Part 接口的 setContent()方法,同时 传入两个参数,分别代表消息内容和其 MIME 类型,如下所示: message.setContent("Hello", "text/plain"); 如果开发者知道实际在使用 MimeMessage,而且消息是纯文本格式,就可以使用 setText 方法,它只需要传入代表实际内容的参数(MIME 类型默认为 text/plain): message.setText("Hello"); 后一种格式是设置纯文本消息内容的首选机制。至于发送其它类型的消息,如 HTML 文 件格式的消息,则首选前者。 用 setSubject 可以方法设置消息主题,用 setHeader 方法可以设置消息头属性,这些方法 的调用形式都与 setContent 方法类似;当然,它们都有对应的 get 方法来获取这些信息。 类声明: public abstract class Message extends Object implements Part { // 嵌套类 static class Message.RecipientType; // 字段 protected boolean expunged; protected Folder folder; protected int msgnum; protected Session session; // 构造函数 56 第 8 章 Java Mail protected Message(); protected Message(Folder folder, int msgnum); protected Message(Session session); // 抽象方法 public abstract Address[] getFrom() throws MessagingException; public abstract Flags getFlags() throws MessagingException; public abstract Date getSentDate() throws MessagingException; public abstract String getSubject() throws MessagingException; public abstract Date getReceivedDate() throws MessagingException; public abstract Address[] getRecipients(Message.RecipientType type) throws MessagingException; public abstract void addRecipients(Message.RecipientType type,Address[] ad)throws MessagingException; public abstract void addFrom(Address[] addresses) throws MessagingException; public abstract void setSentDate(Date date) throws MessagingException; public abstract void setSubject(String subject) throws MessagingException; public abstract void setRecipients(Message.RecipientType type,Address[] ad)throws MessagingException; public abstract void setFlags(Flags flag, boolean set) throws MessagingException; public abstract void setFrom() throws MessagingException; public abstract void setFrom(Address address) throws MessagingException; public abstract Message reply(boolean replyToAll) throws MessagingException; public abstract void saveChanges() throws MessagingException; // 保护方法 protected void setExpunged(boolean expunged); protected void setMessageNumber(int msgnum); // 公共方法 public void addRecipient(Message.RecipientType type, Address address) throws MessagingException; public Address[] getAllRecipients() throws MessagingException; public Folder getFolder(); public int getMessageNumber(); public Address[] getReplyTo() throws MessagingException; public boolean isExpunged(); public boolean isSet(Flags.Flag flag) throws MessagingException; public boolean match(SearchTerm term) throws MessagingException; public void setFlag(Flags.Flag flag, boolean set) throws MessagingException; public void setRecipient(Message.RecipientType type, Address address) throws MessagingException; public void setReplyTo(Address[] addresses) throws MessagingException; } 层次: Message (Part) 子类: MimeMessage 传递给:使用 Message 对象作为参数的方法太多,不再一一列出。 57 J2EE 完全参考手册 (tsl0151@vip.sina.com) 返回自:Folder.getMessage(),Folder.getMessages()*, UIDFolder.getMessageByUID(), UIDFolder.getMessagesByUID()*, MessageContext.getMessage(), MessageCountEvent.getMessages()*, javax.mail.event.TransportEvent.getMessage(), javax.mail.event.StoreEvent.getMessage(), javax.mail.event.MessageChangedEvent.getMessage() expunged Field 语法:protected boolean expunged 描述:若该消息已被擦除,则字段值为 true;否则为 false。 folder Field 语法:protected Folder folder 描述:若该消息来自目录,则该字段表示该目录对象。 msgnum Field 语法:protected int msgnum 描述:该消息所在目录消息数目,若消息不是从目录中获取,则该字段为 0。 session Field 语法:protected Session session 描述:该消息所在会话。 Message 语法:protected Message() 描述:无参构造函数。 Message 语法:protected Message(Folder folder, int msgnum) 描述:使用 Folder 对象和消息序号作为参数的构造函数,由 Folder 实现类使用。 58 第 8 章 Java Mail Message 语法:protected Message(Session session) 描述:在会话上创建一个消息,由客户机程序使用。 getFrom abstract 语法:public abstract Address[] getFrom() throws MessagingException 描述:getFrom 方法获取(邮件)消息的 From 属性(Attribute)值,它包含希望发送该 消息的(邮件)地址列表。在某些实现中,该属性值不同于实际消息的实体。若 该属性未出现在消息中,则返回 null;若该属性出现在消息中,但不包含任何地 址,则返回空队列。 返回:Address 对象数组。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 getFlags abstract 语法:public abstract Flags getFlags() throws MessagingException 描述:getFlags 方法获取一个 Flags 对象,它包含该消息的标志。修改返回 Flags 对象的 内容不会影响消息标志;要修改消息标志,必须使用 setFlags 方法。 返回:包含该消息的标志的 Flags 对象。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 getSentDate abstract 语法:public abstract Date getSentDate() throws MessagingException 描述:getSentDate 方法获取该消息发送日期。 返回:Date 对象,表示消息发送日期。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 getSubject abstract 语法:public abstract String getSubject() throws MessagingException 描述:getSubject 方法获取消息主题。 返回:消息主题字符串。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 59 J2EE 完全参考手册 (tsl0151@vip.sina.com) getReceivedDate abstract 语法:public abstract Date getReceivedDate() throws MessagingException 描述:getReceivedDate 方法获取消息接收日期。 返回:Date 对象,表示消息接收日期。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 getRecipients abstract 语法:public abstract Address[] getRecipients(Message.RecipientType type) throws MessagingException 描述:getRecipients 方法获取指定类型的所有接收者地址。 参数:type:指定接收类型,如 CC(抄送)。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 addRecipient 语法:public void addRecipient(Message.RecipientType type, Address address) throws MessagingException 描述:该方法将一个接收者地址加入指定类型的消息接收者中,该方法的缺省使用了 addRecipients 方法。 参数:type:指定接收类型,如 CC(抄送);address:待加入的接收者地址。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常。 addRecipients abstract 语法:public abstract void addRecipients(Message.RecipientType type, Address[] addresses) throws MessagingException 描述:addRecipients 方法增加指定类型的消息接收者。 参数:type:指定接收类型,如 CC(抄送);addresses:待加入的接收者地址数组。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 addFrom abstract 语法:public abstract void addFrom(Address[] addresses) throws MessagingException 描述:addFrom 方法向 From 属性方法加入发送者地址。 参数:addresses:发送者地址数组。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常;若该消息来自一个只读的目录 60 第 8 章 Java Mail (Folder),则抛出 IllegalStateException 异常。 setSentDate abstract 语法:public abstract void setSentDate(Date date) throws MessagingException 描述:setSentDate 方法设置消息发送日期。 参数:date:Data 对象,表示发送日期。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 setSubject abstract 语法:public abstract void setSubject(String subject) throws MessagingException 描述:setSubject 方法设置消息主题。 参数:subject:消息主题字符串。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 setRecipients abstract 语法:public abstract void setRecipients(Message.RecipientType type, Address[] addresses) throws MessagingException 描述:setRecipients 设置接收者地址,指定类型的所有接收者地址全部被 addresses 参数 取代。 参数:type:接收类型;addresses:接收者地址数组。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常;若该消息来自一个只读的目录 (Folder),则抛出 IllegalStateException 异常。 setFlags abstract 语法:public abstract void setFlags(Flags flag, boolean set) throws MessagingException 描述:setFlags 方法设置消息上指定标志的值,消息上没有包含在 flag 标志中的标志位 的值将不受影响。该方法将引发 MessageChangedEvent 事件,事件将传递给当前 消息所在目录(Folder)所注册的任一消息修改监听器(MessageChangedListener) 对象。 参数:flag:指定标志;set:待设置值,为 true 表示 flag 中的所有标志位被设置,为 false 表示这些标志位未被设置。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常;若该消息来自一个只读的目录 61 J2EE 完全参考手册 (tsl0151@vip.sina.com) (Folder),则抛出 IllegalStateException 异常。 setFlag 语法:public void setFlag(Flags.Flag flag, boolean set) throws MessagingException 描述:setFlag 方法指定消息的某个标志位(由 flag 参数指定)的值,这将引发 MessageChangedEvent 事件,该事件将传递给当前消息所在目录(Folder)所注册 的任一消息修改监听器(MessageChangedListener)对象。该方法的缺省实现调用 了 setFlags 方法。 参数:flag:Flags.Flag 对象,包含将设置的标志位;set:待设置值,为 true 表示该标志 位被设置,为 false 表示该标志位未被设置。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常;若该消息来自一个只读的目录 (Folder),则抛出 IllegalStateException 异常。 setFrom abstract I 语法:public abstract void setFrom() throws MessagingException 描述:该方法使用 mail.user 属性值设置消息的 From 属性;若 mail.user 属性不存在,则 使用系统属性 user.name 进行设置。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常;若该消息来自一个只读的目录 (Folder),则抛出 IllegalStateException 异常。 setFrom abstract II 语法:public abstract void setFrom(Address address) throws MessagingException 描述:该方法设置消息的 From 属性值。 参数:address:发送者地址。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常;若该消息来自一个只读的目录 (Folder),则抛出 IllegalStateException 异常。 reply abstract 语法:public abstract Message reply(boolean replyToAll) throws MessagingException 描述:reply 方法创建一个新的、用于回复当前消息的新消息。新消息的头和属性值都已 被配置好,但其内容为空,留给客户程序填充;新消息的标题为原消息标题加上 62 第 8 章 Java Mail “Re:”前缀(除非原消息标题即以“Re:”开头)。若参数 replyToAll 设置为 true, 则新消息发送给原消息的所有接收者;否则新消息仅发送给原消息的发送者。新 消息与原消息使用同一会话。 参数:replyToAll:指示新消息是否应该被发送给原消息的所有接收者。 返回:新创建的回复消息。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 saveChanges abstract 语法:public abstract void saveChanges() throws MessagingException 描述:如果该消息来自目录(Folder),saveChanges 方法将对消息所做的修改保存到目 录所在的消息存储器(Store)中(在某些实现中,任何修改都将被立即保存), 并修改相应头字段以与修改后的内容保持一致。如果消息头或内容一部分已被改 动,则必须调用 saveChanges 方法以确保该改动被永久保存下来;如果不调用该 方法,则这样的修改是否会被保存依赖于具体的 Store 和 Folder 实现。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常;若该消息来自一个只读的目录 (Folder),则抛出 IllegalStateException 异常。 getAllRecipients 语法:public Address[] getAllRecipients() throws MessagingException 描述:getAllRecipients 方法获取该消息的所有接收者地址,缺省实现将接收者分为 TO、 CC、BCC 三类,然后使用 getRecipients 方法检索各类接收者。如果消息中没有 接收者部分(part),则返回 null;若消息中含有接收者部分,但没有指定任何地 址,则返回空数组。 返回:Address 对象数组。如果消息中没有接收者部分(part),则返回 null;若消息中 含有接收者部分,但没有指定任何地址,则返回空数组。 getFolder 语法:public Folder getFolder() 描述:getFolder 方法检索获取消息的目录;若该消息是一个新创建的消息或嵌套消息, 则返回 null。 返回:包含该消息的目录对象,目录处于关闭状态。 63 J2EE 完全参考手册 (tsl0151@vip.sina.com) getMessageNumber 语法:public int getMessageNumber() 描述:getMessageNumber 方法获取该消息在目录中的序号,该序号可能因为目录中的其 他消息被查处而改变。合法序号从 1 开始,不属于任何目录的消息把 0 作为它们 的序号。 返回:消息在目录中的序号。 getReplyTo 语法:public Address[] getReplyTo() throws MessagingException 描述:getReplyTo 方法获取该消息的回复应该发送到的地址,它通常是原消息发送者的 地址,但某些消息可能会将回复发送到不同的地址。该方法的缺省实现调用 getFrom 方法。 返回:该消息的回复应该发送到的地址。如果消息中没有相应的部分(part),则返回 null; 若消息中含有相应部分,但没有指定任何地址,则返回空数组。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 isExpunged 语法:public boolean isExpunged() 描述:isExpunged 方法检测该消息是否已被擦除,在已擦除的对象上调用除了 getMessageNumber 外的所有方法都是合法的。显式调用 expunge 方法所删除的消 息都被立即从目录中删除;用其他方法擦除的消息被标记为“expunged”,在其 上调用 isExpunged 方法将返回 true,但它们并没有从目录中删除。 返回:若该对象已被擦除,则返回 true,否则返回 false。 isSet 语法:public boolean isSet(Flags.Flag flag) throws MessagingException 描述:isSet 方法检查该消息中 flag 参数所指定的某个标志位是否被设置。该方法的缺省 实现使用 getFlags 方法。 参数:flag:指定标志位。 返回:true 表示该标志位已被设置,false 表示该标志位未被设置。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 64 第 8 章 Java Mail match 语法:public boolean match(SearchTerm term) throws MessagingException 描述:match 方法将指定的搜索准则应用到该消息上。 参数:match:搜索准则。 返回:若该消息匹配搜索准则,则返回 true,否则返回 false。 异常:若方法调用出现错误,则抛出 MessagingException 异常。 setRecipient 语法:public void setRecipient(Message.RecipientType type, Address address) throws MessagingException 描述:setRecipients 设置接收者地址,指定类型的所有接收者地址全部被 address 参数取 代。该方法的缺省实现使用 setRecipient 方法。 参数:type:接收类型;address:接收者地址。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常。 setReplyTo 语法:public void setReplyTo(Address[] addresses) throws MessagingException 描述:setReplyTo 方法设置回复消息应该发送到的地址。缺省实现不支持设置 ReplyTo 属性,调用该方法将抛出 MethodNotSupportedException。 参数:addresses:回复消息应该发送到的地址数组。 异常:若方法调用出现错误,则抛出 MessagingException 异常;若底层实现不支持修改 已存在值,则抛出 IllegalWriteException 异常;若该消息来自一个只读的目录 (Folder),则抛出 IllegalStateException 异常;若底层实现不支持设置该属性,则 抛出 MethodNotSupportedException 异常。 Session JavaMail 1.0 javax.mail final Session 类代表一个基本邮件会话,它是 Java Mail API 最高层入口类,所有其它类都必 须经由 Session 对象才得以生效。Session 对象管理配置选项和用于与邮件系统交互的用户认 证信息,它使用 Java.util.Properties 对象获取信息,如邮件服务器、用户名、密码及整个应用 程序中共享的其它信息。 JavaMail API 支持并发的多个会话,每个会话都可以访问多个 Store 和 Transport 对象。 通常来说,同一台 PC 上的第一个基于 JavaMail 的应用程序将创建一个缺省的会话,并初始 65 J2EE 完全参考手册 (tsl0151@vip.sina.com) 化该用户访问其邮件服务器中 Inbox 目录(Folder)所必需的身份认证信息;该用户之后运行 的应用程序在需要发送或接收邮件时可以使用这个缺省会话。共享这个缺省会话代表所有的 应用程序都使用同样的认证信息、属性和该对象状态。 Session 类的构造器是私有的,它不能被继承,也不能使用 new 语句来创建实例,但它提 供了两个静态方法来获取 Session 实例,如下面代码所示。 // 方法 1:用 getInstance() 创建一个独立的 session Properties props = new Properties(); Session session = Session.getInstance(props); // 方法 2:用 getDefaultInstance() 获取共享的缺省会话对象,其中 null 表示 Authenticator 对象 Properties props = new Properties(); Session defaultSession = Session.getDefaultInstance(props, null); 对于大多数情况,共享的 Session 对象已经够用了,即使要处理多个用户目录的邮件也 一样。开发者可以在通信过程中稍后的步骤加入用户名和密码组合,让一切保持独立。 上面代码中用于初始化 Session 的 Properties 对象包含各种配置信息的缺省值,开发者可 以使用 JavaMail API 来改变这些值,以使其适用于特定场合。表 2-4 列出了 JavaMail API 可 以使用的标准环境属性。此外,邮件系统的某些实现可以使用额外的属性或者可以由用户定 制属性。应用程序可以使用 System.getProperties()方法获取系统属性对象。 表 2-4 JavaMail 环境属性列表 属性 描述 缺省值 mail.store.protocol 表示缺省邮件访问协议。Session.getStore()方法获取一个 实现了该协议的 Store 对象;客户机可以使用 Session.getStore(String protocol)方法覆盖该属性值并显 式指定邮件访问协议。 配置文件中第一个邮件访 问协议。 mail.transport.protocol 表示缺省传输协议。Session. getTransport()方法获取一个 实现了该协议的 Transport 对象;客户机可以使用 Session.getTransport (String protocol)方法覆盖该属性值 并显式指定传输协议。 配置文件中第一个传输协 议。 mail.host 表示缺省邮件服务器。如果特定协议的 host 属性值未指 定,则 Store 和 Transport 对象的 connect 方法使用该属 性值定位目标主机。 本地机 mail.user 表示连接到邮件服务器时所提供的用户名,如果特定协 议的 username 属性值未指定,则 Store 和 Transport 对象 的 connect 方法使用该属性值作为用户名。 user.name mail..host 表示特定协议的缺省邮件服务器,该值将覆盖 mail.host 属性值。 mail.host mail..user 表示特定协议的缺省用户名,该值将覆盖 mail.user 属性 值。 mail.user mail.from 表示当前用户的回复地址,username@host 66 第 8 章 Java Mail InternetAddress.getLocalAddress()方法用它识别当前用 户的电子邮件地址。 mail.debug 设置初始调试模式,将该值设为true表示打开调试模式, 设为 false 则关闭。客户机也可以使用 Session.setDebug 方法设置调试模式。 false 在表 2-4 中提到了配置文件,所谓的配置文件就是配置协议供应商的文件,协议供应商 提供 Store、Transport 和相关类的实现,Session 对象可以访问这些供应商。配置文件有下列 两种: • javamail.providers 和 javamail.default.providers • javamail.address.map 和 javamail.default.address.map javamail.providers 和 javamail.default.providers 文件指明系统中可用的协议供应商,使应 用程序可以访问可用的 Store 和 Transport 实现。文件中每一个协议实现单成一行,定义了四 个属性(attribute)来描述一个协议实现,每一个属性使用“=”隔开名——值对, 使用“;” 作为属性的结束标志。这四个属性分别是 type(类型)、class(实现类)、vendor(厂商,可 选)和 version(版本,可选)。下面列出一个 javamail.default.providers 文件作为示例,它位 于 mail.jar 文件的 META-INF 目录下。 // META-INF/javamail.default.providers protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=Sun Microsystems, Inc; protocol=smtp; type=transport; class=com.sun.mail.smtp.SMTPTransport; vendor=Sun Microsystems, Inc; protocol=pop3; type=store; class=com.sun.mail.pop3.POP3Store; vendor=Sun Microsystems, Inc; 上述文件的第一行表示系统支持 IMAP 协议,既 mail.store.protocol 属性(property)值 为 IMAP,Store 的 IMAP 协议实现类为 com.sun.mail.imap.IMAPStore,协议供应商为 Sun 公司。 其余两行语意与此相似。 javamail.address.map 和 javamail.default.address.map 文件将传输地址类型映射到传输协 议。javax.mail.Address.getType 方法返回传输地址类型。这些文件是由一系列名——值对组成 的,每一个名称对应于当前机器上已经安装的地址类型,比如说,javax.mail.internet.Internet 类的 getType 方法返回"rfc822",它对应于 SMTP 协议。 下面是一个典型的 javamail.address.map 文件的内容。 //javamail.address.map rfc822=smtp news=nntp 用于初始化 Session 对象的另一个参数 Authenticator 对象控制着会话的安全性。消息系 统将它作为一种回调机制,若登录到一个消息系统时需要密码,则消息系统通过 Authenticator 对象与用户交互。它并不直接控制缺省会话。 类声明: public final class Session extends Object { // 静态类方法 static Session getDefaultInstance(Properties props); 67 J2EE 完全参考手册 (tsl0151@vip.sina.com) static Session getDefaultInstance(Properties props, Authenticator authenticator); // 公共实例方法 boolean getDebug(); PrintStream getDebugOut(); Folder getFolder(URLName url) throws MessagingException; static Session getInstance(Properties props); static Session getInstance(Properties props, Authenticator authenticator); PasswordAuthentication getPasswordAuthentication(URLName url); Properties getProperties(); String getProperty(String name); Provider getProvider(String protocol) throws NoSuchProviderException; Provider[] getProviders(); Store getStore() throws NoSuchProviderException; Store getStore(Provider provider) throws NoSuchProviderException; Store getStore(String protocol) throws NoSuchProviderException; Store getStore(URLName url) throws NoSuchProviderException; Transport getTransport() throws NoSuchProviderException; Transport getTransport(Address address) throws NoSuchProviderException; Transport getTransport(Provider provider) throws NoSuchProviderException; Transport getTransport(String protocol) throws NoSuchProviderException; Transport getTransport(URLName url) throws NoSuchProviderException; PasswordAuthentication requestPasswordAuthentication(InetAddress addr, int port, String protocol, String prompt, String defaultUserName); void setDebug(boolean debug); void setDebugOut(PrintStream out); void setPasswordAuthentication(URLName url, PasswordAuthentication pw); void setProvider(Provider provider) throws NoSuchProviderException; } 层次: Object->Session 传递给:javax.mail.internet.InternetAddress.getLocalAddress(), javax.mail.Message.Message(), javax.mail.internet.MimeMessage.MimeMessage(), javax.mail.Service.Service(), javax.mail.Store.Store(), javax.mail.Transport.Transport () 返回自:Session.getDefaultInstance(), Session.getInstance() getDebug 语法:boolean getDebug() 描述:getDebug 方法获取调试设置。 68 第 8 章 Java Mail 返回:若返回 true,表示已打开调试模式,为 false 表示调试模式已关闭。 getDebugOut JavaMail 1.3 语法:PrintStream getDebugOut() 描述:getDebugOut 方法获取调试输出流,默认情况下调试输出流为 System.out。 返回:调试输出流。 getDefaultInstance JavaMail 1.2 I 语法:static Session getDefaultInstance(Properties props) 描述:该方法为静态类方法,它用于获取缺省的会话对象;如果当前没有缺省的会话对 象( getDefaultInstance 第一次被调用),则创建一个新的会话对象并将它作为缺省 会话。必须注意的是用该方法创建的缺省会话没有指定 Authenticator 对象,它对 同一虚拟机中运行的所有代码都是可用的,而该会话内很可能包含敏感的安全信 息,如用户名和密码。所以使用这种方法创建缺省会话并不安全。 参数:props:包含各种配置信息的 Properties 对象。 返回:缺省会话。 getDefaultInstance II 语法:static Session getDefaultInstance(Properties props, Authenticator authenticator) 描述:该方法为静态类方法,它用于获取缺省的会话对象;如果当前没有缺省的会话对 象( getDefaultInstance 第一次被调用),则创建一个新的会话对象并将它作为缺省 会话。因为它对同一虚拟机中运行的所有代码都是可用的,而该会话内很可能包 含敏感的安全信息,所以必须限制对缺省会话的访问。参数 Authenticator 对象(由 调用者创建)即用于非直接的检查访问权限。使用该方法获取缺省会话时所传入 的 Authenticator 对象将与缺省会话被创建时所传入的 Authenticator 对象比较,若 两者相同或来自同一个 ClassLoader,则请求被允许。否则,它将被拒绝。 参数:props:包含各种配置信息的 Properties 对象,该参数只有在 getDefaultInstance 第 一次被调用时才有效,之后的调用中该参数将被系统忽略;authenticator:用于非 直接的检查访问权限;消息系统将之作为回调对象,当需要用户名和密码时消息 系统使用该对象与应用程序交互。 返回:缺省会话。 getFolder 语法:Folder getFolder(URLName url) throws MessagingException 69 J2EE 完全参考手册 (tsl0151@vip.sina.com) 描述:getFolder 方法获取由参数 url 指定的 Folder 对象,若所请求的 Folder 对象不存在, 则返回空值。url 字符串的一部分指定了 Store 对象所使用的协议,Store 对象使用 特定于该协议的方式解释字符串的另一部分、定位并实例化 Folder 对象。 参数:url:表示待返回 Folder 实例的 URLName 对象。 返回:处于关闭状态的 Folder 实例。 异常:若系统未安装参数 url 指定的供应商,则抛出 NoSuchProviderException 异常;若 无法定位或创建 Folder 对象,则抛出 MessagingException 异常。 getInstance JavaMail 1.2 I 语法:static Session getInstance(Properties props) 描述:该方法为静态类方法,它用于创建一个独立的会话对象,同时指定属性值。 参数:props:包含各种配置信息的 Properties 对象。 返回:新创建的会话。 getInstance II 语法:static Session getInstance(Properties props, Authenticator authenticator) 描述:该方法为静态类方法,它用于创建一个独立的会话对象,同时指定属性值和一个 Authenticator 对象。 参数:props:包含各种配置信息的 Properties 对象;authenticator:消息系统将之作为回 调对象,当需要用户名和密码时消息系统使用该对象与应用程序交互。 返回:新创建的会话。 getPasswordAuthentication 语法:PasswordAuthentication getPasswordAuthentication(URLName url) 描述:getPasswordAuthentication 方法获取与参数 url 对应的 PasswordAuthentication 对象, 它通常由 Store 或 Transport 实现类使用。 参数:url:URLName 对象,定位 Store 或 Transport 对象。 返回:PasswordAuthentication 对象。 getProperties 语法:Properties getProperties() 描述:getProperties 方法获取与该会话关联的环境属性。 返回:Properties 对象,包含各种属性配置信息,如表 2-4 所示。 70 第 8 章 Java Mail getProperty 语法:String getProperty(String name) 描述:getProperty 方法获取指定属性的值;若该属性不存在,则返回 null。 参数:name:属性名 返回:属性值字符串。 getProvider 语法:Provider getProvider(String protocol) throws NoSuchProviderException 描述:getProvider 方法获取指定协议的缺省供应商。首先检查 mail..class 属性 是否存在:若存在,则返回与该实现观念的供应商;若不存在,则返回配置文件 中与该协议对应的第一位出现的供应商。如果找不到该协议的实现,则抛出 NoSuchProviderException 异常。 参数:protocol:指定的协议,如 smtp、imap 等。 返回:指定协议的缺省供应商。 异常:若找不到该协议的实现,则抛出 NoSuchProviderException 异常。 getProviders 语法:Provider[] getProviders() 描述:getProviders 方法获取应用程序可用的 ClassLoader 所能装载的、已安装的协议实 现列表,javamail.[default.]providers 文件列出了当前已安装的所有协议实现。 返回:供应商数组。 getStore I 语法:Store getStore() throws NoSuchProviderException 描述:该方法获取一个实现了 mail.store.protocol 属性所指定协议的 Store 对象。 返回:Store 实例。 异常:若无法找到该协议的供应商,则抛出 NoSuchProviderException 异常。 getStore II 语法:Store getStore(Provider provider) throws NoSuchProviderException 描述:该方法由指定供应商实例化一个 Store 对象,并返回该对象。 参数:provider:指定供应商对象。 返回:Store 实例。 71 J2EE 完全参考手册 (tsl0151@vip.sina.com) 异常:若无法实例化该供应商,则抛出 NoSuchProviderException 异常。 getStore III 语法:Store getStore(String protocol) throws NoSuchProviderException 描述:该方法获取一个实现了指定协议的 Store 对象。 参数:protocol:指定协议。 返回:Store 实例。 异常:若无法找到该协议的供应商,则抛出 NoSuchProviderException 异常。 getStore IV 语法:Store getStore(URLName url) throws NoSuchProviderException 描述:该方法获取一个由指定 URLName 定位的 Store 对象。URLName 字符串的一部分 指定了 Store 对象所使用的协议。 参数:url:表示待获取 Store 对象的统一资源定位字符串。 返回:Store 实例。 异常:若无法获取所请求的 Store 对象,则抛出 NoSuchProviderException 异常。 getTransport I 语法:Transport getTransport() throws NoSuchProviderException 描述:该方法获取一个实现了 mail.transport.protocol 属性所指定协议的 Transport 对象。 返回:Transport 实例。 异常:若无法找到该协议的供应商,则抛出 NoSuchProviderException 异常。 getTransport II 语法:Transport getTransport(Address address) throws NoSuchProviderException 描述:该方法获取一个能将邮件消息发送到指定地址类型的 Transport 对象。 参数:address:指定地址类型。 返回:Transport 实例。 异常:若无法找到该地址类型的供应商,则抛出 NoSuchProviderException 异常。 getTransport III 语法:Transport getTransport(Provider provider) throws NoSuchProviderException 描述:该方法由指定供应商实例化一个 Transport 对象,并返回该对象。 72 第 8 章 Java Mail 参数:provider:指定供应商对象。 返回:Transport 实例。 异常:若无法实例化该供应商,则抛出 NoSuchProviderException 异常。 getTransport IV 语法:Transport getTransport(String protocol) throws NoSuchProviderException 描述:该方法获取一个实现了指定协议的 Transport 对象。 参数:protocol:指定协议。 返回:Transport 实例。 异常:若无法找到该协议的供应商,则抛出 NoSuchProviderException 异常。 getTransport V 语法:Transport getTransport(URLName url) throws NoSuchProviderException 描述:该方法获取一个由指定 URLName 定位的 Transport 对象。URLName 字符串的一 部分指定了 Transport 对象所使用的协议。 参数:url:表示待获取 Transport 对象的统一资源定位字符串。 返回:Transport 实例。 异常:若无法获取所请求的 Transport 对象,则抛出 NoSuchProviderException 异常。 requestPasswordAuthentication 语法:PasswordAuthentication requestPasswordAuthentication(InetAddress addr, int port, String protocol, String prompt, String defaultUserName); 描述:requestPasswordAuthentication 方法回调应用程序以获取必需的用户名和密码。程 序将创建一个对话框以供用户输入用户名和密码,并以它们为参数构造一个 PasswordAuthentication 对象返回给调用程序。 参数:addr:服务器地址,可能为空;port:将访问的服务器端口号;protocol:邮件协 议;prompt:显示给用户的(部分)提示信息,可能为空;defaultUserName:缺 省用户名,可能为空。 返回:PasswordAuthentication 对象,包含程序收集的认证信息;可能为空。 setDebug 语法:void setDebug(boolean debug) 描述:setDebug 方法获取该会话的调试模式。mail.debug 属性值用于初始化所有会话的 调试模式,setDebug 方法可以改变该会话的调试模式,但不能改变 mail.debug 属 73 J2EE 完全参考手册 (tsl0151@vip.sina.com) 性值。 参数:debug:待设置调试模式。为 true 表示打开调试模式,为 false 表示关闭。 setDebugOut JavaMail 1.3 语法:void setDebugOut(PrintStream out) 描述:setDebugOut 方法设置该会话调试输出流,若 out 参数为空,则使用 System.out 输出调试信息。注意:在任何会话创建之前出现的调试信息,总是被输出至 System.out。 参数:out:用于输出调试信息的 PrintStream 对象。 setPasswordAuthentication 语法:void setPasswordAuthentication(URLName url, PasswordAuthentication pw) 描述:setPasswordAuthentication 方法设置与参数 url(定位一个 Store 或 Transport 对象) 对应的 PasswordAuthentication 对象。它通常只由 Store 或 Transport 实现类使用, 以允许同一会话的多个用户共享认证信息。 参数:url:URLName 对象,定位 Store 或 Transport 对象。pw:PasswordAuthentication 对象,包含认证信息。 setProvider 语法:void setProvider(Provider provider) throws NoSuchProviderException 描述:setProvider 方法将 provider 参数指定为一个协议(即 provider.tgetProtocol 方法返 回的协议)的缺省供应商,覆盖之前的值。 参数:provider:指定供应商,它将被设置为它所支持协议的缺省供应商。 异常:若参数 provider 非法,则抛出 NoSuchProviderException 异常。 Store JavaMail 1.0 javax.mail abstract Store 是一个抽象类,它模拟了消息存储器(或称为数据库)及其内部目录(Folder)访 问协议,以储存和读取消息,其子类提供具体实现。 Store 定义的存储器包括一个分层的目录体系,消息存储在目录内。客户程序可以通过获 取一个实现了数据库访问协议的 Store 对象来访问消息存储器,绝大多数的存储器要求用户 在访问前提供认证信息,connect 方法执行了该认证过程。大多数情况下,主机名、用户名和 密码已足够认证一个用户,JavaMail API 提供的 connect 方法将这些信息作为输入参数,Store 74 第 8 章 Java Mail 类也提供了一个缺省的 connect 方法;在任何一种情况下,客户机程序都可以从会话对象属 性中获取认证信息;或者通过访问会话的 Authenticator 对象来与用户交互,要求用户输入认 证信息。 Store 类中缺省实现的 connect 方法在收集到必要的信息后,调用了 protocolConnect 方法, 邮件消息系统必须提供该方法的一份实现;当然,它也可以选择直接覆盖该方法。 缺省的,Store 将查询下述属性来获取用户名和主机名: • mail.user(若该属性未设置,则使用系统属性 user.name) • mail.host 这些全局缺省值可能被下列特定协议的属性值覆盖: • mail..user • mail..host 注意:密码不可能通过属性获取。 Store 类为客户提供了一个缺省的名字空间,Store 的实现可以提供其他的名字空间。 getDefaultFolder 方法返回缺省名字空间的根目录(root Folder)。 Store 类可以向其上相关的监听器发送表 2-5 中所列三类事件: 表 2-5 Store 发送的三类事件 事件 描述 ConnectionEvent 当 Store 上的连接被创建、终止或中断时产生该类事件。 StoreEvent 从 Store 向终端用户传输警告或通知消息时产生该类事件。getMessageType 方 法将返回事件类型:ALERT(警告)或 NOTICE(通知),客户机程序可以通 过某种方式显示警告事件,以使用户注意到该消息。 FolderEvent Store 内任何目录的变化时产生该类事件。这些变化可能包括创建一个新目录、 删除或重命名一个已存在的目录。 用 Store 获取消息与用 Transport 发送消息开始很相似,首先通过 Session 获取针对具体 协议的 Store 实例,然后提供用户名和密码连接到一个邮件服务器,如下面代码所示: // // 使用 POP3 协议接受消息,也可以使用 IMAP; Store store = session.getStore("pop3"); store.connect(host, username, password); 完成上述步骤后,客户机程序将通过 Store 对象访问其内的目录以获取消息。 类声明: public abstract class Store extends Service { // 构造函数 protected Store(Session session, URLName urlname); // 抽象方法 public abstract Folder getDefaultFolder() throws MessagingException; public abstract Folder getFolder(String name) throws MessagingException; 75 J2EE 完全参考手册 (tsl0151@vip.sina.com) public abstract Folder getFolder(URLName url) throws MessagingException; // 公共实例方法 public void addFolderListener(FolderListener l); public void addStoreListener(StoreListener l); public Folder[] getPersonalNamespaces() throws MessagingException; Folder[] getSharedNamespaces() throws MessagingException; Folder[] getUserNamespaces(String user) throws MessagingException; void removeFolderListener(FolderListener l); void removeStoreListener(StoreListener l); // 保护方法 protected void notifyFolderListeners(int type, Folder folder); protected void notifyFolderRenamedListeners(Folder oldF, Folder newF); protected void notifyStoreListeners(int type, String message); } 层次: Object -> Service -> Store 传递给:Folder.Folder(), StoreEvent.StoreEvent(), StoreClosedException.StoreClosedException() 返回自:Session.getStore(), Folder.getStore(), StoreClosedException.getStore() getDefaultFolder abstract 语法:public abstract Folder getDefaultFolder() throws MessagingException 描述:getDefaultFolder 方法获取 Store 对象为客户提供的缺省名字空间的根目录。 返回:Folder 对象,表示缺省名字空间内的最顶层目录。 异常:若方法调用出现问题,则抛出 MessagingException;若 Store 对象当前未连接,则 抛出 IllegalStateException 异常。 getFolder abstract I 语法:public abstract Folder getFolder(String name) throws MessagingException 描述:该方法获取与指定名称对应的目录对象。Store 不会缓存目录对象,因此在使用相 同的 name 参数多次调用该方法将返回不同的的目录实例。注意:即使存储器内 并不存在该名称的目录,getFolder 也会返回一个目录对象,调用者可以通过返回 对象上的 exists 方法来测试该目录是否确实存在。 参数:name:目录名称。在某些存储器中,如果目录名称以分层分隔符开发,则它表示 一个绝对路径;否则它将被解释为该名字空间相对根目录的路径。 返回:与指定名称对应的处于关闭状态的 Folder 对象。 异常:若方法调用出现问题,则抛出 MessagingException;若 Store 对象当前未连接,则 抛出 IllegalStateException 异常。 76 第 8 章 Java Mail getFolder abstract II 语法:public abstract Folder getFolder(URLName url) throws MessagingException 描述:该方法获取对应于 URLName 参数的 Folder 对象,URLName 中指定的存储器影 指向当前的 Store 对象。SUN 提供的缺省实现通过 getFile 方法获取目录名称,然 后使用该名称创建 Folder 对象 参数:url:表示待获取目录的 URLName 对象。 返回:对应于 URLName 参数的 Folder 对象,该对象处于关闭状态。 异常:若方法调用出现问题,则抛出 MessagingException;若 Store 对象当前未连接,则 抛出 IllegalStateException 异常。 addFolderListener 语法:public void addFolderListener(FolderListener listener) 描述:addFolderListener 方法为存储器内目录注册一个目录监听器(FolderListener),目 录事件(FolderEvent)将传递给受影响的目录和 Store 容器。 参数:listener:待注册的目录监听器对象。 addStoreListener 语法:public void addStoreListener(StoreListener l) 描述:addStoreListener 方法为当前 Store 注册一个存储器事件(StoreEvent)监听器。 参数:listener:待注册的 StoreEvent 监听器。 getPersonalNamespaces JavaMail 1.2 语法:public Folder[] getPersonalNamespaces() throws MessagingException 描述:getPersonalNamespaces 方法获取代表当前用户个人名字空间的目录集合。一个个 人名字空间是一组在认证用户作用域范围内的名字。比如说,如果用户拥有一个 INBOX 邮件目录,则它必须出现在用户的个人名字空间中。通常来说,只有认 证用户才能访问他们个人名字空间内的邮件目录,并且一个存储器内每个用户应 该只有一个个人名字空间。 返回:代表当前用户个人名字空间的 Folder 对象数组。 异常:若方法调用出现问题,则抛出 MessagingException;若 Store 对象当前未连接,则 抛出 IllegalStateException 异常。 77 J2EE 完全参考手册 (tsl0151@vip.sina.com) getSharedNamespaces JavaMail 1.2 语法:Folder[] getSharedNamespaces() throws MessagingException 描述:getSharedNamespaces 方法获取代表共享名字空间的目录集合。共享名字空间是由 在用户间共享的、不出现在个人名字空间内的邮件目录组成的名字空间。 返回:代表共享名字空间的 Folder 对象数组。 异常:若方法调用出现问题,则抛出 MessagingException;若 Store 对象当前未连接,则 抛出 IllegalStateException 异常。 getUserNamespaces JavaMail 1.2 语法:Folder[] getUserNamespaces(String user) throws MessagingException 描述:getPersonalNamespaces 方法获取代表指定用户个人名字空间的目录集合。要访问 其他用户名字空间的邮件目录,当前认证用户必须被显式授予访问权限。比如说, 管理者通常被授予访问用户邮箱的安全权限。 参数:user:指定用户名,将访问其个人名字空间。 返回:代表指定用户个人名字空间的 Folder 对象数组。 异常:若方法调用出现问题,则抛出 MessagingException;若 Store 对象当前未连接,则 抛出 IllegalStateException 异常。 notifyFolderListeners 语法:protected void notifyFolderListeners(int type, Folder folder) 描述:notifyFolderListeners 方法通知所有目录监听器某个目录事件,Store 类的实现应该 使用该方法广播目录事件。 参数:type:目录事件类型;folder:受影响的目录。 notifyFolderRenamedListeners JavaMail 1.1 语法:protected void notifyFolderRenamedListeners(Folder oldF, Folder newF) 描述:notifyFolderRenamedListeners 方法通知所有的目录监听器某个目录被重命名, Store 类的实现应该使用该方法广播目录重命名事件。 返回:oldF:被重命名的旧目录;newF:重命名后的新目录。 异常:若方法调用出现问题,则抛出 MessagingException;若 Store 对象当前未连接,则 抛出 IllegalStateException 异常。 78 第 8 章 Java Mail notifyStoreListeners 语法:protected void notifyStoreListeners(int type, String message) 描述:notifyStoreListeners 方法通知所有的 StoreListener 个目录某个 StoreEvent 事件,Store 类的实现应该使用该方法广播这类事件。 参数:type:StoreEvent 事件类型;message:警告或通知信息。 removeFolderListener 语法:void removeFolderListener(FolderListener listener) 描述:removeFolderListener 方法删除一个目录监听器(FolderListener)。 参数:listener:待删除的目录监听器对象。 removeStoreListener 语法:void removeStoreListener(StoreListener listener) 描述:removeStoreListener 方法删除一个存储器事件(StoreEvent)监听器。 参数:listener:待删除的 StoreEvent 监听器。 Transport JavaMail 1.0 javax.mail abstract Transport 是一个抽象类,它模拟消息的传送,使用指定协议发送消息(通常是 SMTP), 其子类提供消息传送的具体实现。Transport 继承自 Service 类,而后者提供了很多通用方法, 如命名传输、连接服务器、监听传输事件等等。 Transport 的工作方式与 Session 有类似之处,仅调用静态 send 方法,就能使用发送方法 的缺省版本,如下所示: Transport.send(message); 另一种发送消息的方法是从会话中获取一个针对具体协议的 Transport 实例,传入用户名 和密码(如果不必要就不传),发送消息,然后关闭连接,如下面的代码所示: // 在 Send 方法中消息会自动保存其修改,不需调用 saveChanges 方法 message.saveChanges(); // 使用 SMTP 协议传输消息 Transport transport = session.getTransport("smtp"); // 连接邮件服务器,提供用户名和密码 transport.connect(host, username, password); // 发送消息给所有接收者 79 J2EE 完全参考手册 (tsl0151@vip.sina.com) transport.sendMessage(message, message.getAllRecipients()); // 关闭连接 transport.close(); 第二种发送消息的方法适合于发送多条消息的情况,使用该方法时,到邮件服务器的连 接在消息发送期间始终保持活跃状态,而 send 方法每次调用都将与服务器建立一个独立的连 接。 注意:要观察传送到邮件服务器上的邮件指令,可以用 session.setDebug(true)打开调试模式。 类声明: public abstract class Transport extends Service { // 构造函数 Transport(Session session, URLName urlname); // 静态方法 public static void send(Message msg) throws MessagingException; public static void send(Message msg, Address[] addresses) throws MessagingException; // 抽象方法 public abstract void sendMessage(Message msg, Address[] addresses) throws MessagingException; // 公共实例方法 public void addTransportListener(TransportListener l); public void removeTransportListener(TransportListener l); // 保护方法 protected void notifyTransportListeners(int type, Address[] validSent, Address[] validUnsent, Address[] invalid, Message msg); } 层次: Object ->Service -> Transport 传递给:javax.mail.event.TransportEvent.TransportEvent() 返回自:Session.getTransport() addTransportListener 语法:public void addTransportListener(TransportListener listener) 描述:addTransportListener 方法为传送事件注册一个监听器。 参数:listener:待加入监听器对象。 notifyTransportListeners 语法:protected void notifyTransportListeners(int type, Address[] validSent, Address[] validUnsent, 80 第 8 章 Java Mail Address[] invalid, Message msg) 描述:notifyTransportListeners 通知所有的传送监听器消息的发送情况。 参数:type:事件类型;validSent:成功发送到的合法接收者地址;validUnsent:未发送 成功的合法地址;invalid:不合法地址(即地址格式有问题或找不到收件人); msg:所发送消息。 removeTransportListener 语法:public void removeTransportListener(TransportListener listener) 描述:removeTransportListener 删除一个传送事件的监听器。 参数:listener:待删除的传送监听器。 send static I 语法:public static void send(Message msg) throws MessagingException 描述:该方法是一个静态类方法,它将一个消息发送给该消息指定的所有收件人(即 getAllRecipients 方法返回值),并为每个地址选择适当的 Transport 对象。在发送 消息前,该方法将调用 saveChanges 保存消息。如果在消息提交期间 Transport 检 测到某个接收地址非法,则方法将抛出 SendFailedException 异常,客户机可以通 过检查该异常获悉失败细节。消息能否成功发送到合法的地址,则取决于 Transport 的具体实现。必须注意消息成功发送并不意味着它能到达最终接收者, 在之后的消息传输过程中可能会出现其他错误,但这些错误应该通过其他的机制 报告给用户(比如说,返回无法传递的消息)。 参数:msg:待发送消息。 异常:若方法调用出现问题,则抛出 MessagingException;若消息无法发送给某些接收 者,则抛出 SendFailedException。 send static II 语法:public static void send(Message msg, Address[] addresses) throws MessagingException 描述:该方法将消息发送给 addresses 参数指定的接收者,它将忽略消息中指定的接收者。 在发送消息前,该方法将调用 saveChanges 保存消息。 参数:msg:待发送消息;addresses:指定的接收者列表。 异常:若方法调用出现问题,则抛出 MessagingException;若消息无法发送给某些接收 者,则抛出 SendFailedException。 81 J2EE 完全参考手册 (tsl0151@vip.sina.com) sendMessage abstract 语法:public abstract void sendMessage(Message msg, Address[] addresses) throws MessagingException 描述:sendMessage 对象将消息发送给 addresses 参数指定的接收者。消息发送后,一个 用于报告消息传递情况的 TransportEvent 事件将被发送给该 Transport 对象上注册 的所有监听器。同样,如果在消息提交期间 Transport 检测到某个接收地址非法, 则方法将抛出 SendFailedException 异常;消息能否成功发送到合法的地址,则取 决于 Transport 的具体实现。与 send 方法不同,sendMessage 不会调用 saveChanges 方法,调用者必须自己保存修改过的消息。 参数:msg:待发送消息;addresses:指定的接收者列表。 异常:若方法调用出现问题,则抛出 MessagingException;若消息无法发送给某些接收 者,则抛出 SendFailedException。 82
还剩81页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 16 金币 [ 分享pdf获得金币 ] 3 人已下载

下载pdf

pdf贡献者

danny_ku

贡献于2011-10-26

下载需要 16 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf