Springboot集成发送邮件功能
1、导入依赖
springboot 集成了发送邮件功能的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2、配置文件
spring:
mail:
# 配置模板文件
templates: 'templates.html'
# 配置 SMTP 服务器地址
host: smtp.qq.com
# 发送者邮箱
username: 239XXXX9@qq.com
# 配置密码,注意不是真正的密码,而是刚刚申请到的授权码
password: gplXXXXche
# 端口号 456 或 587
port: 587
# 默认的邮件编码为 UTF-8
default-encoding: UTF-8
# 配置 SSL 加密工厂
properties:
mail:
smtp:
socketFactoryClass: javax.net.ssl.SSLSocketFactory
# 表示开启 DEBUG 模式,邮件发送过程日志会在控制台打印出来,方便排查错误
debug: true
- 注意:
使用 Nacos 时,使用 @Value 注解来获取配置中的配置信息,但不能实现动态。
使用 @NacosValue 和 @NacosProperySource 注解还是获取不到时
解决办法:
//配置文件上下文,使用该类来实现动态获取配置中心的配置文件信息
@Autowired
private ConfigurableApplicationContext configurableApplicationContext;
// 获得配置文件中配置的值
configurableApplicationContext.getEnvironment().getProperty("中心配置的属性值");
- 模板文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div class="info-top" style="padding: 15px 25px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
background: burlywood;
color: crimson;
line-height: 10px;">
<div style="font-size: 18px" ><b>{0}</b></div>
</div>
<div class="info-wrap" style="border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
border:1px solid #ddd;
overflow: hidden;
padding: 15px 15px 20px;">
<div class="tips" style="padding:15px;">
<p style=" list-style: 160%; margin: 10px 0;"><h3>Hi</h3>以下信息请您仔细阅读:</p>
<p style=" list-style: 160%; margin: 10px 0;"> {1}</p>
</div>
</div>
</body>
</html>
3、代码实现
MailService接口
package com.its.server.domain.meet.service;
import javax.mail.MessagingException;
import java.util.Map;
/**
* 邮件服务
*/
public interface MailService {
/**
* 普通邮件发送
* @param tos 发送邮件地址列表
* @param subject 标题
* @param contentText 正文信息
*/
void sendSimpleMail(String[] tos,String subject,String contentText);
/**
* 带抄送人普通邮件发送
* @param tos 发送邮件地址列表
* @param cc 邮件抄送人列表
* @param bcc 隐秘抄送人列表
* @param subject 标题
* @param contentText 正文信息
*/
void sendSimpleMailCc(String[] tos, String[] cc, String[] bcc, String subject, String contentText);
/**
* 模板邮件发送
* @param tos 发送邮件地址列表
* @param subject 标题
* @param contentTitle 正文标题
* @param contentText 正文信息
*/
void sendMail(String[] tos,String subject,String contentTitle,String contentText) throws MessagingException;
/**
* 带抄送人模板邮件发送
* @param tos 发送邮件地址列表
* @param cc 邮件抄送人列表
* @param bcc 隐秘抄送人列表
* @param subject 标题
* @param contentTitle 正文标题
* @param contentText 正文信息
*/
void sendMailCc(String[] tos, String[] cc, String[] bcc,String subject,String contentTitle,String contentText) throws MessagingException;
/**
* 带附件的邮件发送
* @param tos 发送邮件地址列表
* @param subject 标题
* @param contentTitle 正文标题
* @param contentText 正文信息
* @param attachFileMap 附件 key: 文件名称(后缀要加上,eg:资料.xlsx) value: 文件位置(eg:/Desktop/测试数据 2.xlsx)
*/
void sendAttachFileMail(String[] tos, String subject, String contentTitle, String contentText, Map<String ,String> attachFileMap) throws MessagingException;
/**
* 带抄送人带附件的邮件发送
* @param tos 发送邮件地址列表
* @param cc 邮件抄送人列表
* @param bcc 隐秘抄送人列表
* @param subject 标题
* @param contentTitle 正文标题
* @param contentText 正文信息
* @param attachFileMap 附件 key: 文件名称(后缀要加上,eg:资料.xlsx) value: 文件位置(eg:/Desktop/测试数据 2.xlsx)
*/
void sendAttachFileMailCc(String[] tos,String [] cc,String [] bcc,String subject,String contentTitle,String contentText, Map<String ,String> attachFileMap) throws MessagingException;
}
MailService接口实现类 MailServiceImpl
package com.its.server.domain.meet.service.impl;
import com.its.server.domain.meet.service.MailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.*;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Map;
/**
* 邮件服务
*
* @author z
* @date 2022-02-07 15:47
*/
@Service
@Slf4j
@RefreshScope
public class MailServiceImpl implements MailService {
@Resource
private JavaMailSender mailSender;
@Autowired
private ConfigurableApplicationContext configurableApplicationContext;
private static final String FILENAME="spring.mail.templates";
private static final String FROM="spring.mail.username";
/**
* 读取替换html文件模板中的信息
* @param title 正文标题
* @param contentText 正文信息
* @return 替换后文件模板中的信息
*/
public String scopeTemplate(String title ,String contentText){
InputStream inputStream=ClassLoader.getSystemResourceAsStream(configurableApplicationContext.getEnvironment().getProperty(FILENAME));
BufferedReader fileReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer buffer = new StringBuffer();
String line="";
try{
while((line = fileReader.readLine())!= null){
buffer.append(line);
}
}catch(IOException e){
log.info("read template:{}",e);
}finally{
if(inputStream != null){
try{
inputStream.close();
}catch (Exception e){
log.info("{}",e);
}
}
if (fileReader != null){
try{
fileReader.close();
}catch(Exception e){
log.info("{}",e);
}
}
}
return MessageFormat.format(buffer.toString(),title,contentText);
}
/**
* 普通邮件发送
* @param tos 发送邮件地址列表
* @param subject 标题
* @param contentText 正文信息
*/
@Override
public void sendSimpleMail(String[] tos,String subject,String contentText) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
message.setTo(tos);
message.setSubject(subject);
message.setSentDate(new Date());
message.setText(contentText);
mailSender.send(message);
}
/**
* 带抄送人普通邮件发送
* @param tos 发送邮件地址列表
* @param cc 邮件抄送人列表
* @param bcc 隐秘抄送人列表
* @param subject 标题
* @param contentText 正文信息
*/
@Override
public void sendSimpleMailCc(String[] tos, String[] cc, String[] bcc, String subject, String contentText) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
message.setTo(tos);
message.setCc(cc);
message.setBcc(bcc);
message.setSubject(subject);
message.setSentDate(new Date());
message.setText(contentText);
mailSender.send(message);
}
/**
* 模板邮件发送
* @param tos 发送邮件地址列表
* @param subject 标题
* @param contentTitle 正文标题
* @param contentText 正文信息
*/
@Override
public void sendMail(String[] tos, String subject, String contentTitle, String contentText) throws MessagingException {
MimeMessage mimeMessage=mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage);
helper.setTo(tos);
helper.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
helper.setSubject(subject);
helper.setSentDate(new Date());
helper.setText(scopeTemplate(contentTitle,contentText),true);
mailSender.send(mimeMessage);
}
/**
* 带抄送人模板邮件发送
* @param tos 发送邮件地址列表
* @param cc 邮件抄送人列表
* @param bcc 隐秘抄送人列表
* @param subject 标题
* @param contentTitle 正文标题
* @param contentText 正文信息
*/
@Override
public void sendMailCc(String[] tos, String[] cc, String[] bcc, String subject, String contentTitle, String contentText) throws MessagingException {
MimeMessage mimeMessage=mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage);
helper.setTo(tos);
helper.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
helper.setCc(cc);
helper.setBcc(bcc);
helper.setSubject(subject);
helper.setSentDate(new Date());
helper.setText(scopeTemplate(contentTitle,contentText),true);
mailSender.send(mimeMessage);
}
/**
* 带附件的邮件发送
* @param tos 发送邮件地址列表
* @param subject 标题
* @param contentTitle 正文标题
* @param contentText 正文信息
* @param attachFileMap 附件 key: 文件名称(后缀要加上,eg:资料.xlsx) value: 文件位置(eg:/Desktop/测试数据 2.xlsx)
*/
@Override
public void sendAttachFileMail(String[] tos, String subject, String contentTitle, String contentText, Map<String ,String> attachFileMap) throws MessagingException {
MimeMessage mimeMessage=mailSender.createMimeMessage();
// true表示构建一个可以带附件的邮件对象
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setTo(tos);
helper.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
helper.setSubject(subject);
helper.setSentDate(new Date());
helper.setText(scopeTemplate(contentTitle,contentText),true);
for (String key : attachFileMap.keySet()) {
// 第一个参数是自定义的名称,后缀需要加上,第二个参数是文件的位置
helper.addAttachment(key,new File(attachFileMap.get(key)));
}
mailSender.send(mimeMessage);
}
/**
* 带抄送人带附件的邮件发送
* @param tos 发送邮件地址列表
* @param cc 邮件抄送人列表
* @param bcc 隐秘抄送人列表
* @param subject 标题
* @param contentTitle 正文标题
* @param contentText 正文信息
* @param attachFileMap 附件 key: 文件名称(后缀要加上,eg:资料.xlsx) value: 文件位置(eg:/Desktop/测试数据 2.xlsx)
*/
@Override
public void sendAttachFileMailCc(String[] tos, String[] cc, String[] bcc, String subject, String contentTitle, String contentText,Map<String ,String> attachFileMap) throws MessagingException {
MimeMessage mimeMessage=mailSender.createMimeMessage();
// true表示构建一个可以带附件的邮件对象
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setTo(tos);
helper.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
helper.setCc(cc);
helper.setBcc(bcc);
helper.setSubject(subject);
helper.setSentDate(new Date());
helper.setText(scopeTemplate(contentTitle,contentText),true);
for (String key : attachFileMap.keySet()) {
// 第一个参数是自定义的名称,后缀需要加上,第二个参数是文件的位置
helper.addAttachment(key,new File(attachFileMap.get(key)));
}
mailSender.send(mimeMessage);
}
}
测试接口
package com.its.server.domain.meet.web;
import com.its.server.domain.meet.service.impl.MailServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.mail.MessagingException;
import java.util.HashMap;
import java.util.Map;
/**
* 邮件测试
*
* @author z
* @date 2022-02-07 17:45
*/
@Api("邮件测试")
@RestController
@RequestMapping("/mailTest")
@Slf4j
public class MailTestController {
@Autowired
private MailServiceImpl mailService;
@ApiOperation("测试普通邮件")
@GetMapping("/sendMail")
public String sendMail(){
try {
mailService.sendMail(new String[]{"303XXXX44@qq.com"},"test","this is a test" ,"这是个测试邮件");
} catch (MessagingException e) {
log.info("{}",e);
}
return "发送成功";
}
@ApiOperation("测试带附件邮件")
@GetMapping("/sendAttachFileMail")
public String sendAttachFileMail(){
try {
Map<String ,String> map=new HashMap<>();
map.put("aaa.png","C:\\Users\\Desktop\\aa.png");
map.put("aab.png","C:\\Users\\Desktop\\aa.png");
mailService.sendAttachFileMail(new String[]{"303XXXX44@qq.com"},"这是测试邮件","test","this is a test",map);
} catch (MessagingException e) {
log.info("{}",e);
}
return "发送成功";
}
}
4、更多
- 发送带图片资源的邮件
图片资源和附件有什么区别呢?图片资源是放在邮件正文中的,即一打开邮件,就能看到图片。但是一般来说,不建议使用这种方式,一些公司会对邮件内容的大小有限制(因为这种方式是将图片一起发送的)。
/**
* 正文中带图片的邮件
* @throws MessagingException
*/
@Test
public void sendImgResMail() throws MessagingException {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setSubject("这是一封测试邮件");
helper.setFrom("79*****39@qq.com");
helper.setTo("10****6@qq.com");
//helper.setCc("37xxxxx37@qq.com");
//helper.setBcc("14xxxxx098@qq.com");
helper.setSentDate(new Date());
// src='cid:p01' 占位符写法 ,第二个参数true表示这是一个html文本
helper.setText("<p>hello 大家好,这是一封测试邮件,这封邮件包含两种图片,分别如下</p><p>第一张图片:</p><img src='cid:p01'/><p>第二张图片:</p><img src='cid:p02'/>",true);
// 第一个参数指的是html中占位符的名字,第二个参数就是文件的位置
helper.addInline("p01",new FileSystemResource(new File("/Users/gamedev/Desktop/压缩.jpeg")));
helper.addInline("p02",new FileSystemResource(new File("/Users/gamedev/Desktop/瑞文.jpg")));
javaMailSender.send(mimeMessage);
}
效果
在公司实际开发中,第一种和第三种都不是使用最多的邮件发送方案。因为正常来说,邮件的内容都是比较的丰富的,所以大部分邮件都是通过 HTML 来呈现的,如果直接拼接 HTML 字符串,这样以后不好维护,为了解决这个问题,一般邮件发送,都会有相应的邮件模板。
- 使用 Thymeleaf 作邮件模板
推荐在 Spring Boot 中使用 Thymeleaf 来构建邮件模板。因为 Thymeleaf 的自动化配置提供了一个 TemplateEngine,通过 TemplateEngine 可以方便的将 Thymeleaf 模板渲染为 HTML ,同时,Thymeleaf 的自动化配置在这里是继续有效的。
引入 Thymeleaf 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
创建Thymeleaf模板:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>hello 欢迎加入 xxx 大家庭,您的入职信息如下:</p>
<table border="1">
<tr>
<td>姓名</td>
<td th:text="${username}"></td>
</tr>
<tr>
<td>工号</td>
<td th:text="${num}"></td>
</tr>
<tr>
<td>薪水</td>
<td th:text="${salary}"></td>
</tr>
</table>
<div style="color: #ff1a0e">一起努力创造辉煌</div>
</body>
</html>
发送邮件:
@Autowired
TemplateEngine templateEngine;
@Test
public void sendThymeleafMail() throws MessagingException {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setSubject("这是一封测试邮件");
helper.setFrom("790933839@qq.com");
helper.setTo("1032065316@qq.com");
// helper.setCc("37xxxxx37@qq.com");
// helper.setBcc("14xxxxx098@qq.com");
helper.setSentDate(new Date());
// 这里引入的是Template的Context
Context context = new Context();
// 设置模板中的变量
context.setVariable("username", "javaboy");
context.setVariable("num","000001");
context.setVariable("salary", "99999");
// 第一个参数为模板的名称
String process = templateEngine.process("hello.html", context);
// 第二个参数true表示这是一个html文本
helper.setText(process,true);
javaMailSender.send(mimeMessage);
}
效果:
参考链接: