一、概述
JavaMail API 顾名思义,提供给开发者处理电子邮件相关的编程接口,它是Sun发布的用来处理email的API,其提供独立于平台且与协议无关的框架来构建邮件和消息传递应用。JavaMail API 提供了一组抽象类,用于定义组成邮件系统的对象,它是一个可选包(标准扩展名),用于阅读,撰写和发送电子信息。
开发人员使用JavaMail编写邮件程序时,不再需要考虑底层的通讯细节如:Socket,而是关注在逻辑层面。JavaMail可以发送各种复杂MIME格式的邮件内容,注意JavaMail仅支持JDK4及以上版本。虽然JavaMail是JDK的API但它并没有直接加入JDK中,所以我们需要另外添加依赖。
JavaMail 下载地址: github.com/javaee/java…
二、邮件协议
在收发邮件的过程中,需要遵守相关的协议,JavaMail并不是绝对支持每一个协议,其中主要有:
- 发送电子邮件的协议:
SMTP
; - 接收电子邮件的协议:
POP3
和IMAP
。
2.1 什么是SMTP?
SMTP
全称为Simple Mail Transfer Protocol
(简单邮件传输协议),它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP
认证要求必须提供账号和密码才能登陆服务器,其设计目的在于避免用户受到垃圾邮件的侵扰。
SMTP
协议提供程序支持以下属性,这些属性可以在JavaMail会话对象进行设置。
名称 | 类型 | 描述 |
---|---|---|
mail.smtp.user | String | SMTP的默认用户名 |
mail.smtp.host | String | 要连接的SMTP服务器 |
mail.smtp.port | int | 要连接的SMTP服务器端口,默认为25 |
mail.smtp.connectiontimeout | int | 套接字连接超时值,以毫秒为单位.默认为无限超时 |
mail.smtp.timeout | int | 套接字I/O超时值毫秒,默认为无限超时 |
mail.smtp.auth | boolean | 如果为true,则对用户进行身份验证,默认为false |
mail.smtp.ssl.enable | boolean | 如果设置为true,则默认情况下使用SSL连接并使用SSL端口。对于”smtp”协议,默认为false;对于”smtps”协议,默认为true. |
2.2 什么是IMAP?
IMAP
全称为Internet Message Access Protocol
(互联网邮件访问协议),IMAP
允许从邮件服务器上获取邮件的信息、下载邮件等。IMAP
与POP
类似,都是一种邮件获取协议。IMAP协议提供程序支持以下属性,这些属性可以在JavaMail会话对象进行设置。
名称 | 类型 | 描述 |
---|---|---|
mail.imap.user | String | IMAP的默认用户名 |
mail.imap.host | String | 要连接的IMAP服务器 |
mail.imap.port | int | 要连接的IMAP服务器端口,默认为143 |
mail.imap.connectiontimeout | int | 套接字连接超时值,以毫秒为单位.默认为无限超时 |
mail.imap.timeout | int | 套接字I/O超时值毫秒,默认为无限超时 |
mail.imap.statuscachetimeout | int | 缓存的超时值(以毫秒为单位),默认值为1000(1秒),零禁用缓存 |
mail.imap.appendbuffersize | int | 要缓冲的邮件的最大大小附加到IMAP文件夹时的内存 |
mail.imap.connectionpoolsize | int | 最大可用数量连接池中的连接,默认值为1 |
mail.imap.connectionpooltimeout | int | 连接池连接的超时值(以毫秒为单位),默认值为45000(45秒). |
mail.imap.ssl.enable | boolean | 如果设置如果为true,则默认使用SSL连接并使用SSL端口。”imap”协议默认为false,”imaps”协议默认为true. |
2.3 什么是POP3?
POP3
全称为Post Office Protocol 3
(邮局协议),POP3
支持客户端远程管理服务器端的邮件。POP3
常用于离线邮件处理,即允许客户端下载服务器邮件,然后服务器上的邮件将会被删除。目前很多POP3
的邮件服务器只提供下载邮件功能,服务器本身并不删除邮件,这种属于改进版的POP3
协议。
IMAP
和POP3
协议两者最大的区别在于,IMAP
允许双向通信,即在客户端的操作会反馈到服务器上,例如在客户端收取邮件、标记已读等操作,服务器会跟着同步这些操作。而对于POP
协议虽然也允许客户端下载服务器邮件,但是在客户端的操作并不会同步到服务器上面的,例如在客户端收取或标记已读邮件,服务器不会同步这些操作。
POP3协议提供程序支持以下属性,这些属性可以在JavaMail会话对象中设置
名称 | 类型 | 描述 |
---|---|---|
mail.pop3.user | String | POP3的默认用户名 |
mail.pop3.host | String | 要连接的POP3服务器 |
mail.pop3.port | int | 要连接的POP3服务器端口,默认为110 |
mail.pop3.connectiontimeout | int | 套接字连接超时值,以毫秒为单位,默认为无限超时 |
mail.pop3.timeout | int | 套接字I/O超时值毫秒,默认为无限超时 |
mail.pop3.ssl.enable | boolean | 如果设置为true,则默认情况下使用SSL连接并使用SSL端口。”pop3”协议默认为false,”pop3s”协议默认为true. |
三、核心类
JavaMail API 包含一些用于发送,读取和删除电子邮件的接口和类.虽然 JavaMail API 中有许多软件包,但它们将涵盖 Java Mail API 中经常使用的两个主要软件包: javax.mail 和 javax.mail.internet 软件包.这些包包含所有JavaMail核心类.它们是:
Class | 描述 |
---|---|
javax.mail.Session | API的关键类,多线程对象表示连接工厂。 |
javax.mail.Message | 为电子邮件建模的抽象类,子类提供实际的实现。 |
javax.mail.Address | 一个抽象类,用于对消息中的地址(来自地址和来自地址)进行建模,子类提供特定的实现。 |
javax.mail.Authenticator | 用于保护邮件服务器上邮件资源的抽象类。 |
javax.mail.Transport | 一个抽象类,它模拟用于发送电子邮件的邮件传输机制。 |
javax.mail.Store | 为消息存储建模的抽象类及其访问协议,用于存储和检索消息.商店分为文件夹。 |
javax.mail.Folder | 表示邮件消息文件夹的抽象类.它可以包含子文件夹。 |
3.1 Session
javax.mail.Session 类定义了一个基本邮件会话(session),是Java Mail API最高层入口类,所有其它类都是经由这个session才得以生效。Session类用于定义整个应用程序所需的环境信息以及客户端与邮件服务器建立网络连接的会话信息,例如邮件服务器的主机名、端口号、采用的邮件发送和接收协议等。Session 对象用Java.util.Properties
对象获取信息,根据这些信息构建用于邮件收发的 Transport 和 Store 对象,以及为客户端创建 Message 对象时提供信息支持。
Session类的构建方法是private 的,因此它提供了两个方法可以得到Session对象:
- getDefualtInstance()
1 | java复制代码public static Session getDefaultInstance(Properties props) |
- getInstance()
1 | java复制代码public static Session getInstance(Properties props) |
3.2 Message
javax.mail.Message 类是创建和解析邮件的核心API,一旦获得Session对象,就可以继续创建要发送的消息,这由Message类来完成。这是一个抽象类,通常使用它的子类 javax.mail.internet.MimeMessage
类。客户端程序发送邮件时,首先使用创建邮件的 JavaMail API 创建出封装了邮件数据的 Message 对象,然后把这个对象传递给邮件发送API(Transport 类) 发送。客户端程序接收邮件时,邮件接收API把接收到的邮件数据封装在Message 类的实例中,客户端程序在使用邮件解析API从这个对象中解析收到的邮件数据。
为了建立一个MimeMessage对象,我们必须将Session对象作为MimeMessage构造方法的参数传入:
1 | java复制代码// 通过session对象来创建一个MimeMessage对象 |
message对象一旦创建,就需要填充一些信息。Meesage类实现了 javax.mail.Part 接口,而MimeMessage类实现了 javax.mail.internet.MimePart 接口。
方法 | 描述 |
---|---|
void setFrom(Address address) | 用于设置发送者的邮件地址 |
void addRecipient(Message.RecipientType type,String address) | 设置邮件的收件人、抄送人、密送人(通过type区分) |
void addRecipients(Message.RecipientType type,Address[] addresses) | 设置邮件的多个收件人、抄送人、密送人(通过type区分) |
void setSubject(String subject) | 设置邮件标题 |
void setText(String textmessage) | 如果邮件内容是纯文本,可以使用此接口设置文本内容。 |
void setContent(Object obj,String type) | 设置邮件内容 |
3.3 Address
创建了Session和Message后,需要通过 Address 来设置信件的地址信息。由于 Address 是个抽象类,因此多数用它的实现类 javax.mial.internet.InternetAddress。
1 | java复制代码// 直接通过一个邮箱地址来创建 |
为了设置收信人,我们使用addRecipient()方法增加收信人,此方法需要使用Message.RecipientType的常量来区分收信人的类型:
1 | java复制代码message.addRecipient(type, address) |
下面是Message.RecipientType的三个常量:
1 | java复制代码public static class RecipientType implements Serializable { |
3.4 Authenticator
javax.mail.Authenticator 代表一个知道如何获得网络连接认证的对象,是一个抽象类,通常通过创建它的子类PasswordAuthentication,传递用户名和密码来创建。JavaMail API 可以利用 Authenticator 通过用户名和密码访问受保护的资源,对于JavaMail API来说,这些资源就是邮件服务器。
1 | java复制代码Properties props = new Properties(); |
3.5 Store
javax.mail.Store 是接收邮件的核心 API 类,它的实例对象代表实现了某个邮件接收协议的邮件接收对象,用来存储和查询消息。客户端程序接收邮件时,只需要使用邮件接收 API 得到 Store 对象,然后调用 Store 对象的接收方法,就可以从指定的 POP3 服务器获得邮件数据,并把这些邮件数据封装到表示邮件的 Message 对象中。
1 | java复制代码Store store = session.getStore("pop3"); |
Store 将根据Session中Properties属性设置情况进行工作,属性包括:
属性名 | 说明 |
---|---|
mail.store.protocol | 默认的存储邮件协议,例如:pop3 |
mail.host | 默认的邮件服务地址,例如:imap.sina.com |
mail.user | 默认的登陆用户名,例如:dllwhcrawler@sina.com |
mail.port | 默认的邮件服务端口 |
3.6 Transport
javax.mail.Transport 是发送邮件的核心API 类,它的实例对象代表实现了某个邮件发送协议的邮件发送对象,例如 SMTP 协议,客户端程序创建好 Message 对象后,只需要使用邮件发送API 得到 Transport 对象,然后把 Message 对象传递给 Transport 对象,并调用它的发送方法,就可以把邮件发送给指定的 SMTP 服务器。
1 | java复制代码Transport.send(message); |
Transport 将根据Session中Properties属性设置情况进行工作,属性包括:
属性名 | 说明 |
---|---|
mail.transport.protocol | 默认的邮件传输协议,例如,smtp |
mail.host | 默认的邮件服务地址,例如:smtp.sina.com |
mail.user | 默认的登陆用户名,例如:dllwhcrawler@sina.com |
mail.port | 默认的邮件服务端口 |
3.7 Folder
javax.mail.Folder是个抽象类,代表邮件消息的一个文件夹,其子类实现了特定的Folders。其实例:
1 | java复制代码public abstract class Folder implements AutoCloseable |
由于 Folder 类唯一的构造函数是受保护的,但Session
、Store
都有一个类似的getFolder()方法获取Folder对象:
1 | java复制代码public abstract Folder getFolder(String name) throws MessagingException; |
四、邮件操作
4.1 准备工作
创建一个邮件的基本信息类MailInfo,如下:
1 | java复制代码import lombok.Data; |
相关依赖:
1 | xml复制代码<!-- JavaMail API--> |
4.2 发送邮件
- 发送邮件需要使用的基本信息:MailSenderInfo
1 | java复制代码@Data |
- 发送邮件
1 | java复制代码import org.apache.commons.lang3.StringUtils; |
- 测试类
1 | java复制代码import org.dllwh.javamail.mailsend.JavaMailSendHelper; |
4.2 收取邮件
- 接收邮件
1 | java复制代码import org.apache.commons.lang3.ArrayUtils; |
- 测试类
1 | java复制代码import org.dllwh.javamail.mailreceive.JavaMailReceiveHelper; |
4.3 回复邮件
我们使用JavaMail API来回复电子邮件,下面的程序中的列出基本步骤:
- 获取Session对象与POP和SMTP 服务器的细节属性。
- 创建POP3存储对象,并连接到存储。
- 创建文件夹对象,并在您的邮箱中打开相应的文件夹。
- 检索消息。
- 遍历的消息,如果你想回复键入“Y”或“y”。
- 得到消息的所有信息(收件人,发件人,主题,内容)(To,From,Subject, Content) 。
- 建立应答消息,使用Message.reply()方法。这个方法配置一个新的消息与适当的收件人和主题。该方法接受一个布尔参数,指示是否只回复给发送者 (false)或回复给所有人(true)。
- 从设置,文本和回复到邮件中,并通过传输对象的实例发送。
- 关闭传输,文件夹和存储对象分别。
4.5 转发邮件
我们将使用JavaMail API来转发电子邮件,下面的程序的基本步骤是:
- 获取Session对象与POP和SMTP服务器的细节的属性。我们需要的POP细节来检索信息和SMPT详细信息发送邮件。
- 创建POP3存储对象,并连接到存储。
- 创建文件夹对象,并在您的邮箱中打开相应的文件夹。
- 检索消息。
- 遍历的消息,如果你想转发键入“Y”或“y”。
- 得到消息的所有信息(收件人,发件人,主题,内容)。
- 通过与组成消息的各个部分的工作建立转发消息。第一部分将是消息的文本和第二部分将要转发的邮件。结合两成多部分。那么你多部分添加到妥善处理消息并发送它。
- 关闭传输,文件夹和存储对象分别。
4.6 删除邮件
我们将使用JavaMail API来删除电子邮件。删除信息涉及与该消息相关联的标志工作。有不同的标志为不同的状态,一些系统定义和一些用户定义的。预定义的标志在内部类中定义的标志。标志如下所列:
Flags.Flag.ANSWERED | 邮件回复标记,标识邮件是否已回复。 |
Flags.Flag.DELETED | 邮件删除标记,标识邮件是否需要删除。 |
Flags.Flag.DRAFT | 草稿邮件标记,标识邮件是否为草稿。 |
Flags.Flag.FLAGGED | 表示邮件是否为回收站中的邮件。 |
Flags.Flag.RECENT | 新邮件标记,表示邮件是否为新邮件。 |
Flags.Flag.SEEN | 邮件阅读标记,标识邮件是否已被阅读。 |
Flags.Flag.USER | 底层系统是否支持用户自定义标记,应用程序只能检索这个属性,而不能设置。 |
其次在删除程序的基本步骤是:
- 获取Session对象与POP和SMTP伺服器的细节的属性。
- 创建POP3存储对象,并连接到存储。
- 创建文件夹对象,并在READ_WRITE模式下邮箱打开相应的文件夹。
- 从收件箱文件夹中检索邮件。
- 遍历的消息,如果你想通过Message对象上调用方法setFlag(Flags.Flag.DELETED, true)以删除邮件中键入“Y”或“y”。
- 这些消息标记DELETED 实际上并没有删除,直到我们调用Folder对象上expunge() 方法,或expunge 设置为true,关闭文件夹。
- 关闭存储对象
4.7 邮件文件夹管理
下面列出一些常用的方法:
- 获取 Folder 对象的方法
方法 | 描述 |
---|---|
boolean exists() | 检查文件夹是否真的存在。 |
void open(int mode) | 以Folder.READ_ONLY或Folder.READ_WRITE模式打开文件夹。 |
boolean isOpen() | 如果文件夹打开,此返回true,否则返回false。 |
void close(boolean expunge) | 关闭文件夹。如果expunge为true,则会从服务器上的实际文件中删除该文件夹中的所有已删除邮件。否则,它们只是标记为已删除,但邮件仍然可以取消删除. |
* 获取文件夹基本信息的方法 |
方法 | 描述 |
---|---|
String getName() | 返回文件夹的名称,例如”TutorialsPoint Mail” |
String getFullName() | 从根目录返回完整的层次结构名称,例如”books/Manisha/TutorialsPointMail” |
URLName getURLName() | 返回表示此文件夹的URLName |
Folder getParent() | 返回包含此文件夹的文件夹的名称,即父文件夹.例如,之前的”TutorialsPoint Mail”示例中的”Manisha”. |
int getType() | 返回一个int,指示文件夹是否可以包含消息和/或其他文件夹. |
int getMode() | 它返回两个命名常量Folder.READ_ONLY或Folder之一.当模式未知时,READ_WRITE或-1. |
Store getStore() | 返回Store对象从中检索此文件夹 |
char getSeparator() | 返回分隔的分隔符此文件夹的路径名来自直接子文件夹的名称 |
* 管理文件夹 |
方法 | 描述 |
---|---|
create(int type) | 这会在此文件夹的Store中创建一个新文件夹.如果成功返回true,否则返回false。其中类型将是:Folder.HOLDS_MESSAGES或Folder.HOLDS_FOLDERS. |
delete(boolean recurse) | 仅当文件夹关闭时,才会删除文件夹,否则抛出IllegalStateException。如果recurse是true,则删除子文件夹. |
renameTo(Folder f) | 更改文件夹的名称,必须关闭文件夹才能重命名.否则,抛出IllegalStateException |
appendMessages(Message[] messages) | 顾名思义,数组中的消息放在此文件夹的末尾 |
copyMessages(Message[] msgs,Folder folder) | 这会将此文件夹中的消息复制到作为参数给出的指定文件夹中 |
Message[] expunge() | 从文件夹中物理删除已删除的邮件 |
* 列出文件夹的内容 |
方法 | 描述 |
---|---|
Folder[] list() | 返回一个数组,列出该文件夹包含的文件夹. |
Folder[] listSubscribed() | 返回一个数组,列出该文件夹包含的所有订阅文件夹. |
* 检查邮件 |
方法 | 描述 |
---|---|
int getMessageCount() | 邮件总数 |
boolean hasNewMessages() | |
int getNewMessageCount() | |
int getUnreadMessageCount() | 未读邮件数 |
int getDeletedMessageCount() | 删除邮件数 |
* 从文件夹获取消息 |
方法 | 描述 |
---|---|
Messageget Message(int msgnum) | 这将返回文件夹中的第n条消息.文件夹中的第一条消息是数字 1 |
Message[] getMessages() | 返回一组Message对象,表示此文件夹中的所有消息 |
Message[] getMessages(int start,int end) | |
Message[] getMessages(int[] msgnums) | |
* 修改文件夹标记 |
方法 | 描述 |
---|---|
void setFlags(Message[] msgs,Flags flag,boolean value) | 在数组中指定的消息上设置指定的标志 |
void setFlags(intstart,intend,Flags flag,boolean value) | 设置从开始到结束编号的消息上的指定标志,包括起点和终点 |
void setFlags(int[] msgnums,Flags flag,boolean value) | 设置消息号在数组中的消息的指定标志 |
Flags getPermanentFlags() | 返回此文件夹支持所有邮件的标志 |
本文转载自: 掘金