SpringBoot整合邮箱发送邮件
1. SpringBoot整合邮箱发送邮件
在开发中,经常会碰到email邮件发送的场景,如发送验证码,向客户发送邮件等等。
今天,本项目将讲解通过 SpringBoot 发送 email 邮件(普通文本邮件 ,HTML内容板式邮件 ,包含静态资源邮件,以及带附件邮件)。
2. 项目配置
2.1 创建SpringBoot项目
项目结构,简单测试没有分包
2.2 pom文件导入需要的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--邮件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
2.3 邮箱smtp配置
因为各大邮件都有其对应安全系统,不是项目中想用就可以用的,我们必须要拿到其对应的客户端授权码才行,拿到授权码,在项目中配置SMTP服务协议以及主机配置账户,才可以在项目中使用各大邮件
运营商进行发送邮件了。
什么是SMTP?SMTP全称为Simple Mail Transfer Protocol(简单邮件传输协议),它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP认证要求必须提供账号和密码
才能登陆服务器,其设计目的在于避免用户受到垃圾邮件的侵扰。
什么是IMAP?IMAP全称为Internet Message Access Protocol(互联网邮件访问协议),IMAP允许从邮件服务器上获取邮件的信息、下载邮件等。IMAP与POP类似,都是一种邮件获取协议。
什么是POP3?POP3全称为Post Office Protocol 3(邮局协议),POP3支持客户端远程管理服务器端的邮件。POP3常用于“离线”邮件处理,即允许客户端下载服务器邮件,然后服务器上的邮件将会被删
除。目前很多POP3的邮件服务器只提供下载邮件功能,服务器本身并不删除邮件,这种属于改进版的POP3协议。
获取客户端授权码过程,由于国内使用163邮箱以及qq邮箱较多,仅展示163邮箱获取客户端授权码的步骤(qq的类似)
如果没有开启,选择开启发送验证码即可,我的是已经开过了(如果忘记授权码,重新发送短信生成)
2.4 配置yml文件
在拿到授权码后,就可以在我们Springboot工程中的配置文件 aplication.yml 或者properties文件中配置了
server:
port: 8091
# 邮件配置
spring:
mail:
# 这里换成自己的邮箱类型 例如smtp.163.com, smtp.qq.com
host: smtp.163.com
# 发送邮件服务协议
protocol: smtp
# 编码集
default-encoding: UTF-8
# 发送邮件的账户
username: liy22222@163.com
# 授权码(自己邮箱的授权码)
password: AWYFJEIJSDFJASSDDDVOC
test-connection: true
properties:
mail:
smtp:
# 表示SMTP发送邮件,需要进行身份验证
auth: true
starttls:
enable: true
required: true
2.5 创建接收消息的对象
package com.liyh;
import lombok.*;
@Data
public class MessageInfo {
/**
* 收件人邮箱
**/
private String receiver;
/**
* 一对多群发收件人邮箱
**/
private String receivers;
/**
* 邮件标题
**/
private String subject;
/**
* 邮件内容
**/
private String content;
/**
* 图片路径
**/
private String imgPath;
/**
* 文件路径
**/
private String filePath1;
/**
* 文件路径
**/
private String filePath2;
/**
* 发件人姓名
**/
private String fromName;
/**
* 收件人姓名
**/
private String receiverName;
}
2.6 Html邮箱模板
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8"/>
<title>邮件通知</title>
</head>
<body>
<div>
<includetail>
<div align="center">
<div class="open_email" style="margin-left: 8px; margin-top: 8px; margin-bottom: 8px; margin-right: 8px;">
<div>
<br>
<span class="genEmailContent">
<div id="cTMail-Wrap"
style="word-break: break-all;box-sizing:border-box;text-align:center;min-width:320px; max-width:660px; border:1px solid #f6f6f6; background-color:#f7f8fa; margin:auto; padding:20px 0 30px; font-family:'helvetica neue',PingFangSC-Light,arial,'hiragino sans gb','microsoft yahei ui','microsoft yahei',simsun,sans-serif">
<div class="main-content" style="">
<table style="width:100%;font-weight:300;margin-bottom:10px;border-collapse:collapse">
<tbody>
<tr style="font-weight:300">
<td style="width:3%;max-width:30px;"></td>
<td style="max-width:600px;">
<div id="cTMail-logo" style="width:92px; height:25px;">
<a href="">
<img border="0" src="https://image.youyoushop.work/yahoo/zhenyu.png"
style="height:50px;display:block">
</a>
</div>
<p style="height:2px;background-color: #00a4ff;border: 0;font-size:0;padding:0;width:100%;margin-top:20px;"></p>
<div id="cTMail-inner" style="background-color:#fff; padding:23px 0 20px;box-shadow: 0px 1px 1px 0px rgba(122, 55, 55, 0.2);text-align:left;">
<table style="width:100%;font-weight:300;margin-bottom:10px;border-collapse:collapse;text-align:left;">
<tbody>
<tr style="font-weight:300">
<td style="width:3.2%;max-width:30px;"></td>
<td style="max-width:480px;text-align:left;">
<h1 id="cTMail-title" style="font-size: 20px; line-height: 36px; margin: 0px 0px 22px;">
邮件测试平台
</h1>
<p id="cTMail-receiverName" style="font-size:14px;color:#333; line-height:24px; margin:0;">
尊敬的<span style="font-weight: bold;"> ${receiverName} </span>用户,您好!
</p>
<p class="cTMail-content" style="line-height: 24px; margin: 6px 0px 0px; overflow-wrap: break-word; word-break: break-all;">
<span style="color: rgb(51, 51, 51); font-size: 14px;">
由<span style="font-weight: bold;"> ${fromName} </span>发送的邮件请及时处理。消息内容如下:<br/>
</span>
</p>
<p class="cTMail-content" style="line-height: 24px; margin: 6px 0px 0px; overflow-wrap: break-word; word-break: break-all;">
<span style="color: rgb(51, 51, 51); font-size: 14px;">
<span style="font-weight: bold;">${content}</span>
</span>
</p>
<dl style="font-size: 14px; color: rgb(51, 51, 51); line-height: 18px;">
<dd style="margin: 0px 0px 6px; padding: 0px; font-size: 12px; line-height: 22px;">
<p id="cTMail-sender" style="font-size: 14px; line-height: 26px; word-wrap: break-word; word-break: break-all; margin-top: 32px;">
发送时间
<br>
<strong>${sendTime}</strong>
</p>
</dd>
</dl>
</td>
<td style="width:3.2%;max-width:30px;"></td>
</tr>
</tbody>
</table>
</div>
</td>
<td style="width:3%;max-width:30px;"></td>
</tr>
</tbody>
</table>
</div>
</div>
</span>
</div>
</div>
</div>
</includetail>
</div>
</body>
</html>
2.7 创建Spring工具类
package com.liyh;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* spring工具类 方便在非spring管理环境中获取bean
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware {
/**
* Spring应用上下文环境
*/
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringUtils.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringUtils.applicationContext = applicationContext;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T) beanFactory.getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*/
public static <T> T getBean(Class<T> clz) throws BeansException {
T result = (T) beanFactory.getBean(clz);
return result;
}
}
2.8 创建 MailUtil 工具类
package com.liyh;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
@Component
public class MailUtil {
/**
* 从配置文件中注入发件人的姓名
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* Spring官方提供的集成邮件服务的实现类,目前是Java后端发送邮件和集成邮件服务的主流工具。
*/
@Autowired
private JavaMailSender mailSender;
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
}
2.9 创建 MailUtils 工具类
package com.liyh;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* 统一邮件发送工具类
*
* @author Liyh
* @date 2022/03/28
*/
@Component
public class MailUtils {
/**
* 从配置文件中注入是否需要身份验证
*/
@Value("${spring.mail.properties.mail.smtp.auth}")
private String auth;
/**
* 从配置文件中注入邮箱类型
*/
@Value("${spring.mail.host}")
private String emailHost;
/**
* 从配置文件中注入发件人
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* 从配置文件中注入授权码
*/
@Value("${spring.mail.password}")
private String password;
}
2.10 创建 SendMailController
package com.liyh;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 发送邮件接口
*/
@RestController
@RequestMapping("/mail")
public class SendMailController {
}
3. 第一种方式可以配置模板使用
下面开始 SpringBoot 项目中发送邮件的代码编写
其实也非常简单 ,SpringBoot已经给我们邮件发送进行了非常好的整合了,我们只需要注入邮件发送接口 调用其中的方法,就能轻松而愉悦的进行邮件发送了!
3.1 发送文本邮件
3.1.1 创建 MailUtil 工具类,添加代码
/**
* 发送文本邮件
*
* @param receiver 收件人
* @param subject 邮件标题
* @param content 邮件内容
*/
public String sendSimpleMail(String receiver, String subject, String content) {
try {
SimpleMailMessage message = new SimpleMailMessage();
// 发件人
message.setFrom(fromEmail);
// 收件人
message.setTo(receiver);
// 邮件标题
message.setSubject(subject);
// 邮件内容
message.setText(content);
mailSender.send(message);
return "发送文本邮件成功";
} catch (MailException e) {
e.printStackTrace();
return "发送文本邮件失败!!!";
}
}
3.1.2 添加访问接口
/**
* 发送文本邮件
*
* @param messageInfo 邮件信息
*/
@PostMapping("sendSimpleMail")
public String sendSimpleMail(MessageInfo messageInfo) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
return mailUtil.sendSimpleMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent());
}
3.1.3 测试接口
3.2 发送带附件的邮件
3.2.1 在MailUtil工具类添加代码
/**
* 发送带附件的邮件
*
* @param receiver 收件人
* @param subject 邮件标题
* @param content 邮件内容
* @param filePath 文件路径
* @param imgPath 图片路径
* @param multipartFile 上传的文件
*/
public String sendAttachmentsMail(String receiver, String subject, String content, String filePath, String imgPath, MultipartFile multipartFile) {
try {
MimeMessage message = mailSender.createMimeMessage();
// 要带附件第二个参数设为true
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 发件人
helper.setFrom(fromEmail);
// 收件人
helper.setTo(receiver);
// 邮件标题
helper.setSubject(subject);
// 邮件内容,第二个参数:格式是否为html
helper.setText(content, true);
// 添加文件附件1
FileSystemResource file = new FileSystemResource(new File(filePath));
helper.addAttachment(file.getFilename(), file);
// 添加文件附件2
FileSystemResource files = new FileSystemResource(multipartFileToFile(multipartFile));
helper.addAttachment(files.getFilename(), files);
// 添加图片附件
FileSystemResource image = new FileSystemResource(new File(imgPath));
helper.addAttachment(image.getFilename(), image);
mailSender.send(message);
return "发送带附件的邮件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "发送带附件的邮件失败!!!";
}
}
3.2.2 在MailUtil工具类添加代码
/**
* 把 multiFile 转换为 file
*
* @param multiFile
* @return
*/
private File multipartFileToFile(MultipartFile multiFile) {
// 获取文件名
String fileName = multiFile.getOriginalFilename();
// 获取文件后缀
String prefix = fileName.substring(fileName.lastIndexOf("."));
// 若需要防止生成的临时文件重复,可以在文件名后添加随机码
try {
File file = File.createTempFile(fileName, prefix);
multiFile.transferTo(file);
return file;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
3.2.3 添加访问接口
/**
* 发送带附件的邮件
*
* @param messageInfo 邮件信息
* @param multipartFile 上传的文件
*/
@PostMapping("sendAttachmentsMail")
public String sendAttachmentsMail(MessageInfo messageInfo, MultipartFile multipartFile) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
// 发送带附件的邮件( 路径中的 \ 通常需要使用 \\, 如果是 / 就不需要使用转义了, \ 常用于本地,而/ 常用于网络连接地址 )
// D:\nacos1.2.1\bin\logs\access_log.2022-03-22.log
// C:/Users/Administrator/Pictures/1.jpg
return mailUtil.sendAttachmentsMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getFilePath1(), messageInfo.getImgPath(), multipartFile);
}
3.2.4 测试接口
3.3 发送模板邮件
3.3.1 在MailUtil工具类添加代码
/**
* 发送模板邮件
*
* @param receiver 收件人
* @param subject 邮件标题
* @param content 邮件内容
* @param fromName 发件人姓名
* @param receiverName 收件人姓名
* @return
*/
public String sendTemplateMail(String receiver, String subject, String content, String fromName, String receiverName) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 获得模板
Template template = null;
try {
template = freeMarkerConfigurer.getConfiguration().getTemplate("message.ftl");
} catch (IOException e) {
e.printStackTrace();
return "获取模板失败!!!";
}
// 使用Map作为数据模型,定义属性和值
Map<String, Object> model = new HashMap<>();
model.put("fromName", fromName);
model.put("receiverName", receiverName);
model.put("content", content);
model.put("sendTime", simpleDateFormat.format(new Date()));
// 传入数据模型到模板,替代模板中的占位符,并将模板转化为html字符串
String templateHtml = null;
try {
templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
} catch (IOException e) {
e.printStackTrace();
return "转换模板失败!!!";
} catch (TemplateException e) {
e.printStackTrace();
return "转换模板失败!!!";
}
// 该方法本质上还是发送html邮件,调用之前发送html邮件的方法
return this.sendHtmlMail(receiver, subject, templateHtml);
}
/**
* 发送html邮件
*
* @param receiver 收件人
* @param subject 邮件标题
* @param content 邮件内容
*/
public String sendHtmlMail(String receiver, String subject, String content) {
try {
// 注意这里使用的是MimeMessage
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 发件人
helper.setFrom(fromEmail);
// 收件人
helper.setTo(receiver);
// 邮件标题
helper.setSubject(subject);
// 邮件内容,第二个参数:格式是否为html
helper.setText(content, true);
mailSender.send(message);
return "发送html邮件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "发送html邮件失败!!!";
}
}
3.3.2 添加访问接口
/**
* 发送模板邮件
*
* @param messageInfo 邮件信息
* @return
*/
@PostMapping("sendTemplateMail")
public String sendTemplateMail(MessageInfo messageInfo) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
// 发送Html模板邮件
return mailUtil.sendTemplateMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getFromName(), messageInfo.getReceiverName());
}
3.3.3 测试接口
4 第二种方式可以发送复杂的邮件(支持一对多发送邮件)
4.1 发送复杂邮件
4.1.1 创建 MailUtils 工具类,添加代码
package com.liyh;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Date;
import java.util.Properties;
/**
* 统一邮件发送工具类
*
* @author Liyh
* @date 2022/03/28
*/
@Component
public class MailUtils {
/**
* 从配置文件中注入是否需要身份验证
*/
@Value("${spring.mail.properties.mail.smtp.auth}")
private String auth;
/**
* 从配置文件中注入邮箱类型
*/
@Value("${spring.mail.host}")
private String emailHost;
/**
* 从配置文件中注入发件人
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* 从配置文件中注入授权码
*/
@Value("${spring.mail.password}")
private String password;
/**
* 发送复杂邮件
*
* @param receivers 收件人
* @param subject 邮件标题
* @param content 邮件内容
* @param imgPath 图片路径
* @param filePath1 文件路径
* @param filePath2 文件路径
*/
public String sendComplexMail(String receivers, String subject, String content, String imgPath, String filePath1, String filePath2) {
try {
Properties props = new Properties();
// 表示SMTP发送邮件,需要进行身份验证
props.put("mail.smtp.auth", auth);
props.put("mail.smtp.host", emailHost);
// 发件人的账号
props.put("mail.user", fromEmail);
// 访问SMTP服务时需要提供的密码
props.put("mail.password", password);
// 1.Session对象.连接(与邮箱服务器连接)
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromEmail, password);
}
});
// 2.构建邮件信息
Message message = new MimeMessage(session);
// 发件人邮箱
message.setFrom(new InternetAddress(fromEmail));
// Message.RecipientType.TO:消息接受者
// Message.RecipientType.CC:消息抄送者
// Message.RecipientType.BCC:匿名抄送接收者(其他接受者看不到这个接受者的姓名和地址)
// 判断接收人个数
if (receivers != null && receivers != "") {
String[] receiverArray = receivers.split(",");
if (receiverArray.length == 1) {
// 一对一发送邮件
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiverArray[0]));
} else {
// 一对多发送邮件
// 构建一个群发地址数组
String[] receiverArry = receivers.split(",");
InternetAddress[] adr = new InternetAddress[receiverArry.length];
for (int i = 0; i < receiverArry.length; i++) {
adr[i] = new InternetAddress(receiverArry[i]);
}
// Message的setRecipients方法支持群发。。注意:setRecipients方法是复数和点 到点不一样
message.setRecipients(Message.RecipientType.TO, adr);
}
}
// 发送日期
message.setSentDate(new Date());
// 设置标题
message.setSubject(subject);
// 3.准备邮件内容
// 3.1.准备图片数据
MimeBodyPart image = new MimeBodyPart();
FileDataSource imageSource = new FileDataSource(imgPath);
DataHandler handler = new DataHandler(imageSource);
image.setDataHandler(handler);
image.setFileName(imageSource.getName());
// 创建图片的一个表示用于显示在邮件中显示
image.setContentID(imageSource.getName());
// 3.2准备本文本数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("<img src='cid:" + image.getContentID() + "'/>" + "<h2>" + content + "</h2>", "text/html;charset=utf-8");
// 3.3.准备附件数据
MimeBodyPart appendix1 = new MimeBodyPart();
FileDataSource fileSource1 = new FileDataSource(filePath1);
appendix1.setDataHandler(new DataHandler(fileSource1));
appendix1.setFileName(fileSource1.getName());
MimeBodyPart appendix2 = new MimeBodyPart();
FileDataSource fileSource2= new FileDataSource(filePath2);
appendix2.setDataHandler(new DataHandler(fileSource2));
appendix2.setFileName(fileSource2.getName());
// 3.4.拼装邮件正文
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(image);
mimeMultipart.addBodyPart(text);
// 文本和图片内嵌成功
mimeMultipart.setSubType("related");
// 3.5.将拼装好的正文内容设置为主体
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(mimeMultipart);
// 3.6.拼接附件
MimeMultipart allFile = new MimeMultipart();
// 附件
allFile.addBodyPart(image);
allFile.addBodyPart(appendix1);
allFile.addBodyPart(appendix2);
// 正文
allFile.addBodyPart(contentText);
// 正文和附件都存在邮件中,所有类型设置为mixed
allFile.setSubType("mixed");
// 3.7.放到Message消息中
message.setContent(allFile);
// 4.发送邮件信息
Transport.send(message);
return "发送复杂邮件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "发送复杂邮件失败!!!";
}
}
}
4.1.2 添加访问接口
/**
* 发送复杂邮件
*
* @param messageInfo 邮件信息
*/
@PostMapping("sendComplexMail")
public String sendComplexMail(MessageInfo messageInfo) {
MailUtils mailUtils = SpringUtils.getBean(MailUtils.class);
return mailUtils.sendComplexMail(messageInfo.getReceivers(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getImgPath(), messageInfo.getFilePath1(), messageInfo.getFilePath2());
}
4.1.3 测试接口
4.2 完整工具类代码
4.2.1 SendMailController
查看代码
package com.liyh;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* 发送邮件接口
*/
@RestController
@RequestMapping("/mail")
public class SendMailController {
/**
* 发送文本邮件
*
* @param messageInfo 邮件信息
*/
@PostMapping("sendSimpleMail")
public String sendSimpleMail(MessageInfo messageInfo) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
return mailUtil.sendSimpleMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent());
}
/**
* 发送带附件的邮件
*
* @param messageInfo 邮件信息
* @param multipartFile 上传的文件
*/
@PostMapping("sendAttachmentsMail")
public String sendAttachmentsMail(MessageInfo messageInfo, MultipartFile multipartFile) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
// 发送带附件的邮件( 路径中的 \ 通常需要使用 \\, 如果是 / 就不需要使用转义了, \ 常用于本地,而/ 常用于网络连接地址 )
// D:\nacos1.2.1\bin\logs\access_log.2022-03-22.log
// C:/Users/Administrator/Pictures/1.jpg
return mailUtil.sendAttachmentsMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getFilePath1(), messageInfo.getImgPath(), multipartFile);
}
/**
* 发送模板邮件
*
* @param messageInfo 邮件信息
* @return
*/
@PostMapping("sendTemplateMail")
public String sendTemplateMail(MessageInfo messageInfo) {
MailUtil mailUtil = SpringUtils.getBean(MailUtil.class);
// 发送Html模板邮件
return mailUtil.sendTemplateMail(messageInfo.getReceiver(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getFromName(), messageInfo.getReceiverName());
}
/**
* 发送复杂邮件
*
* @param messageInfo 邮件信息
*/
@PostMapping("sendComplexMail")
public String sendComplexMail(MessageInfo messageInfo) {
MailUtils mailUtils = SpringUtils.getBean(MailUtils.class);
return mailUtils.sendComplexMail(messageInfo.getReceivers(), messageInfo.getSubject(), messageInfo.getContent(),
messageInfo.getImgPath(), messageInfo.getFilePath1(), messageInfo.getFilePath2());
}
}
4.2.2 MailUtil
查看代码
package com.liyh;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component
public class MailUtil {
/**
* 从配置文件中注入发件人的姓名
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* Spring官方提供的集成邮件服务的实现类,目前是Java后端发送邮件和集成邮件服务的主流工具。
*/
@Autowired
private JavaMailSender mailSender;
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
/**
* 发送文本邮件
*
* @param receiver 收件人
* @param subject 邮件标题
* @param content 邮件内容
*/
public String sendSimpleMail(String receiver, String subject, String content) {
try {
SimpleMailMessage message = new SimpleMailMessage();
// 发件人
message.setFrom(fromEmail);
// 收件人
message.setTo(receiver);
// 邮件标题
message.setSubject(subject);
// 邮件内容
message.setText(content);
mailSender.send(message);
return "发送文本邮件成功";
} catch (MailException e) {
e.printStackTrace();
return "发送文本邮件失败!!!";
}
}
/**
* 发送html邮件
*
* @param receiver 收件人
* @param subject 邮件标题
* @param content 邮件内容
*/
public String sendHtmlMail(String receiver, String subject, String content) {
try {
// 注意这里使用的是MimeMessage
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 发件人
helper.setFrom(fromEmail);
// 收件人
helper.setTo(receiver);
// 邮件标题
helper.setSubject(subject);
// 邮件内容,第二个参数:格式是否为html
helper.setText(content, true);
mailSender.send(message);
return "发送html邮件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "发送html邮件失败!!!";
}
}
/**
* 发送带附件的邮件
*
* @param receiver 收件人
* @param subject 邮件标题
* @param content 邮件内容
* @param filePath 文件路径
* @param imgPath 图片路径
* @param multipartFile 上传的文件
*/
public String sendAttachmentsMail(String receiver, String subject, String content, String filePath, String imgPath, MultipartFile multipartFile) {
try {
MimeMessage message = mailSender.createMimeMessage();
// 要带附件第二个参数设为true
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 发件人
helper.setFrom(fromEmail);
// 收件人
helper.setTo(receiver);
// 邮件标题
helper.setSubject(subject);
// 邮件内容,第二个参数:格式是否为html
helper.setText(content, true);
// 添加文件附件1
FileSystemResource file = new FileSystemResource(new File(filePath));
helper.addAttachment(file.getFilename(), file);
// 添加文件附件2
FileSystemResource files = new FileSystemResource(multipartFileToFile(multipartFile));
helper.addAttachment(files.getFilename(), files);
// 添加图片附件
FileSystemResource image = new FileSystemResource(new File(imgPath));
helper.addAttachment(image.getFilename(), image);
mailSender.send(message);
return "发送带附件的邮件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "发送带附件的邮件失败!!!";
}
}
/**
* 发送模板邮件
*
* @param receiver 收件人
* @param subject 邮件标题
* @param content 邮件内容
* @param fromName 发件人姓名
* @param receiverName 收件人姓名
* @return
*/
public String sendTemplateMail(String receiver, String subject, String content, String fromName, String receiverName) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 获得模板
Template template = null;
try {
template = freeMarkerConfigurer.getConfiguration().getTemplate("message.ftl");
} catch (IOException e) {
e.printStackTrace();
return "获取模板失败!!!";
}
// 使用Map作为数据模型,定义属性和值
Map<String, Object> model = new HashMap<>();
model.put("fromName", fromName);
model.put("receiverName", receiverName);
model.put("content", content);
model.put("sendTime", simpleDateFormat.format(new Date()));
// 传入数据模型到模板,替代模板中的占位符,并将模板转化为html字符串
String templateHtml = null;
try {
templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
} catch (IOException e) {
e.printStackTrace();
return "转换模板失败!!!";
} catch (TemplateException e) {
e.printStackTrace();
return "转换模板失败!!!";
}
// 该方法本质上还是发送html邮件,调用之前发送html邮件的方法
return this.sendHtmlMail(receiver, subject, templateHtml);
}
/**
* 把 multiFile 转换为 file
*
* @param multiFile
* @return
*/
private File multipartFileToFile(MultipartFile multiFile) {
// 获取文件名
String fileName = multiFile.getOriginalFilename();
// 获取文件后缀
String prefix = fileName.substring(fileName.lastIndexOf("."));
// 若需要防止生成的临时文件重复,可以在文件名后添加随机码
try {
File file = File.createTempFile(fileName, prefix);
multiFile.transferTo(file);
return file;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
MailUtil
4.2.3 MailUtils
查看代码
package com.liyh;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Date;
import java.util.Properties;
/**
* 统一邮件发送工具类
*
* @author Liyh
* @date 2022/03/28
*/
@Component
public class MailUtils {
/**
* 从配置文件中注入是否需要身份验证
*/
@Value("${spring.mail.properties.mail.smtp.auth}")
private String auth;
/**
* 从配置文件中注入邮箱类型
*/
@Value("${spring.mail.host}")
private String emailHost;
/**
* 从配置文件中注入发件人
*/
@Value("${spring.mail.username}")
private String fromEmail;
/**
* 从配置文件中注入授权码
*/
@Value("${spring.mail.password}")
private String password;
/**
* 发送复杂邮件
*
* @param receivers 收件人
* @param subject 邮件标题
* @param content 邮件内容
* @param imgPath 图片路径
* @param filePath1 文件路径
* @param filePath2 文件路径
*/
public String sendComplexMail(String receivers, String subject, String content, String imgPath, String filePath1, String filePath2) {
try {
Properties props = new Properties();
// 表示SMTP发送邮件,需要进行身份验证
props.put("mail.smtp.auth", auth);
props.put("mail.smtp.host", emailHost);
// 发件人的账号
props.put("mail.user", fromEmail);
// 访问SMTP服务时需要提供的密码
props.put("mail.password", password);
// 1.Session对象.连接(与邮箱服务器连接)
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromEmail, password);
}
});
// 2.构建邮件信息
Message message = new MimeMessage(session);
// 发件人邮箱
message.setFrom(new InternetAddress(fromEmail));
// Message.RecipientType.TO:消息接受者
// Message.RecipientType.CC:消息抄送者
// Message.RecipientType.BCC:匿名抄送接收者(其他接受者看不到这个接受者的姓名和地址)
// 判断接收人个数
if (receivers != null && receivers != "") {
String[] receiverArray = receivers.split(",");
if (receiverArray.length == 1) {
// 一对一发送邮件
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiverArray[0]));
} else {
// 一对多发送邮件
// 构建一个群发地址数组
String[] receiverArry = receivers.split(",");
InternetAddress[] adr = new InternetAddress[receiverArry.length];
for (int i = 0; i < receiverArry.length; i++) {
adr[i] = new InternetAddress(receiverArry[i]);
}
// Message的setRecipients方法支持群发。。注意:setRecipients方法是复数和点 到点不一样
message.setRecipients(Message.RecipientType.TO, adr);
}
}
// 发送日期
message.setSentDate(new Date());
// 设置标题
message.setSubject(subject);
// 3.准备邮件内容
// 3.1.准备图片数据
MimeBodyPart image = new MimeBodyPart();
FileDataSource imageSource = new FileDataSource(imgPath);
DataHandler handler = new DataHandler(imageSource);
image.setDataHandler(handler);
image.setFileName(imageSource.getName());
// 创建图片的一个表示用于显示在邮件中显示
image.setContentID(imageSource.getName());
// 3.2准备本文本数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("<img src='cid:" + image.getContentID() + "'/>" + "<h2>" + content + "</h2>", "text/html;charset=utf-8");
// 3.3.准备附件数据
MimeBodyPart appendix1 = new MimeBodyPart();
FileDataSource fileSource1 = new FileDataSource(filePath1);
appendix1.setDataHandler(new DataHandler(fileSource1));
appendix1.setFileName(fileSource1.getName());
MimeBodyPart appendix2 = new MimeBodyPart();
FileDataSource fileSource2= new FileDataSource(filePath2);
appendix2.setDataHandler(new DataHandler(fileSource2));
appendix2.setFileName(fileSource2.getName());
// 3.4.拼装邮件正文
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(image);
mimeMultipart.addBodyPart(text);
// 文本和图片内嵌成功
mimeMultipart.setSubType("related");
// 3.5.将拼装好的正文内容设置为主体
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(mimeMultipart);
// 3.6.拼接附件
MimeMultipart allFile = new MimeMultipart();
// 附件
allFile.addBodyPart(image);
allFile.addBodyPart(appendix1);
allFile.addBodyPart(appendix2);
// 正文
allFile.addBodyPart(contentText);
// 正文和附件都存在邮件中,所有类型设置为mixed
allFile.setSubType("mixed");
// 3.7.放到Message消息中
message.setContent(allFile);
// 4.发送邮件信息
Transport.send(message);
return "发送复杂邮件成功";
} catch (MessagingException e) {
e.printStackTrace();
return "发送复杂邮件失败!!!";
}
}
}
MailUtils