1.开发 JavaMail Web应用
通过JavaMail Web应用,客户可以访问邮件服务器上的邮件账号,收发邮件和管理邮件夹。本章首先介绍电子邮件的发送和接收协议,接着介绍JavaMail API的常用类的用法,然后讲解通过JavaMail API 创建应用程序的步骤,最后介绍JavaMail Web应用。运行JavaMail 例子时,读者需要先安装一个名为 merak 的邮件服务器,本章介绍了在Windows下安装和配置该邮件服务器的方法。
1.1 E-Mail 协议简介
邮件服务器按照提供的服务类型可分为发送邮件服务器和接收邮件服务器。邮件发送协议常用的是 SMTP协议;邮件接收协议常用的有 POP3协议和 IMAP协议。
1.1.1 SMTP简单邮件传输协议
简单邮件传输协议(SMTP),是 Internet传递 E-Mail的基本协议,也是 TCP/IP协议组的成员。
SMTP协议发送一封邮件的过程:客户端邮件首先到达邮件发送服务器,再由发送服务器负责传递到接收方的服务器。发送邮件前,发送服务器会与接收方服务器联系,以确认接收方服务器是否已准备好接收邮件,如果已经准备好,则传递邮件;如果没有准备好,发送服务器便会等待,并在一段时间后继续与接收方服务器进行联系,若在规定的时间内联系不上,发送服务器会发送一个消息到客户的邮箱说明这个问题。这种方式在 Internet中称为 “ 储存 - 转发 ” 方式,这种方式会使得邮件在沿途各个网点上处于等待状态,直至允许其继续前进。虽然该方式降低了邮件的传送速度,但能极大地提高邮件到达目的地的成功率。
1.1.2 接收邮件的新协议 IMAP
IMAP是互联网消息访问协议,是一种功能比 POP3 更强大的新的接收邮件协议。
IMAP4 与 POP3 协议一样提供了方便的下载邮件服务,允许用户在脱机状态下阅读已经下载到本地磁盘的邮件。但 IMAP4 的功能远远不止这些,他还具有以下功能:
- 摘要浏览邮件的功能。允许用户先阅读邮件的概要信息,比如邮件的到达时间、主题、发件人和邮件大小等,然后再做出是否下载邮件的决定。
- 选择性下载附件的功能。假如一封邮件里有五个附件,用户可以选择下载其中几个附件。
- 鼓励用户把邮件一直存储在邮件服务器上。
- 允许用户把远程邮件服务器上的邮件作为信息储存工具。
1.2 JavaMail API 简介
如果用 Java 语言从头编写邮件客户程序,就必须通过 Java 套字节(Socket)与邮件服务器通信,发送和接收符合IMAP、POP3 或 SMTP 协议的请求和响应信息。
-
javax.mail.Session 类
Session 类表示邮件会话,是 JavaMail API 的最高层入口类。Session 对象从 java.util.Properties 对象中获取配置信息。
提示:javax.mail.Session 和 javax.servlet.http.HttpSession 是两个不同的类,为了区分他们,把前者称为邮件会话,把后者称为HTTP会话。
-
javax.mail.Store 类
Store 类表示接收邮件服务器上的注册账号的储存空间,通过Store 类的 getFolder() 方法,可以访问用户的特定邮件夹。
-
javax.mail.Folder 类
Folder 类代表邮件夹,邮件都放在邮件夹中,Folder 类提供了管理邮件夹以及邮件的各种方法。
-
javax.mail.Message 类
Message 类代表电子邮件。Message 类提供了读取和设置邮件内容的方法。这是个抽象类,常用的具体子类为 Javax.mail.internet.MimeMessage。MimeMessage 是正文部分符合 MIME 协议的电子邮件。
-
javax.mail.Address 类
Address 类代表邮件地址,Address类也是个抽象类。常用的具体子类为javax.mail.internet.InternetAddress 类。
-
javax.mail.Transport 类
Transport 类根据指定的邮件发送协议(通常是SMTP协议),通过指定的邮件发送服务器来发送邮件。Transport 类是抽象类,它的静态方法 send(Message) 负责发送邮件。
1.3 建立 JavaMail 应用程序的开发环境
JDK 中并不包含JavaMail API 及其实现的类库。
可以通过pom.xml配置,也可以通过1.3.1下载类库到lib目录下配置。
<!-- https://mvnrepository.com/artifact/javax.mail/javax.mail-api -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.6.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>
1.3.1 获得 JavaMail API 的类库
可以到 https://www.oracle.com/technetwork/java/JavaMail/index-138643.html 下载最新的 JavaMail API 的类库文件,获得 mail.jar 文件,它包含了 JavaMail API 中所有的接口和类。
还需要到 https://www.oracle.com/technetwork/java/jaf11-139815.html 下载最新的 JavaBean Activation Framework(JavaBean 激活框架)的类库文件 。JavaMail API 的实现依赖于 JavaBean 激活框架。获得activation.jar 文件,它包含了 JavaBean 激活框架中所有的接口和类。
1.3.2 安装和配置邮件服务器
我们选用 Merak 邮件服务器,它是一个商业邮件服务器,支持STMP、POP3和 IMAP协议。
提示:Merak 邮件服务器已经更名为 IceWarp 邮件服务器,它是商业化软件,它的新的官方网站为:www.icewarp.com。可以从该网址下载最新的免费试用版本。
安装和配置过程请自行百度或评论留言!
我们在该服务器上配置了一个邮件账号:admin@mydomain.com,且修改这个账号的接收邮件协议属性,把原来默认的 POP3协议改为 IMAP协议,因为 IMAP协议具有更多的功能。
我们也可以使用 QQ邮箱服务器作为邮件发送和接收的服务器。“smtp.qq.com”。
1.4 创建 JavaMail 应用程序
例程的 MailClient 类演示了通过 JavaMail API 来收发邮件的基本方法。
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
import java.util.*;
public class MailClient {
protected Session session;
protected Store store;
private String sendHost="localhost"; //发送邮件服务器
private String receiveHost="localhost"; //接收邮件服务器
private String sendProtocol="smtp"; //发送邮件协议
private String receiveProtocol="imap"; //接收邮件协议
private String username = "admin";
private String password = "1234";
private String fromAddr="admin@mydomain.com"; //发送者地址
private String toAddr="admin@mydomain.com"; //接收者地址
public void init()throws Exception{
//设置 JavaMail 属性,如果采用默认值,则不必调用 props.put()方法来显式设置该属性。
Properties props = new Properties();
props.put("mail.transport.protocol", sendProtocol); //指定邮件发送协议,默认值为“smtp”
props.put("mail.store.protocol", receiveProtocol); //指定邮件接收协议
// 指定支持 SMTP 协议的 Transport 具体类,允许由第三方提供。默认值为“com.sun.mail.smtp.SMTPTransport”
props.put("mail.smtp.class", "com.sun.mail.smtp.SMTPTransport");
// 指定支持 SMTP 协议的 Store 具体类,允许由第三方提供。默认值为“com.sun.mail.imap.IMAPStore”
props.put("mail.imap.class", "com.sun.mail.imap.IMAPStore");
props.put("mail.smtp.host", sendHost); //设置发送邮件服务器
// 创建Session对象,该方法根据已经配置的 JavaMail属性来创建 Session实例
session = Session.getDefaultInstance(props);
//session.setDebug(true); //输出跟踪日志
// 创建Store对象,返回 JavaMail中设置的com.sun.mail.imap.IMAPStore类的实例
store = session.getStore(receiveProtocol);
//连接到收邮件服务器
store.connect(receiveHost,username,password);
//连接成功!就可以用 Store对象来访问邮件服务器上的特定邮件账号了。
}
public void close()throws Exception{
store.close();
}
public void sendMessage(String fromAddr,String toAddr)throws Exception{
//创建一个邮件
Message msg = createSimpleMessage(fromAddr,toAddr);
//发送邮件
Transport.send(msg);
}
public Message createSimpleMessage(String fromAddr,String toAddr)throws Exception{
//创建一封纯文本类型的邮件
Message msg = new MimeMessage(session);
InternetAddress[] toAddrs =InternetAddress.parse(toAddr, false);
msg.setRecipients(Message.RecipientType.TO, toAddrs);//设置邮件接收者
msg.setSentDate(new Date());
msg.setSubject("hello");//设置邮件主题
msg.setFrom(new InternetAddress(fromAddr));//设置邮件发送者
msg.setText("How are you");//设置邮件正文
return msg;
}
public void receiveMessage()throws Exception{
browseMessagesFromFolder("inbox");
/* 在IMAP协议中,inbox邮件夹是邮件账号的保留邮件夹,用户不允许删除该邮件夹,邮件服务器把所有接收到的新邮件都存在该邮件夹中。*/
}
public void browseMessagesFromFolder(String folderName)throws Exception{
Folder folder=store.getFolder(folderName);//获得名为 folderName的邮件夹
if(folder==null)
throw new Exception(folderName+"邮件夹不存在");
browseMessagesFromFolder(folder);
}
public void browseMessagesFromFolder(Folder folder)throws Exception{
folder.open(Folder.READ_ONLY);//打开邮件夹
//获得邮件夹中的邮件数目
System.out.println("You have "+folder.getMessageCount()+" messages in inbox.");
//获得邮件夹中的未读邮件数目
System.out.println("You have "+folder.getUnreadMessageCount()+" unread messages in inbox.");
//读邮件
Message[] messages=folder.getMessages();
for(int i=1;i<=messages.length;i++){
System.out.println("------第"+i+"封邮件-------");
//打印邮件信息
folder.getMessage(i).writeTo(System.out);
System.out.println();
}
folder.close(false); //关闭邮件夹,但不删除邮件夹中标志为“deleted”的邮件
}
public static void main(String[] args)throws Exception {
MailClient client=new MailClient();
client.init();
client.sendMessage(client.fromAddr,client.toAddr);
client.receiveMessage();
client.close();
}
}
1.5 JavaMail Web 应用简介
图1-1显示了该应用的三层结构:Web客户通过浏览器访问 JavaMail应用,该应用可以连接到客户请求的某个 IMAP服务器上的邮件账号。此外,该应用还可以通过特定的 SMTP服务器发送邮件。
需要该 JavaMail应用的例子请评论区留言!!!
1.5.1 重新封装 Message 数据
PMessage 类对 Message 类表示的邮件数据重新封装,提供更方便地显示邮件信息的方法。例如在javax.mail.Message 类中读取接收者邮件地址列表的方法为 getTo()方法,该方法返回 Address[]类型的数组,如果要把接受者邮件地址列表显示到网页上,必须把 Address[]数组转化为相应的字符串,PMessage 的PMessage(Message msg) 构造方法对 Message数据做了重新封装。调用PMessage getTo() 方法可以直接获取到字符串形式的接受者邮件地址列表。
在PMessage类的PMessage(String to, String cc, String bcc, String subj, String text) 构造方法中,输入的多个邮件地址之间采用逗号间隔,这是因为 IMAP协议要求多个邮件地址之间采用逗号作为间隔。
1.6 在Tomcat中配置邮件会话(Mail Session)
可以把 Mail Session作为一种 JNDI资源在 Tomcat中配置,Tomcat提供了创建 Mail Session对象的工厂:org.apache.naming.factory.MailSessionFactory。
1.6.1 在 context.xml 中配置 Mail Session 资源
以下代码在 JavaMail/META-INF/context.xml 文件中配置了一个 Mail Session 资源,它的 JNDI名字为 “mail/session”:
<Context reloadable="true" >
<Resource name="mail/session"
auth="Container"
type="javax.mail.Session"
mail.smtp.host="localhost"
mail.store.protocol="imap" />
</Context>
以上<Resource>元素用于配置 Mail Session资源,对应的属性描述参见下表。
属性 | 描述 |
---|---|
name | 指定Resource 的 JNDI名字 |
auth | 指定管理 Resource的 Manager,它有两个可选值:Container 和 Application。Container表示由容器来创建和管理Resource,Application是由 Web应用来创建和管理Resource。 |
type | 指定 Resource所属的 Java类名 |
mail.smtp.host | 指定发送邮件服务器的主机 |
mail.store.protocol | 指定接收邮件的协议 |
提示:如果希望 Mail Session资源被 Servlet容器内的虚拟主机中的多个 Web应用访问。那么可以在 <CATALINA_HOME>/conf/server.xml 文件中的相应 <Host>元素中配置 <Resource>子元素。
1.6.2 在web.xml中加入对JNDI Mail Session资源的引用
由于 JavaMail应用会引用 JNDI Mail Session资源,所以应该在 web.xml中加入<resource-ref>元素,用于声明所引用的名为 “mail/session” 的 JNDI资源:
<resource-ref>
<description>Java Mail Session</description>
<res-ref-name>mail/session</res-ref-name>
<res-type>javax.mail.Session</res-type>
<res-auth>Container</res-auth>
</resource-ref>
1.6.3 在 JavaMail应用中获取 JNDI Mail Session资源
从 Tomcat 的 Mail Session 工厂中取得 Session对象的引用:
Context ctx = new InitialContext();
if(ctx == null )
throw new Exception("No Context");
Session mailsession =(Session)ctx.lookup("java:comp/env/mail/session");
Mail Session 所需的 JavaMail 属性已经在 context.xml文件中做了设置,Mail Session由 Tomcat容器来负责创建和管理,所以在该代码中不需要再为 Mail Session设置 JavaMail属性。
1.6.4 发布和运行 JavaMail应用
由于 Mail Session由 Tomcat容器来负责创建和管理,所以需要把 activation.jar 和 mail.jar 文件复制到 <CATALINA_HOME>/lib 目录下,这样Tomcat容器才可以访问这些 JAR文件。
然后将 JavaMail应用复制到 <CATALINA_HOME>/webapps 目录下即可。
需要该 JavaMail应用的例子请评论区留言!!!