您的位置:首页 > 编程语言 > Java开发

JavaMail

2015-08-03 02:47 357 查看


一、MAIL_BASE


1. 为什么学习邮件开发

许多办公自动化项目(OA)中都需要附带发送邮件的功能。

在许多网站项目中也都需要附带发送邮件的功能,即要求软件开发人员在WEB应用中编写相应的邮件处理程序。


2. 应用场景

给新注册的用户自动发送一封包含其注册信息的欢迎E-Mail

给过生日的注册会员自动发送一封表示祝贺的E-Mail

将网站的最新活动信息通过E-Mail发送给所有的注册会员


3. 邮件服务器

电子邮件服务器主要提供以下功能:

接收用户投递的邮件;

将用户投递进来的邮件转发给目标邮件服务器;

接收其他邮件服务器转发来的邮件并把邮件存储到其管理的用户邮箱中;

为前来读取邮件的用户提供读取服务。

邮件服务器按通讯协议可以划分为两种类型:

SMTP服务器 (发送邮件)

POP3/IMAP服务器 (接收)

例如163邮件服务器:

接收邮件服务器地址:pop.163.com

发送邮件服务器地址:smtp.163.com


4. 电子邮箱

每个电子邮件服务器之上都可以开设多个电子邮箱,电子邮箱也称之为E-mail地址,它类似现实生活中的通讯地址,用户可通过这个地址接收别人发来的电子邮件和向别人发送电子邮件。电子邮箱的获得需要在邮件服务器上进行申请 ,确切地说,电子邮箱其实就是用户在邮件服务器上申请的一个帐户。邮件服务器把接收到的邮件保存到为某个帐户所分配的邮箱空间中,用户通过其申请的用户名和密码登陆到邮件服务器上查收该地址已收到的电子邮件。


5. 邮件客户端软件

邮件客户端软件负责与邮件服务器通讯,主要用于帮助用户将邮件发送给SMTP服务器和从POP3/IMAP邮件服务器读取用户的电子邮件。邮件客户端软件通常集邮件撰写、发送和接收功能于一体。如:outloook。


6. 电子邮件传输过程






7. 邮件传输协议


7.1 SMTP协议

全称为Simple Mail Transfer Protocol(简单邮件传输协议),它定义了邮件客户端软件与SMTP服务器之间、以及两台SMTP服务器之间的通讯规则。


7.2 POP3协议

全称为Post Office Protocol(邮局协议),它定义了邮件客户端软件与POP3服务器的通讯规则。


7.3 IMAP协议

全称为Internet Message Access Protocal(Internet消息访问协议),它是对POP3协议的一种扩展,定义了邮件客户端软件与IMAP服务器的通讯规则。


8. JAVA Mail

要自己写程序发送和接收邮件,可以直接采用Socket编程连接上远程的邮件服务器,然后按照邮件协议与邮件服务器进行交互,涉及较多细节。另外,要想自己编程创建出复杂的MIME格式的邮件,是一件非常困难和麻烦的事情。

JavaMail 是Sun公司为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,如SMTP、POP3、IMAP。

开发人员使用JavaMail API编写邮件处理软件时,无须考虑邮件协议的底层实施细节,只要调用JavaMail开发包中相应的API类就可以了。

JavaMail 也提供了能够创建出各种复杂MIME格式的邮件内容的相关API。


9. JavaMail 的体系结构与API分类


9.1 体系结构






9.2 JavaMail的核心类介绍

(1) Message:javax.mail.Message是创建和解析邮件的核心类,他的实例代表一封电子邮件。客户端程序发送邮件时,首先使用创建邮件JavaMail API创建出封装了邮件数据的Message对象,然后把这个对象传送给发送API发送。客户端接收邮件时,邮件接收API把收到的邮件数据封装在Message类的实例对象中,客户端程序再使用邮件分析API从这个对象中介析出接收到的邮件数据。

(2) Transport:javax.mail.Transport类是发送邮件的核心API,他的实例对象代表实现了某个邮件发送协议的邮件发送对象,例如SMTP,客户端程序创建好Message对象后,只需要使用邮件发送API得到Transport对象,然后把Message对象传递给Transport对象,并调用它的发送方法,就可以把邮件发送给指定了SMTP服务器。

(3) Session:javax.mail.Session类用于定义整个应用程序所需的环境信息,以及收集客户端与邮件服务器建立网络联接的会话信息,如邮件服务器的主机名,端口号,采用的邮件发送和接收协议等。Session对象根据信息构建用于邮件收发的Transport和Store对象,以及为客户端创建Message对象是提供信息支持。

(4) InternetAddress:javax.mail.internet.InternetAddress。它继承自抽象类javax.mail.Address。InternetAddress类。用于表示邮件发送地址的类,其构造方法需要传递一个字符串类型的参数,如果是单个邮件地址,只需将邮件地址作为字符串参数传递即可,如果是群发邮件,则将所有的邮件地址拼接成一个字符串,中间有逗号“,”分隔即可,然后使用 InternetAddress.parse(以逗号分隔的多个邮件地址字符串)方法可以将群邮件地址解析为邮件地址数组。

注意:java的RFC822规范中规定多个邮件分隔符是逗号",",outlook的分号";"不是规范的多邮件地址分隔符。

(5) MimeMessage:javax.mail.internet.MimeMessage。它继承自抽象类javax.mail.Message,表示一封MIME邮件。MimeMessage有一个内部类Recipient类,即javax.mail.internet.MimeMessage.Recipient,表示邮件消息的接收者。这个类有一个属性to表示接收者,即接收邮件的邮箱地址。

MimeMessage内部类Recipient类还有一个Message.RecipientType内部类:

表示收件人的类型,它是Message中的一个静态类。该类中有如下三个常量:

a.TO:代表有健的主要接收者。

b.CC:代表有健的抄送接收者。

c.BCC:代表邮件的暗送接收者。

(6) Store:javax.mail.Store类是接收邮件的核心,他的实例对象代表实现了某个邮件接收协议的邮件接收对象,例如POP3。客户端程序接收到邮件时,只需要有事邮件接收API得到Store对象的接收方法,就可以从制定的POP3服务器获得邮件数据,并把这些数据封装到表示邮件的Message的对象中。Store类最常用的方法就是getFolder(),此方法得到指定名称的邮件服务器文件夹中的邮件。

(7) Folder:javax.mail.Folder,它是一个邮件文件夹类。Folder类有两个常见的属性,READ_ONLY表示只读,READ_WRITE表示其内容可读可写。


10. MIME协议

MIME,英文全称为“Multipurpose Internet Mail Extensions”,即多用途互联网邮件扩展,是目前互联网电子邮件普遍遵循的邮件技术规范,在MIME出现之前,互联网电子邮件主要遵循由RFC 822所制定的标准,电子邮件一般只用来传递基本的ASCII码文本信息,MIME在 RFC 822的基础上对电子邮件规范做了大量的扩展,引入了新的格式规范和编码方式,在MIME的支持下,图像、声音、动画等二进制文件都可方便的通过电子邮件来进行传递,极大地丰富了电子邮件的功能。目前互联网上使用的基本都是遵循MIME规范的电子邮件。


11. multipart类型

multipart/mixed类型

如果一封邮件中含有附件,那nt-邮件的ConteType域中必须定义multipart/mixed类型,邮件通过multipart/mixed类型中定义的boundary标识将附件内容同邮件其它内容分成不同的段。基本格式如下:

Content-Type: multipart/mixed;

boundary="{分段标识}"

multipart/related类型

MIME邮件中除了可以携带各种附件外,还可以将其它内容以内嵌资源的方式存储在邮件中。比如我们在发送html格式的邮件内容时,可能使用图像作为html的背景,html文本会被存储在alternative段中,而作为背景的图像则会存储在multipart/related类型定义的段中。基本格式如下:

Content-Type: multipart/related;

type="multipart/alternative";

boundary="{分段标识}"

multipart/alternative类型

MIME邮件可以传送超文本内容,但出于兼容性的考虑,一般在发送超文本格式内容的同时会同时发送一个纯文本内容的副本,如果邮件中同时存在纯文本和超文本内容,则邮件需要在Content-Type域中定义multipart/alternative类型,邮件通过其boundary中的分段标识将纯文本、超文本和邮件的其它内容分成不同的段。基本格式如下:

Content-Type: multipart/alternative;

boundary="{分段标识}"


12. MIME中的组合关系






13. 邮件结构





相关API说明:

MimeMessage类表示整封邮件。

MimeBodyPart类表示邮件的一个MIME消息。

MimeMultipart类表示一个由多个MIME消息组合成的组合MIME消息。


14. JAF简介

在使用JavaMail API进行邮件发送接收时,除了JavaMail相关的类以外,还需要使用JAF相关的类,JAF(JavaBeans Activation Framework,JavaBeans激活框架)是一个专用的数据处理框架,用于封装数据,并为应用程序提供访问和操作数据的接口。JavaMail API可以利用JAF从某种数据源中读取数据和获知数据的MIMe类型,并用这些数据生成MIME消息中的消息体和消息类型。

JAF的主要作用在于让Java应用程序知道如何对一个数据源进行察看,编辑和打印等操作。大家知道,在MSWord程序中可以打开一片Word文档中嵌套的Visio图片,JAF就是要让Java程序能够完成类似的技术应用,让应用程序知道数据源支持哪些操作,每个操作分别调用哪个处理模块。对于通过JAF封装的数据,应用程序通过JAF提供的接口可以完成以下操作:

访问数据源中的数据;

获知数据源的数据类型;

获知可对数据进行的各种操作;

用户对数据执行某种操作时,自动创建执行该操作的软件部件的实例对象。

例如,如果要使用JAF处理一个图片文件,那么应用程序通过JAF提供的接口就可以得到队图片文件进行操作的输入输出流,图片文件的MIME类型,JAF为图片文件提供的操作方法(如查看,毕激活打印图片等等),应用程序调用这些操作时,JAF就会调用相应的处理模块对数据进行处理。


二、JAVA Mail发送邮件


1. 准备环境

(1) 将javaMail核心类mail.jar加入到classpath中。

(2) 将JAF框架核心类activation.jar加入到classpath中。

注意:上面是针对JavaSE的环境,如果是JavaEE环境则不需要,j2ee.jar中包含了上述两个依赖包,可以直接使用。


2. 发送纯文本邮件

(1) 设置连接会话属性:

?
(2) 创建邮件对象:

?
(3) 设置邮件相关信息:

?
注意:

a.收件人和发件人的邮箱地址如果是多个,字符串中用逗号“,”(如果报错可以试试分号“;”)分隔即可。

b.收到邮件后显示的发件人地址是设置的setFrom值,而不是真正的发送邮箱。

c. Message.RecipientType类表示收件人的类型,是MimeMessage内部类Recipient类的一个内部类,它是Message中的一个静态类。该类中有如下三个常量:

TO:代表有健的主要接收者。

CC:代表有健的抄送接收者。

BCC:代表邮件的暗送接收者。

(4) 发送邮件:

?
注意:在transport.connect中设置的用户名和密码是为了连接邮箱服务器,该用户名不一定是收到邮件的发件人,发件人以message.setFrom中设置的为准。


3. 发送HTML格式邮件

和发送纯文本邮件类似,不同之处在于设置邮件内容部分,如:

?


4. 发送带附件的邮件

发送带有附件的邮件的过程有些类似转发邮件,我们需要建立一个完整邮件的各个邮件体部分,在邮件内容文字后,增加一个具有DataHandler的附件而不是在转发邮件时那样复制第一个部分的DataHandler。发送带附件的邮件需要用到JAF框架的DataHandler。
如果我们将文件作为附件发送:

a. 建立FileDataSource类型的对象作为附件数据源;如果从URL读取数据作为附件发送,那么将要建立URLDataSource类型的对象作为附件数据源。

b. 将这个数据源(FileDataSource或是URLDataSource)对象作为DataHandler类构造方法的参数传入,从而建立一个DataHandler对象作为数据源的DataHandler。

c. 将这个DataHandler设置为邮件体部分的DataHandler。这样就完成了邮件体与附件之间的关联工作,下面的工作就是BodyPart的setFileName()方法设置附件名为原文件名。

d. 将两个邮件体放入到Multipart中,设置邮件内容为这个容器Multipart,发送邮件。
这里说明一下邮件的结构:

每个邮件是由多个部分组成,每个部分称为一个邮件体部分,是一个BodyPart类对象,对于MIME类型邮件来讲就是MimeBodyPart类对象。这些邮件体包含在成为Multipart的容器中对于MIME类型邮件来讲就是MimeMultiPart类对象。

和发送纯文本也发送HTML格式邮件类似,不同之处在于:
(1) 创建附件内容对象:

?
(2) 设置附件内容对象的数据源和DataHandler:

?
(3) 创建附件对象:

?
(4) 添加附件:

?


5. 回复邮件

回复邮件的方法很简单:使用Message类的reply()方法,通过配置回复邮件的收件人地址和主题(如果没有提供主题的话,系统将默认将“Re:”作为邮件的主体),这里不需要设置任何的邮件内容,只要复制发信人或者reply-to到新的收件人。而reply()方法中的boolean参数表示是否将邮件回复给发送者(参数值为false),或是回复给所有人(参数值为true)。

补充一下,reply-to地址需要在发信时使用setReplyTo()方法设置。

?


6. 转发邮件

转发邮件的过程不如前面的回复邮件那样简单,它将建立一个转发邮件,这并非一个方法就能做到。

在转发邮件时,我们建立一个文字邮件体部分和一个被转发的文字邮件体部分,然后将这两个邮件体放到一个Multipart中。说明一下,复制一个邮件内容到另一个邮件的方法是仅复制它的DataHandler(数据处理者)即可。这是由JAF定义的一个类,它提供了对邮件内容的操作命令的访问、管理了邮件内容操作,是不同的数据源和数据格式之间的一致性接口。

(1) 创建转发邮件:

?
(2) 设置转发邮件信息:

?
(3) 复制被转发邮件内容到转发邮件内容中

?


三、JAVA Mail接收邮件

JavaMail API中定义了一个javax.mail.Store类,它用于执行邮件接收任务,这个类的实例对象封装了某种邮件接收协议的底层实施细节,应用程序调用这个类中的方法就可以获得用户邮箱中的各个邮件夹的信息。JavaMail使用Folder对象表示邮件夹,通过Folder对象的方法应用程序进而又可以获得该邮件夹中的所有邮件信息,而每封邮件信息,JavaMail又分别使用了一个Message对象进行封装。

Store类:与Transport类一样,javax.mail.Store类也继承了java.mail.Service类。Store类用于连接邮件接收服务器,并访问邮件接收服务器上的邮箱夹。Store类是一个抽象类,Sun公司在mail.jar包的com/sun/mail/pop3目录中提供了POP3协议的实现子类POP3Store,POP3Store封装了POP3协议的底层实施细节。应用程序通常调用Session.getStore方法得到Store类的实例对象,这个方法根据Session对象中定义的mail.store.procotol属性构建相应的协议实现类,并返回该类的实例对象。


1. 接收邮件的具体过程

(1) 从Session对象中获得实现了某种邮件发送协议的Store对象。

?
(2) 以某个邮箱帐户的身份连接上 POP3 或 IMAP4 服务器。

?
(3) 调用 Store 的 getFolder 方法,获取代表该帐户的邮箱中的某个邮件夹的 Folder 对象。

?
注意:JavaMail在Folder类中定义了两个用于表示操作权限的常量:

a. Folder.READ_ONLY:表示只读权限。

b. Folder.READ_WRITE:表示可以修改并读取邮件夹中的邮件。

(4) 调用Folder对象中的getMessage或getMessages方法,获取邮件夹中的一封邮件或所有邮件,每封邮件以一个Message对象返回。

?
(5) 读取邮件内容:

a.用Message.writeTo(java.io.OutputStream os)方法将邮件内容读入输出流中。

b.也可以使用getContent();获取邮件内容,返回一个Object对象。


2. 读取邮件中的附件

读取邮件中的附件的过程要比发送它的过程复杂一点。因为带有附件的邮件是多部分组成的,我们必须处理每一个部分获得邮件的内容和附件。但是如何辨别邮件信息内容和附件呢?Sun在Part类(BodyPart类实现的接口类)中提供了getDisposition()方法让开发者获得邮件体部分的部署类型,当该部分是附件时,其返回之将是Part.ATTACHMENT。但附件也可以没有部署类型的方式存在或者部署类型为Part.INLINE,无论部署类型为Part.ATTACHMENT还是Part.INLINE,我们都能把该邮件体部分导出保存。

?
上述代码中使用了saveFile方法是自定义的方法,它根据附件的文件名建立一个文件,如果本地磁盘上存在名为附件的文件,那么将在文件名后增加数字表示区别。然后从邮件体中读取数据写入到本地文件中。


3. 标记邮件

标记邮件就是把邮件标记为已读,删除等操作,需要使用Flags类,它mail.jar包中的Flags类代表以组邮件标记的集合,邮件标记用于标示邮件的使用情况,例如邮件的删除标记、已读标记等。JavaMail中的邮件标记分为系统标记和用户标记,系统标记指Flags.Flag这个内部类中表示的邮件标记,用户标记指用户自定义的标记。

Flags.Flag类:是Flags的内部类,以定义了一些常量类分别表示各种不同的邮件标记,这些邮件标记都是系统标记。如下所示:
Flags.Flag.ANSWERED
邮件回复标记,标识邮件是否已回复。
Flags.Flag.DELETED
邮件删除标记,标识邮件是否需要删除。
Flags.Flag.DRAFT
草稿邮件标记,标识邮件是否为草稿。
Flags.Flag.FLAGGED
表示邮件是否为回收站中的邮件。
Flags.Flag.RECENT
新邮件标记,表示邮件是否为新邮件。
Flags.Flag.SEEN
邮件阅读标记,标识邮件是否已被阅读。
Flags.Flag.USER
底层系统是否支持用户自定义标记,应用程序只能检索这个属性,而不能设置这个属性。
标记邮件的操作如下:

(1) 设置邮件标记:

?
(2) 清除邮件标记

?

4. 搜索邮件

JavaMail在javax.mail.search包中定义了一个用于创建搜索条件的SearchTerm类,应用程序创建SearchTerm类的实例对象以后,就可以调用Folder.search(SearchTerm
st)方法搜索邮件夹中符合搜索条件的所有邮件。SearchTerm类是一个抽象类,JavaMail提供了22个实现子类以帮助应用程序创建不同的搜索条件。如下:

(1) 用于创建逻辑组合关系的类

AND条件(AndTerm类)

OR条件(OrTerm类)

NOT条件(NotTerm类)

Comparison条件(ComparisonTerm类)

(2) 用于创建具体搜索条件的类

DATE条件(SendDateTerm、ReceinedDateTerm类)

CONTENT条件(BodyTerm类)

HEADER条件(FormStringTerm,RecipientStringTerm,SubjectTerm类等)

具体用法如下:

a. 搜索邮件夹中所有从test1@163.com或test2@163.com法来的邮件。

?
b. 搜索所有今天收到的,并且是test1@163.com 这个地址发来的邮件。

?


5. 解析和显示邮件

解析和显示一封邮件就是把封装在Message对象中的数据解析出来,包括邮件头中的邮件发送者地址、邮件主体、发送时间,邮件正文中的文本信息、内嵌资源,邮件体中的附件信息等,然后把解析出来的这些信息交给数据显示软件显示。

JavaMail解析邮件的流程如下:

(1) 调用Message对象的getForm,getSubject等方法,可以得到邮件发送人和主题等信息,调用getContentType方法得到邮件的类型。

(2) 通过Message.getContentType方法的返回值判断邮件类型,并调用Message.getContent方法得到邮件内容。如果邮件类型为“text/plain”或”text/html”,表示邮件为纯文本,此时调用Message对象的getContent方法得到邮件内容,然后将返回对象的类型转换成String输出给显示软件即可。如果邮件类型为”multipart/*”,表示邮件内容是一个复合类型,此时需将Message.getContent方法返回的对象转换成Multipart。

(3) 调用Multipart对象的getCount方法检测Multipart对象中封装了多少个BodyPart对象,并通过for循环逐一取出Multipart对象中的每个BodyPart对象进行处理。

(4) 在处理每个BodyPart对象时,首先调用BodyPart对象的getContentType方法得到他的MIME类型,然后根据MIME类型做出如下三种情况的处理:

a. 当MIME类型表示的是图片、声音或附件等二进制数据时,此时应调用BodyPart对象的getDataHandler方法得到封装了数据的DataHandler对象,然后调用DataHandler对象的getInputStream方法获得与数据相关的InputStream对象,通过这个InputStream对象中即可获得原始的二进制数据内容。

b. 当MIME类型为”text/*”时,表示BodyPart对象中保存的是纯文本数据,此时调用BodyPart对象的getContent方法并将返回的对象转换成String输出给显示软键显示即可。

c. 当MIME类型是”multipart/mixed”时,表示BodyPart对象中保存的是一个复合MIME消息,此时调用BodyPart对象中的getContent方法得到封装复合MIME消息的对象并将它转换成Multipart类型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: