使用JavaMail收发邮件

时间:2021-12-11 23:18:48

JavaMail是可以用来收发电子邮件的API。使用它需要两个Jar:mail.jaractivation.jar。API文档可以在这里查看。

关于收发邮件,相信只要使用过邮件客户端(比如MicrosoftOutlook)就应该知道,发送邮件需要使用smtp协议,而收取邮件需要使用pop3或者imap协议。如果不知道也没关系,因为使用JavaMail除了知道这几个协议的名字之外,并不需要知道更深的原理。

下面就来介绍一下使用JavaMail收发邮件的详细步骤。在可以收发邮件之前,首先要:

 

(一)与服务器建立连接

连接到服务器的过程分为以下四步:

 

第一步:设置SSL安全连接(如果需要的话)

有些邮箱要求客户端必须使用SSL安全连接,比如Gmail。这时,我们就必须先设置SSL安全连接属性。设置方法如下:
Security.addProvider(newcom.sun.net.ssl.internal.ssl.Provider());
final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
Properties props = System.getProperties();
props.setProperty("mail.
(协议名).socketFactory.class", SSL_FACTORY);
props.setProperty("mail.(协议名).socketFactory.fallback", "false");
props.setProperty("mail.(协议名).port","服务器端口号");
props.setProperty("mail.(协议名).socketFactory.port","服务器SSL端口号");

 

比如,设置到Gmail的smtp服务器的SSL连接,代码如下:
Security.addProvider(newcom.sun.net.ssl.internal.ssl.Provider());
final String SSL_FACTORY ="javax.net.ssl.SSLSocketFactory";
Properties props = System.getProperties();
props.setProperty("mail.smtp.socketFactory.class",SSL_FACTORY);
props.setProperty("mail.smtp.socketFactory.fallback","false");
props.setProperty("mail.smtp.port", "465");
props.setProperty("mail.smtp.socketFactory.port", "465");

 

第二步:创建Session(会话)对象

查看API文档中对于Session类的定义:

The Session class represents a mail session and is notsubclassed. It collects together properties and defaults used bythe mail API's. A single default session can be shared by multipleapplications on the desktop. Unshared sessions can also becreated.

这就是说,在一个Java虚拟机中,若干个收发邮件的程序可以共享一个Session对象用来收发邮件。(待证!)

要共享Session对象,就需要有一个默认的静态对象可供随时调用。取得这个静态Session对象的方法是:
Session session =Session.getDefaultInstance(props);
调用这个方法时,如果这个静态对象还未建立,虚拟机则会根据参数提供的属性建立一个Session对象;如果已经建立过了,则会直接返回静态对象,而忽略传入的属性参数。

当然,也可以不使用默认的静态对象,而是建立一个非默认的Session对象:
Session session =Session.getInstance(props);

其中的属性参数(props),如果第一步设置过SSL安全连接,那么就使用第一步中那个props对象;如果没有设置过安全连接,则可以直接使用System.getProperties()

 

第三步:创建Service(服务)对象

查看API文档中对于Service类的定义:

An abstract class that contains the functionality common tomessaging services, such as stores and transports.

一个Service对象是利用Session对象获取的,可以看作一个与服务器的连接。这个连接对应的服务器地址、端口、用户名和密码是确定的,并且这个对象可以提供“messageingservices”,即与收发邮件有关的服务。

Service是抽象类,它有两个子类,分别是Store和Transport。这两个类的对象分别提供接收邮件和发送邮件的相关功能。我们在实际使用时,一般总是直接使用Store和Transport两个类,而在代码中看不到“Service”的影子。

①要收取邮件,就要取得与pop3或者imap服务器连接的Store对象。取得方法是:
URLName urln= new URLName("pop3"(或"imaps"),"服务器地址", "服务器端口号", null, "用户名","密码");
Store store = session.getStore(urln);

②要发送邮件,则要取得与smtp服务器连接的Transport对象。取得方法是:
URLName urln= new URLName("smtp", "服务器地址","服务器端口号", null, "用户名", "密码");
Transport store =session.getTransport(urln);

 

第四步:连接服务器

非常简单:
store.connect();
或者
transport.connect();

连接服务器的方法直到连接成功或超时才会返回,因此会有网络延迟,需要等待几秒钟的时间。第一到第三步都不会有网络通信,因此基本不会有延迟。

 

现在已经获得了可用于收发邮件的Store或者Transport对象了,接下来就可以:

(二)发送一封邮件

要使用发送邮件功能,首先要:

 

第一步:建立一封邮件

JavaMail使用Message类对象代表一封邮件。而在本地建立邮件,我们使用的是它的子类MimeMessage。

一封邮件有哪几部分组成?主题、收件人、发件人、正文……一个发送邮件的页面并不能告诉我们一封邮件的全部组成。简单来说,在JavaMail中,一封邮件是用一个Message类对象表示的,可以设置或读取的部分有以下几个:

 

 项目  在JavaMail中的名称  在JavaMail中的使用格式(类)
 发件人  from  Address
 收件人  recipients  Address[]
 回复地址  reply to  Address
 主题  subject   String
 发送日期  send date  Date
 邮件头  headers  String-String
 标志  flags  String-boolean
 正文  content  (Object)

 

首先,建立一封邮件:
Messagemessage = new MimeMessage(session);

设置发件人(可省略):
message.setFrom(newInternetAddress("发件人邮箱名"));
设置发件人可以省略,默认为Transport对应的邮箱,也就是实际发出邮件的邮箱。不过如果把发件人设置成别人的邮箱会怎样呢?可以用来忽悠人么?我用Gmail试过,即使发件人设置成另外一个邮箱,收到以后仍然会显示实际发出邮件的邮箱……囧

设置收件人:
message.addRecipients(收件人格式,InternetAddress.parse("收件人邮箱名"));
可以重复调用此方法来添加多个收件人。
“收件人格式”有以下几种:
Message.RecipientType.TO:普通的“收件人”
Message.RecipientType.CC:“抄送”
Message.RecipientType.BCC:“密送”

设置回复地址(可省略):
message.setReplyTo(InternetAddress.parse("回复地址"));
设置回复地址可以省略,默认为发件人的邮箱地址。据说设置回复地址可以让收到邮件的人在回复邮件的时候自动回复到指定的邮箱地址。但是我用Gmail试验的结果:无效!仍然会回复到发件人的邮箱。这是咋回事呢?

设置主题(可省略):
message.setSubject("主题");
设置主题也可以省略,默认为没有主题,在很多邮箱的网页上会显示“(无主题)”。

设置发送日期(可省略):
message.setSendDate(发送日期);
设置发送日期可以省略,默认为发送时的时间。发送日期的格式是Date对象。需要注意的是,邮件的发送日期与接收日期是分开的。接受日期会在邮件被接收到的时候由接收邮件的邮箱服务器自动设置。比如Gmail在邮件列表的右侧显示的是邮件的接收日期,而在邮件页面的详细信息那里,“日期”一项显示的则是邮件的发送日期。

设置邮件头(可省略):
message.setHeader("名称","");
邮件头(headers)是在邮件正文之前的一部分,写有邮件的各种属性。每一封邮件有若干个邮件头,每一个邮件头由一个名称(name)和一个值(value)组成,类似于映射(Map),不过每一个邮件头的名称和值都是字符串。
其实,邮件的主题、发件人、回复地址、发送日期等信息都是被写在邮件头里的,当调用JavaMail的方法设置的时候,JavaMail就会设置相应的邮件头。当然,我们也可以定义自己的邮件头,而且不同的邮件头是可以重名的。

设置标志(可省略):
message.setFlags(标志,是否被设置);
(待学习……)

设置正文:
message.setContent(Multipart);
邮件正文最常用的是Multipart(因为其他格式我还没学会……)。当然,如果邮件正文只需要有一段纯文本的话,可以用message.setText("纯文本")设置。
Multipart相当于若干个Part的集合。Multipart是一个抽象类,我们实际使用的是它的子类MimeMultipart:
Multipartmultipart = newMimeMultipart();
建立好Multipart以后,就可以建立Part对象并加到Multipart对象里了。Part是一个接口,一般使用它的实现类MimeBodyPart:
MimeBodyPartmimeBodyPart = new MimeBodyPart();
multipart.addBodyPart(mimeBodyPart);
每一个MimeBodyPart都可以有两种格式:文本和附件。可以使用这个方法进行设置:
mimeBodypart.setDescription(Part.INLINE或者Part.ATTACHMENT);
①对于文本格式的MimeBodyPart,可以使用这个方法写入内容:
mimeBodypart.setText("文本");
②对于附件格式的MimeBodyPart,一般使用以下两种方法写入内容:
mimeBodypart.attachFile(文件);
mimeBodypart.setDataHandler(new DataHandler(newFileDataSourse(文件)));
其中的文件参数既可以是File对象,又可以是文件路径字符串。
如果是附件,还不要忘了添加附件文件名:
mimeBodypart.setFileName("附件文件名");
邮件中的附件文件名可以与本地实际文件的文件名不同。
建立若干需要的mimeBodyPart并加入到MimeMultipart之后,一封邮件的正文部分就创建完成了。

 

邮件创建好后,就可以用Transport对象发送它了: 

第二步:发送邮件

发送邮件的方法很简单:
transport.sendMessage(message,message.getAllRecipients());
此方法将在邮件发送完毕后返回。