SpringBoot整合邮箱发送邮件
1 SpringBoot整合邮箱发送邮件
在开发中,经常会碰到email邮件发送的场景,如发送验证码,向客户发送邮件等等。
今天,本项目将讲解通过 SpringBoot 发送 email 邮件(普通文本邮件 ,HTML内容板式邮件 ,包含静态资源邮件,以及带附件邮件)。
2 项目配置
2.1 创建SpringBoot项目
项目结构,简单测试没有分包
2.2 pom文件导入需要的依赖
<dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-mailartifactId> dependency> <dependency> <groupId>org.freemarkergroupId> <artifactId>freemarkerartifactId> <version>2.3.28version> <scope>compilescope> dependency> <dependency> <groupId>org.projectlombokgroupId> <artifactId>lombokartifactId> <version>1.18.22version> 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: liyh722@163.com
# 授权码(自己邮箱的授权码)
password: AWYCRGDVOAUHTVOC
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 staticT getBean(String name) throws BeansException { return (T) beanFactory.getBean(name); } /** * 获取类型为requiredType的对象 * * @param clz * @return * @throws org.springframework.beans.BeansException */ public static T getBean(Class clz) throws BeansException { T result = (T) beanFactory.getBean(clz); return result; } }
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作为数据模型,定义属性和值 Mapmodel = 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("" + "
" + content + "
", "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 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作为数据模型,定义属性和值 MapMailUtilmodel = 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; } }
4.2.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("MailUtils" + "
" + content + "
", "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 "发送复杂邮件失败!!!"; } } }