大家好,今天笔者学习了一下 Spring 框架下的邮件发送,尝试了一下真的成功了呢!感兴趣的童鞋们可以继续往下看看~
JavaMail 概述
JavaMail,顾名思义,提供给开发者处理电子邮件相关的编程接口。JavaMail 是由 Sun 定义的一套收发电子邮件的 API,它可以方便地执行一些常用的邮件传输,不同的厂商可以提供自己的实现类。但它并没有包含在 JDK 中,而是作为 JavaEE 的一部分。
厂商所提供的 JavaMail 服务程序可以有选择地实现某些邮件协议,常见的邮件协议包括:
- SMTP:简单邮件传输协议,用于发送电子邮件的传输协议;
- POP3:用于接收电子邮件的标准协议;
- IMAP:互联网消息协议,是 POP3 的替代协议。
这三种协议都有对应 SSL 加密传输的协议,分别是 SMTPS,POP3S 和 IMAPS。除 JavaMail 服务提供程序之外, JavaMail 还需要 JAF(JavaBeans Activation Framework)来处理不是纯文本的邮件内容,这包括 MIME(多用途互联网邮件扩展)、URL 页面和文件附件等内容。另外,JavaMail 依赖 JAF(JavaBeans Activation Framework),JAF 在 Java6 之后已经合并到 JDK 中,而 JDK5 之前需要另外下载 JAF 的类库。
协议介绍
在研究 JavaMail API 的细则之前,首先需要对于 API 用到的协议有个认识。对于 java mail 来说用到的协议有常见的几种: SMTP、POP、IMAP、MIME
SMTP(通俗易懂就是发送的协议)
简单邮件传输协议(Simple Mail Transfer Protocol,SMTP)由 RFC 821 定义。它定义了发送电子邮件的机制。在 JavaMail API 环境中,您基于 JavaMail 的程序将和您的公司或因特网服务供应商的(Internet Service Provider's,ISP's)SMTP 服务器通信。SMTP 服务器会中转消息给接收方 SMTP 服务器以便最终让用户经由 POP 或 IMAP 获得。
POP(通俗易懂就是接收的协议)
POP 代表邮局协议(Post Office Protocol)。目前用的是版本 3,也称 POP3,RFC 1939 定义了这个协议。POP 是一种机制,因特网上大多数人用它得到邮件。它规定每个用户一个邮箱的支持。这就是它所能做的,而这也造成了许多混淆。使用 POP3 时,用户熟悉的许多性能并不是由 POP 协议支持的,如查看有几封新邮件消息这一性能。这些性能内建于如 Eudora 或 Microsoft Outlook 之类的程序中,它们能记住一些事,诸如最近一次收到的邮件,还能计算出有多少是新的。所以当使用 JavaMail API 时,如果您想要这类信息,您就必须自己算。
IMAP(通俗易懂就是比POP高级一点的接收的协议)
IMAP 是更高级的用于接收消息的协议。在 RFC 2060 中被定义,IMAP 代表因特网消息访问协议 (Internet Message Access Protocol),目前用的是版本 4,也称 IMAP4。在用到 IMAP 时,邮件服务器必需支持这个协议。不能仅仅把使用 POP 的程序用于 IMAP,并指望它支持 IMAP 所有性能。假设邮件服务器支持 IMAP,基于 JavaMail 的程序可以利用这种情况——用户在服务器上有多个文件夹(folder),并且这些文件夹可以被多个用户共享。因为有这一更高级的性能,您也许会认为所有用户都会使用 IMAP。事实并不是这样。要求服务器接收新消息,在用户请求时发送到用户手中,还要在每个用户的多个文件夹中维护消息。这样虽然能将消息集中备份,但随着用户长期的邮件夹越来越大,到磁盘空间耗尽时,每个用户都会受到损失。使用 POP,就能卸载邮件服务器上保存的消息了。
MIME
MIME 代表多用途因特网邮件扩展标准(Multipurpose Internet Mail Extensions)。它不是邮件传输协议。但对传输内容的消息、附件及其它的内容定义了格式。这里有很多不同的有效文档:RFC 822、RFC 2045、RFC 2046 和 RFC 2047。作为一个 JavaMail API 的用户,您通常不必对这些格式操心。无论如何,一定存在这些格式而且程序会用到它。
JavaMail 的关键对象
JavaMail 对收发邮件进行了高级的抽象,形成了一些关键的的接口和类,它们构成了程序的基础,下面我们分别来了解一下这些最常见的对象。
Properties 属性对象
由于 JavaMail 需要和邮件服务器进行通信,这就要求程序提供许多诸如服务器地址、端口、用户名、 密码等信息,JavaMail 通过 Properties 对象封装这些属性信息。如下面的代码封装了两个属性信息:
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.sina.com.cn");
props.put("mail.smtp.auth", "true");
针对不同的的邮件协议,JavaMail 规定了服务提供者必须支持一系列属性,下表是针对 SMTP 协议的一些常见属性(属性值都以 String 类型进行设置,属性类型栏仅表示属性是如何被解析的):
其他几个协议也有类似的一系列属性,如 POP3 的 mail.pop3.host、mail.pop3.port 以及IMAP 的 mail.imap.host、mail.imap.port等。
Session 会话对象
Session 是一个很容易被误解的类,这归咎于混淆视听的类名。千万不要以为这里的 Session 像 HttpSession 一样代表真实的交互会话,但创建 Session 对象时,并没有对应的物理连接,它只不过是一对配置信息的集合。
Session 的主要作用,包括两个方面:
- 接收各种配置属性信息:通过 Properties 对象设置的属性信息;
- 初始化 JavaMail 环境:根据 JavaMail 的配置文件,初始化 JavaMail 环境,以便通过 Session 对象创建其他重要类的实例。
Transport 和 Store 传输和存储
邮件操作只有发送或接收两种处理方式,JavaMail 将这两种不同操作描述为传输 (javax.mail.Transport)和存储(javax.mail.Store),传输对应邮件的发送,而存储对应邮件的接收
Message 消息对象
一旦获得 Session 对象,就可以继续创建要发送的消息。这由 Message 类来完成。因为 Message 是个抽象类,您必需用一个子类,多数情况下为 javax.mail.internet.MimeMessage。MimeMessage 是个能理解 MIME 类型和头的电子邮件消息,正如不同 RFC 中所定义的。虽然在某些头部域非 ASCII 字符也能被译码,但 Message 头只能被限制为用 US-ASCII 字符。
Address 地址
一旦您创建了 Session 和 Message,并将内容填入消息后,就可以用 Address 确定信件地址了。和 Message 一样,Address 也是个抽象类。您用的是 javax.mail.internet.InternetAddress 类。若创建的地址只包含电子邮件地址,只要传递电子邮件地址到构造器就行了。
Authenticator 认证者
与 java 类一样,JavaMail API 也可以利用 Authenticator 通过用户名和密码访问受保护的资源。对于 JavaMail API 来说,这些资源就是邮件服务器。JavaMail Authenticator 在 javax.mail 包中,而且它和 java.net 中同名的类 Authenticator 不同。两者并不共享同一个 Authenticator,因为 JavaMail API 用于 Java 1.1,它没有 java.net 类别。要使用 Authenticator,先创建一个抽象类的子类,并从 getPasswordAuthentication() 方法中返回 PasswordAuthentication 实例。创建完成后,您必需向 session 注册 Authenticator。然后,在需要认证的时候,就会通知 Authenticator。您可以弹出窗口,也可以从配置文件中(虽然没有加密是不安全的)读取用户名和密码,将它们作为 PasswordAuthentication 对象返回给调用程序。
Java Mail 环境准备
设置邮箱服务
由于笔者用的是 qq 邮箱,因此以 qq邮箱为例。登录 qq 邮箱页面,进行登录。
进入设置,然后到下图中的模块,将图中的两个 SMTP 服务都开启
需要根据注册时的手机号发送的验证码来开通获取邮箱客户端授权码。开通成功后,会显示个人授权访问码,该授权码是后面通过 Java mail 发送邮件的认证密码,非常重要。并且此授权码可用于其他第三方的邮箱登录密码!
添加依赖
创建 Maven 项目,在 pom.xml 配置文件中添加 mail 的所需的依赖
<!-- Java Mail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.6.2</version>
</dependency>
Java Mail 发送邮件
发送普通文本的邮件
public static void main(String[] args) throws Exception {
// 定义邮箱服务器配置
Properties properties=new Properties();
// 设置邮件服务器主机名 (163 邮件服务器地址:"mail.smtp.host" "smtp.163.com")
properties.setProperty("mail.smtp.host","smtp.qq.com");
// 设置邮件服务器的端⼝
properties.setProperty("mail.smtp.port", "587");
// 设置邮件服务器认证属性 (设置为true表示发送服务器需要身份验证)
properties.setProperty("mail.smtp.auth", "true");
// 使⽤JavaMail发送邮件的5个步骤
// 1. 创建session
Session session = Session.getInstance(properties);
// 开启Session的debug模式,这样就可以查看到程序发送Email的运⾏状态
session.setDebug(true);
// 2. 通过session得到transport对象
Transport ts = session.getTransport();
// 3. 使⽤邮箱的⽤户名和密码连上邮件服务器(⽤户名只需写@前⾯的即可,密码是指授权码)
ts.connect("smtp.qq.com", "1109725833", "ovhghencpxwuigbb");
// 4. 创建邮件
// 发送包含附件的邮件
Message message = createMail(session);
// 5. 发送邮件
ts.sendMessage(message, message.getAllRecipients());
// 关闭transport对象
ts.close();
}
public static MimeMessage createMail(Session session) throws MessagingException{
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("1109725833@qq.com"));
message.setRecipient(Message.RecipientType.TO, new InternetAddress("1109725833@qq.com"));
message.setSubject("你好吗");
message.setSentDate(new Date());
test1(message);
// 返回创建好的邮件对象
return message;
}
public static MimeMessage test1(MimeMessage message) throws MessagingException {
message.setText("你好,这是⼀封测试邮件!");
return message;
}
发送HTML内容的邮件
public static MimeMessage test2(MimeMessage message) throws MessagingException {
// 准备邮件数据
/**
* Message表示⼀个邮件,messgaes.getContent()返回⼀个Multipart对象。
* ⼀个Multipart对象包含⼀个或多个BodyPart对象,来组成邮件的正⽂部分(包括附件)。
*/
// 创建多媒体对象
MimeMultipart multipart = new MimeMultipart();
// 创建邮件体对象
MimeBodyPart bodyPart = new MimeBodyPart();
// 设置HTML内容
StringBuffer sb = new StringBuffer();
sb.append("<html><body><a href='http://www.baidu.com'>百度⼀下</a></body> </html>");
bodyPart.setContent(sb.toString(), "text/html;charset=UTF-8");
// 将bodyPart对象设置到multipart对象中
multipart.addBodyPart(bodyPart);
// 将multipart对象设置到message对象中 (setContent():)
message.setContent(multipart);
return message;
}
将 test2 方法替换 test1 方法即可,效果如图
发送包含附件的邮件
public static MimeMessage test3(MimeMessage message) throws MessagingException {
// 创建邮件正⽂
MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent("使⽤JavaMail创建的带附件的邮件", "text/html;charset=UTF-8");
// 创建附件
MimeBodyPart attachPart = new MimeBodyPart();
// 本地⽂件
DataHandler dh = new DataHandler(new FileDataSource("C:\\Users\\Administrator\\Desktop\\04-JSP与JSTL.txt"));
attachPart.setDataHandler(dh);
// 附件名
attachPart.setFileName(dh.getName());
// 创建容器描述数据关系
MimeMultipart multipart = new MimeMultipart();
// 添加正⽂
multipart.addBodyPart(bodyPart);
// 添加附件
multipart.addBodyPart(attachPart);
// 如果在邮件中要添加附件,设置为mixed;。
multipart.setSubType("mixed");
// 设置邮件的内容
message.setContent(multipart);
return message;
}
将 test3 方法替换 test2 方法即可,效果如图
使用 Spring API 实现邮件发送
环境准备
创建 Maven 项目,在 pom.xml 文件中添加依赖
<!-- spring核⼼ jar 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!--spring 上下⽂环境 ⽀持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.4.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- Java Mail坐标依赖 -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
配置邮件发送 bean
在 spring.xml 配置文件中设置邮件发送对应的 bean 标签
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启⾃动化扫描 -->
<context:component-scan base-package="com.shsxt"/>
<!-- 邮件发送器(提供了邮件发送接⼝、透明创建Java Mail的MimeMessage、及邮件发送的配置) -->
<bean id="mailSender"
class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.qq.com" />
<property name="port" value="587" />
<property name="defaultEncoding" value="utf-8"></property>
<property name="username" value="*********"></property>
<property name="password" value="*********"></property>
</bean>
<!-- 普通⽂本邮件对象 -->
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="***********@qq.com" />
<property name="subject" value="spring_mail" />
</bean>
</beans>
定义接口与实现类
定义接口
package com.xxxx.springMail;
/**
* 定义接⼝
*/
public interface OrderManager {
void placeOrder();
}
定义实现类
package com.xxxx.springMail;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class SimpleOrderManager implements OrderManager {
@Resource
private JavaMailSenderImpl mailSender;
@Resource
private SimpleMailMessage templateMessage;
@Override
public void placeOrder() {
// 获取邮件对象
SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
// 设置邮件收件⼈的邮箱地址
msg.setTo("收件⼈的邮箱地址");
// 设置邮件内容
msg.setText("Hello Spring Mail");
try{
// 发送邮件
this.mailSender.send(msg);
} catch (MailException ex) {
System.err.println(ex.getMessage());
}
}
}
邮件发送测试
/**
* 发送邮件
* @param args
*/
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");
SimpleOrderManager simpleOrderManager =
(SimpleOrderManager) ac.getBean("simpleOrderManager");
simpleOrderManager.placeOrder();
}
发送附件
/**
* 发送包含附件的邮件
* @param args
* @throws MessagingException
*/
public static void main(String[] args) throws MessagingException {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
JavaMailSender mailSender= (JavaMailSender) ac.getBean("mailSender");
MimeMessage message= mailSender.createMimeMessage();
message.setSubject("spring_mail"); // 邮件主题
// 创建带有附件的消息帮组类
MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");
helper.setTo(new InternetAddress("收件⼈的邮箱地址"));//设置接收⼈
helper.setText("Thank you for ordering!"); // 邮件内容
helper.setFrom("发件⼈的邮箱地址"); // 发件⼈
// 设置附件
File file = new File("C:\\work\\邮件附件.txt");
// 添加附件
helper.addAttachment(file.getName(), file);
// 发送邮件
mailSender.send(message);
}
总结:spring Mail 发送邮件实现的基础就是这些,感兴趣的童鞋们可以手动试试,别问我为什么没有接收,问就是还没学到≧ ﹏ ≦
时间是一个伟大的作者,它会给每个人写出完美的结局来