目录
- 前言
- 一、创建Spring boot工程后,在pom.xml中添加依赖
- 1.1、方式一,新建工程时,在IO选项勾选邮件依赖
- 1.2、方式二,手动在pom.xml中添加依赖
- 二、在工程resource目录下创建application.properties文件,并添加相关配置
- 三、关于授权码
- 3.1、什么是 QQ 邮箱授权码
- 3.2、如何获取QQ授权码
- 3.2.1、登录 QQ 邮箱
- 3.2.2、点击设置,再点击页签中的“账户”
- 3.2.3、跳转页面后,点击账户,将页面往下拖动,您会看到,授权码的开启菜单
- 3.2.4、点击“开启”,验证成功过后,即可获取授权码
- 3.3、163邮箱的授权码
- 3.3.1、点击顶部页签的”"设置"按钮,进入POP3设置界面
- 3.3.2、开启服务,也可以重新生成授权码
- 3.4、 发送邮件所需要遵从的POP3/SMTP/IMAP三个协议的简述
- 四、业务代码
- 4.1、新增MailService接口,并声明4个发送不同类型邮件的方法
- 4.2、新增MailService接口的实现类MailServiceImpl
- 4.3、工程目录结构查看
- 五、单元测试,查看成果
- 5.1、发送纯文本邮件的测试
- 5.1.1、测试代码编写
- 5.1.2、运行查看,报错小插曲
- 5.1.3、给MailServiceImpl添加@Component注解后,再试
- 5.2、发送纯HTML文本测试
- 5.2.1、测试代码编写
- 5.2.2、运行并查看结果
- 5.3、发送带图片的HTML测试
- 5.3.1、测试代码编写
- 5.3.2、运行并查看结果
- 5.4、发送带附件的测试
- 5.4.1、测试代码编写
- 5.5.2、运行并查看结果
前言
邮件发送,听着很神秘,然而对于Spring Boot来说,这个功能已被集成好,只需引入spring-boot-starter-mail依赖后,少量代码即可实现大部分邮件发送需求。
因发送邮件的方法只是在调用上,略有改动(比如,设置参数是否包含有ture),故在代码编排上,写在一个类中了,后面单元测试时分开测试即可。
¥¥¥¥¥具体操作步骤如下¥¥¥¥¥
一、创建Spring boot工程后,在pom.xml中添加依赖
1.1、方式一,新建工程时,在IO选项勾选邮件依赖
勾选后,spring-boot-starter-mail 依赖会被自动引入到pom.xml中
1.2、方式二,手动在pom.xml中添加依赖
引入:mail核心依赖
<dependencies> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-mail</artifactId> | |
</dependency> | |
</dependencies> |
其他相关依赖,可以酌情引入,需要注意的是,如果在项目中,无法自动导入依赖包,则很可能是下面的某个依赖,你没有引入,引入后鼠标右键pom.xml-->Maven-->Reload Project,就可以了。
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter</artifactId> | |
<exclusions> | |
<!--不使用默认的 logback日志,使用下面的logj2--> | |
<exclusion> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-logging</artifactId> | |
</exclusion> | |
</exclusions> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-logj2</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-web</artifactId> | |
<!-- 移除掉默认支持的 Tomcat --> | |
<exclusions> | |
<exclusion> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-tomcat</artifactId> | |
</exclusion> | |
</exclusions> | |
</dependency> | |
<!-- 添加 Undertow 容器 --> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-undertow</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-test</artifactId> | |
<scope>test</scope> | |
</dependency> | |
<!-- aop 依赖 --> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-aop</artifactId> | |
</dependency> | |
<!-- 用于日志切面中,以 gson 格式打印出入参 --> | |
<dependency> | |
<groupId>com.google.code.gson</groupId> | |
<artifactId>gson</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.projectlombok</groupId> | |
<artifactId>lombok</artifactId> | |
<version>.18.24</version> | |
</dependency> | |
<!-- 引入DevTools热部署 --> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-devtools</artifactId> | |
<scope>runtime</scope> | |
<optional>true</optional> | |
</dependency> |
二、在工程resource目录下创建application.properties文件,并添加相关配置
注意:下面的邮箱地址,是你自己的邮箱(作为邮件的发送者);密码是对应邮箱的登录密码或授权码,授权码在下方会有详细介绍,本文以163邮箱为例!
发送邮件的服务器, | |
QQ 邮件:smtp.qq.com | |
如果是邮箱,变更为“smtp.163.com”即可 | |
spring.mail.host=smtp..com | |
你的邮箱地址 | |
spring.mail.username=@163.com | |
授权码,或邮箱登录密码 | |
spring.mail.password= | |
true为开启,false不开启 | 是否开启验证|
spring.mail.properties.mail.smtp.auth=true | |
true开启,false不开启 | 通讯是否加密,|
spring.mail.properties.mail.smtp.starttls.enable=true | |
true开启,false不开启 | 是否必须通过使用加密通讯进行通讯,|
spring.mail.properties.mail.smtp.starttls.required=true |
提示:如果你想使用application.yml配置文件,则格式如下
spring: | |
mail: | |
host: smtp.qq.com #发送邮件的服务器 | |
username: 你的邮箱地址 | |
password: 授权码,或邮箱密码 | |
properties.mail.smtp.auth: true | |
properties.mail.smtp.starttls.enable: true | |
default-encoding: utf- |
三、关于授权码
如果使用的是 163 邮箱,或者 Gmail 邮箱,直接使用密码就可以了,如果使用的是 QQ 邮箱,则需要先获取授权码。
3.1、什么是 QQ 邮箱授权码
官方解释如下图所示
3.2、如何获取QQ授权码
3.2.1、登录 QQ 邮箱
3.2.2、点击设置,再点击页签中的“账户”
3.2.3、跳转页面后,点击账户,将页面往下拖动,您会看到,授权码的开启菜单
3.2.4、点击“开启”,验证成功过后,即可获取授权码
3.3、163邮箱的授权码
我的账号默认是开启的,如果你的没有开启,如下步骤操作
3.3.1、点击顶部页签的”"设置"按钮,进入POP3设置界面
3.3.2、开启服务,也可以重新生成授权码
3.4、 发送邮件所需要遵从的POP3/SMTP/IMAP三个协议的简述
SMTP(Simple Mail Transfer Protocol):简单邮件传输协议,用于发送电子邮件的传输协议。
POP3(Post Office Protocol - Version 3):用于接收电子邮件的标准协议。
IMAP(Internet Mail Access Protocol):互联网消息协议,是POP3的替代协议。
简而言之,SMTP是发邮件必须遵从的标准,POP3是接收邮件要遵从的标准,而IMAP是对POP3协议的升级,日常工作中,我们主要使用的是发邮件操作。
四、业务代码
4.1、新增MailService接口,并声明4个发送不同类型邮件的方法
注:入参多于3个的情况下,通常也会把入参封装为一个实体Bean,方便起见,这里就不封装了。
package com.example.demo.service; | |
/** | |
* @author xyp | |
* @create-10-07 12:57 | |
* @describe 邮件发送接口,定义发送不同类型邮件的方法 | |
*/ | |
public interface MailService { | |
/** | |
* 发送简单文本的邮件 | |
* @param to | |
* @param subject | |
* @param content | |
* @return | |
*/ | |
boolean sendSimpleText(String to, String subject, String content); | |
/** | |
* 发送 html 的邮件 | |
* @param to | |
* @param subject | |
* @param html | |
* @return | |
*/ | |
boolean sendWithHtml(String to, String subject, String html); | |
/** | |
* 发送带有图片的 html 的邮件 | |
* @param to | |
* @param subject | |
* @param html | |
* @param cids | |
* @param filePaths | |
* @return | |
*/ | |
boolean sendWithImageHtml(String to, String subject, String html, String[] cids, String[] filePaths); | |
/** | |
* 发送带有附件的邮件 | |
* @param to | |
* @param subject | |
* @param content | |
* @param filePaths | |
* @return | |
*/ | |
boolean sendWithWithEnclosure(String to, String subject, String content, String[] filePaths); | |
} | |
4.2、新增MailService接口的实现类MailServiceImpl
package com.example.demo.service.impl; | |
import com.example.demo.service.MailService; | |
import org.slfj.Logger; | |
import org.slfj.LoggerFactory; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.autoconfigure.mail.MailProperties; | |
import org.springframework.core.io.FileSystemResource; | |
import org.springframework.mail.SimpleMailMessage; | |
import org.springframework.mail.javamail.JavaMailSender; | |
import org.springframework.mail.javamail.MimeMessageHelper; | |
import javax.mail.internet.MimeMessage; | |
/** | |
* @author xyp | |
* @create-10-07 13:01 | |
* @describe | |
*/ | |
//没有这个注解,发送邮件时可能会引发空指针异常 | |
public class MailServiceImpl implements MailService { | |
private final static Logger logger = LoggerFactory.getLogger(MailServiceImpl.class); | |
private MailProperties mailProperties; | |
private JavaMailSender javaMailSender; | |
public boolean sendSimpleText(String to, String subject, String content) { | |
logger.info("## Ready to send mail ..."); | |
SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); | |
// 邮件发送来源 | |
simpleMailMessage.setFrom(mailProperties.getUsername()); | |
// 邮件发送目标 | |
simpleMailMessage.setTo(to); | |
// 设置标题 | |
simpleMailMessage.setSubject(subject); | |
// 设置内容 | |
simpleMailMessage.setText(content); | |
try { | |
// 发送 | |
javaMailSender.send(simpleMailMessage); | |
logger.info("## Send the mail success ..."); | |
} catch (Exception e) { | |
logger.error("Send mail error: ", e); | |
return false; | |
} | |
return true; | |
} | |
public boolean sendWithHtml(String to, String subject, String html) { | |
logger.info("## Ready to send mail ..."); | |
MimeMessage mimeMessage = javaMailSender.createMimeMessage(); | |
MimeMessageHelper mimeMessageHelper = null; | |
try { | |
mimeMessageHelper = new MimeMessageHelper(mimeMessage, true); | |
// 邮件发送来源 | |
mimeMessageHelper.setFrom(mailProperties.getUsername()); | |
// 邮件发送目标 | |
mimeMessageHelper.setTo(to); | |
// 设置标题 | |
mimeMessageHelper.setSubject(subject); | |
// 设置内容,并设置内容 html 格式为 true | |
mimeMessageHelper.setText(html, true); | |
javaMailSender.send(mimeMessage); | |
logger.info("## Send the mail with html success ..."); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
logger.error("Send html mail error: ", e); | |
return false; | |
} | |
return true; | |
} | |
public boolean sendWithImageHtml(String to, String subject, String html, String[] cids, String[] filePaths) { | |
logger.info("## Ready to send mail ..."); | |
MimeMessage mimeMessage = javaMailSender.createMimeMessage(); | |
MimeMessageHelper mimeMessageHelper = null; | |
try { | |
mimeMessageHelper = new MimeMessageHelper(mimeMessage, true); | |
// 邮件发送来源 | |
mimeMessageHelper.setFrom(mailProperties.getUsername()); | |
// 邮件发送目标 | |
mimeMessageHelper.setTo(to); | |
// 设置标题 | |
mimeMessageHelper.setSubject(subject); | |
// 设置内容,并设置内容 html 格式为 true | |
mimeMessageHelper.setText(html, true); | |
// 设置 html 中内联的图片 | |
for (int i =; i < cids.length; i++) { | |
FileSystemResource file = new FileSystemResource(filePaths[i]); | |
// addInline() 方法 cid 需要 html 中的 cid (Content ID) 对应,才能设置图片成功, | |
// 具体可以参见,下面.3.3 单元测试的参数设置 | |
mimeMessageHelper.addInline(cids[i], file); | |
} | |
javaMailSender.send(mimeMessage); | |
logger.info("## Send the mail with image success ..."); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
logger.error("Send html mail error: ", e); | |
return false; | |
} | |
return true; | |
} | |
public boolean sendWithWithEnclosure(String to, String subject, String content, String[] filePaths) { | |
logger.info("## Ready to send mail ..."); | |
MimeMessage mimeMessage = javaMailSender.createMimeMessage(); | |
MimeMessageHelper mimeMessageHelper = null; | |
try { | |
// 设置为true,代表要支持附件 | |
mimeMessageHelper = new MimeMessageHelper(mimeMessage, true); | |
// 邮件发送来源 | |
mimeMessageHelper.setFrom(mailProperties.getUsername()); | |
// 邮件发送目标 | |
mimeMessageHelper.setTo(to); | |
// 设置标题 | |
mimeMessageHelper.setSubject(subject); | |
// 设置内容 | |
mimeMessageHelper.setText(content); | |
// 添加附件 | |
for (int i =; i < filePaths.length; i++) { | |
FileSystemResource file = new FileSystemResource(filePaths[i]); | |
String attachementFileName = "附件" + (i +)+"_"+ file.getFilename(); | |
mimeMessageHelper.addAttachment(attachementFileName, file); | |
} | |
javaMailSender.send(mimeMessage); | |
logger.info("## Send the mail with enclosure success ..."); | |
} catch (Exception e) { | |
logger.error("Send html mail error: ", e); | |
return false; | |
} | |
return true; | |
} | |
} | |
4.3、工程目录结构查看
如下图所示,核心的几个类,都被红色的框,框选着的,其他一些package与本项目无关。
五、单元测试,查看成果
准备工作
1、在pom中引入单元测试的依赖
<dependency> | |
<groupId>junit</groupId> | |
<artifactId>junit</artifactId> | |
<version>.9</version> | |
<scope>test</scope> | |
</dependency> |
需要注意的是,在单元测试类中,所有与单元测试类相关的类,都来自于junit,不要使用默认的。
2、在test单元测试目录,新建SpringBootMailTest.java类
5.1、发送纯文本邮件的测试
5.1.1、测试代码编写
package com.example.demo; | |
import com.example.demo.service.MailService; | |
import org.junit.Assert;//注意这个包是junit的,不是自带的 | |
import org.junit.jupiter.api.Test; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.test.context.SpringBootTest; | |
/** | |
* @author xyp | |
* @create-10-07 15:07 | |
* @describe | |
*/ | |
public class SpringBootMailTest { | |
false) | (required =|
private MailService mailService; | |
public void sendSimpleText(){ | |
String to="@qq.com"; | |
String title="标题:简单的文本发送测试"; | |
String content="简单的文本"; | |
Assert.assertTrue(mailService.sendSimpleText(to,title,content)); | |
} | |
} | |
5.1.2、运行查看,报错小插曲
初次运行,可能会报如下错误
经百般百度后,得知需要给MailServicel的实现类MailServiceImpl添加@Component注解
5.1.3、给MailServiceImpl添加@Component注解后,再试
至此,第一个纯文本邮件发送,测试成功!
5.2、发送纯HTML文本测试
5.2.1、测试代码编写
public void sendHtml(){ | |
String to="@qq.com"; | |
String title="标题:Html文本发送测试"; | |
String htmlContent="<html><body><h>欢迎来到 Spring boot 的世界</h1></body></html>"; | |
Assert.assertTrue(mailService.sendWithHtml(to,title,htmlContent)); | |
} |
5.2.2、运行并查看结果
运行后,收到邮件提示
进入邮箱,并打开
至此,第二个发送Html的测试,测试成功!
5.3、发送带图片的HTML测试
5.3.1、测试代码编写
public void sendWithImageHtml(){ | |
String to="@qq.com"; | |
String title="标题:带有图片的Html发送测试"; | |
String htmlContent="<html><body>" + | |
"<h>欢迎来到 Spring boot 的世界</h1>" + | |
"<image width='' height='60' src='cid:test1'>图片1 </image>" +//cid:是约定好的固定格式,只需要修改后面的变量 | |
"<image width='' height='60' src='cid:test2'>图片1 </image>" + | |
"</body></html>"; | |
//数组中的cid要和上面html中image中的cid一致,否则图片将设置失败 | |
String[] cids=new String[]{"test","test2"}; | |
String[] filePaths=new String[]{ | |
"D:\\Documents\\ioc\\MyIco\\pao.ico", | |
"D:\\Documents\\ioc\\MyIco\\xiang.ico" | |
}; | |
Assertions.assertTrue(mailService.sendWithImageHtml(to,title,htmlContent,cids,filePaths)); | |
} |
5.3.2、运行并查看结果
电脑右下角有邮件提醒
进入邮箱,查看邮件
至此,第三个发送带图片的Html邮件,测试成功!
5.4、发送带附件的测试
5.4.1、测试代码编写
public void sendWithWithEnclosure(){ | |
String to="@qq.com"; | |
String title="标题:带有附件的邮件发送测试"; | |
String content="欢迎来到 Spring boot 的世界"; | |
String[] filePaths=new String[]{ | |
"D:\\Documents\\ioc\\MyIco\\pao.ico", | |
"D:\\Documents\\ioc\\MyIco\\expect.45.tar.gz" | |
}; | |
Assert.assertTrue(mailService.sendWithWithEnclosure(to,title,content,filePaths)); | |
} |
5.5.2、运行并查看结果
注:刚开始附件,测试的是图片,为了测试压缩包是否能被当做附件发送,又新增了压缩包的测试。
电脑右下角弹出新邮件提示:
进入收件箱查看邮件
经测试,下载后,附件可以正常打开。
至此,各个案例都演示完毕!
案例虽然简单,总的来说,这个几个方法还是有一定的局限性,不过它为我们今后整合一个功能更齐全的邮件发送功能,带来的指引和启发,已经够用了。
注意下面几行点参数中true的含义:
//纯文本邮件,不用带任何参数 | |
SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); | |
simpleMailMessage .setText(contentText); | |
// 邮件内容如果是html和图片,则下面两处都需要设置为true | |
mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);//如果是仅支持附件,这一处设置为true即可 | |
mimeMessageHelper.setText(html, true); |
注意:连续发内容相同的邮件,会被判定为垃圾邮件,可能会被拦截。