springboot系列(十六):如何实现发送邮件提醒,附完整源码(完结篇)
Posted bug菌¹
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot系列(十六):如何实现发送邮件提醒,附完整源码(完结篇)相关的知识,希望对你有一定的参考价值。
👨🎓作者:bug菌
🚫特别声明:原创不易,转载请附上原文出处链接和本文声明,谢谢配合。
🙏版权声明:文章里可能部分文字或者图片来源于互联网或者百度百科,如有侵权请联系bug菌处理。
嗨,家人们,我是bug菌呀,我又来啦。今天我们来聊点什么咧,OK,接着为大家更《springboot零基础入门教学》系列文章吧。希望能帮助更多的初学者们快速入门!
小伙伴们在批阅文章的过程中如果觉得文章对您有一丝丝帮助,还请别吝啬您手里的赞呀,大胆的把文章 点亮👍吧,您的点赞三连( 收藏⭐️+关注👨🎓+留言📃)就是对bug菌我创作道路上最好的鼓励与支持😘。时光不弃🏃🏻♀️,创作不停💕,加油☘️
一、前言🔥
先不开始这期的内容,我们先来回顾一下吧,考考大家, 上几篇都讲了些什么知识点呀,不知道大家都还有印象没?如果实在回忆不起,那也没关系,bug菌再集中给大家复盘下,让大家都能系统性的掌握这整块知识点,好吧。
springboot如何整合邮件发送提醒功能?这个业务场景虽然平时开发比较少接触,毕竟一般邮件开发基本都是一些用于什么人员oa、pm、财务等管理系统,但这些早就已经被系统集成过了,一般情况下也不会说拿出来二次开发或者迭代,但是身为开发,多了解一些总归没有坏处,万一那天就排上用场了,说不定你还得回来感谢bug菌我哦。
再者,此次带大家了解加实践,也算是有过开发邮件业务的经验咯,你们说是不是。
如下呢,是上几期的教学大纲,大家可以看一下:
然而,今天是最后一期啦,啊呸呸,不是我要最后一期,而是这块知识点啦,要与大家说再见啦。如果有小伙伴直接中途插入,还请麻烦先去看上几期的内容,要不然贸然跟着学,肯定要吃大亏,去我的专栏《SpringBoot零基础入门》从头开始跟进。
首先,我先给大家整理下上几期所开发实现的代码吧,我尽量把完整代码都粘贴出来,一来方便大家系统性的阅读(cv大法),二来也能有个标准核对自己的代码,如果有运行不起来的,也好有个标准答案可以借鉴,哈哈哈哈哈哈。
二、方法类🔥
如下就是上几期所实现的不同邮件发送方法类,需要的小伙伴自行存取,尽情拿去造吧~
package com.example.demo.component.mail.build;
import com.example.demo.component.mail.model.AccessoryMail;
import com.example.demo.component.mail.model.ImgResMail;
import com.example.demo.component.mail.model.Mail;
import com.example.demo.component.mail.model.ThymeleafMail;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
/**
* @author luoYong
* @version 1.0
* @date 2022/1/18 9:36
*/
@Component
public class SendMailBuild
@Autowired
private JavaMailSender javaMailSender;
@Autowired
private SpringTemplateEngine templateEngine; //创建模板引擎
@Autowired private UserService userService;
/**
* 发送简单邮件
*/
public void sendSimpleMail(Mail model)
//构建邮件内容对象
SimpleMailMessage msg = new SimpleMailMessage(); //邮件发送者
msg.setFrom(model.getSendMailAccount()); //邮件接收者
msg.setTo(model.getAcceptMailAccount()); //邮件主题
msg.setSubject(model.getTheme()); //邮件正文
msg.setText(model.getMailText()); //邮件发送时间
msg.setSentDate(model.getSendTime());
javaMailSender.send(msg);
/**
* 发送带附件的邮件
*/
public void sendAccessoryMail(AccessoryMail model) throws MessagingException
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper msg = new MimeMessageHelper(mimeMessage, true); //邮件发送者
msg.setFrom(model.getSendMailAccount()); //邮件接收者
msg.setTo(model.getAcceptMailAccount()); //邮件主题
msg.setSubject(model.getTheme()); //邮件正文
msg.setText(model.getMailText()); //邮件发送时间
msg.setSentDate(model.getSendTime()); //添加附件
msg.addAttachment(model.getAttachmentName(), new File(model.getAttachmentPath()));
javaMailSender.send(mimeMessage);
/**
* 发送带图片资源的邮件
* 图片资源和附件的区别就在于:图片资源是放在邮件正文中的,就是一打开邮件就能看到图片。
*/
public void sendImgResMail(ImgResMail model) throws MessagingException
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper msg = new MimeMessageHelper(mimeMessage, true); //邮件发送者
msg.setFrom(model.getSendMailAccount()); //邮件接收者
msg.setTo(model.getAcceptMailAccount()); //邮件主题
msg.setSubject(model.getTheme()); //邮件发送时间
msg.setSentDate(model.getSendTime()); //邮件正文
msg.setText(model.getMailText(),true); //添加图片链接
for (int i = 0; i < model.getContentIds().size(); i++)
msg.addInline(model.getContentIds().get(i), new FileSystemResource(new File(model.getPaths().get(i))));
javaMailSender.send(mimeMessage);
/**
* 配置静态模板 这里使用了Thymeleaf 作为邮件模板
*/
public void sendThymeleafMail(ThymeleafMail model) throws MessagingException
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper msg = new MimeMessageHelper(mimeMessage, true); //邮件发送者
msg.setFrom(model.getSendMailAccount()); //邮件接收者
msg.setTo(model.getAcceptMailAccount()); //邮件主题
msg.setSubject(model.getTheme()); //邮件发送时间
msg.setSentDate(model.getSendTime());
Context context = new Context(); //添加模板数据
model.getVariables().forEach(p ->
context.setVariable(p.getName(), p.getValue());
); //指定静态页面模板
String process = templateEngine.process(model.getTemplate(), context);
msg.setText(process, true);
javaMailSender.send(mimeMessage);
如上是这几期发送邮件功能点的核心,大家有空一定要好好研究,虽然我也有的是参考了网上大佬的教学才自己去进行了尝试,我希望你们也能跟我一样,能把这些方法分别断点研究,看看每一处代码类都是在干一件什么事!
其实邮件发送,由于被springboot集成过后,一切使用就变得超级简单了,你只需要学习SimpleMailMessage 与 MimeMessage 这两邮件创建类是如何工作的,基本就了解到这儿就可以了,毕竟一般业务中也不怎么会接触到这个,了解使用为主,不必深入研究,好吧。
三、vo类🔥
Mail.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
/**
* 基本邮件参数
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 9:37
*/
@ApiModel(value = "基本邮件参数",description = "基本邮件参数")
public class Mail
@ApiModelProperty("发件人邮箱账号")
private String sendMailAccount;
@ApiModelProperty("收件人邮箱账号")
private String acceptMailAccount;
@ApiModelProperty("邮件主题")
private String theme;
@ApiModelProperty("邮件内容")
private String mailText;
@ApiModelProperty("发送时间")
private Date sendTime = new Date();
public String getTheme()
return theme;
public void setTheme(String theme)
this.theme = theme;
public String getSendMailAccount()
return sendMailAccount;
public void setSendMailAccount(String sendMailAccount)
this.sendMailAccount = sendMailAccount;
public String getAcceptMailAccount()
return acceptMailAccount;
public void setAcceptMailAccount(String acceptMailAccount)
this.acceptMailAccount = acceptMailAccount;
public Date getSendTime()
return sendTime;
public void setSendTime(Date sendTime)
this.sendTime = sendTime;
public String getMailText()
return mailText;
public void setMailText(String mailText)
this.mailText = mailText;
ImgResMail.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
/**
* 发送带图片资源邮件参数
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 10:54
*/
@ApiModel(value = "发送带图片资源邮件参数",description = "发送带图片资源邮件参数")
public class ImgResMail extends Mail
@ApiModelProperty("对于的图片标记id")
private List<String> contentIds;
@ApiModelProperty("图片地址")
private List<String> paths;
public List<String> getContentIds()
return contentIds;
public void setContentIds(List<String> contentIds)
this.contentIds = contentIds;
public List<String> getPaths()
return paths;
public void setPaths(List<String> paths)
this.paths = paths;
AccessoryMail.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModelProperty;
/**
* 发送带附件的邮件参数
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 10:57
*/
public class AccessoryMail extends Mail
@ApiModelProperty("附件地址")
private String attachmentPath;
@ApiModelProperty("附件名")
private String attachmentName;
public String getAttachmentPath()
return attachmentPath;
public void setAttachmentPath(String attachmentPath)
this.attachmentPath = attachmentPath;
public String getAttachmentName()
return attachmentName;
public void setAttachmentName(String attachmentName)
this.attachmentName = attachmentName;
Variable.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* 静态文件对应的key-value
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 11:25
*/
@ApiModel(value = "静态文件对应的key-value",description = "静态文件对应的key-value")
public class Variable
@ApiModelProperty("参数名")
private String name;
@ApiModelProperty("值")
private String value;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getValue()
return value;
public void setValue(String value)
this.value = value;
ThymeleafMail.java
package com.example.demo.component.mail.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* 静态文件对应的key-value
*
* @author luoYong
* @version 1.0
* @date 2022/1/18 11:25
*/
@ApiModel(value = "静态文件对应的key-value",description = "静态文件对应的key-value")
public class Variable
@ApiModelProperty("参数名")
private String name;
@ApiModelProperty("值")
private String value;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getValue()
return value;
public void setValue(String value)
this.value = value;
四、test-case类🔥
至于test-case,可能每个人书写习惯不一样,大家都有自己独特的代码习惯,你们也可以按照自己的风格来写,毕竟主要是为了测试邮件方法,别的倒没啥,测试方法功能点是否正常即可。如下是我的:仅供参考:
package com.example.demo.component.build;
import com.example.demo.component.mail.build.SendMailBuild;
import com.example.demo.component.mail.model.*;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.mail.MessagingException;import java.util.ArrayList;
import java.util.Date;import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MailTest
@Autowired
private SendMailBuild sendMailBuild;
/**
* 发送简单邮件
*/
@Test
void sendSimpleMail()
Mail mailModel = new Mail();
mailModel.setTheme("title:这是一封测试邮件哈!"); // 设置邮件主题
mailModel.setSendMailAccount("luoyong0603@foxmail.com"); // 设置邮箱发送者
mailModel.setAcceptMailAccount("luoyong0603@foxmail.com"); // 设置邮件接收者,可以有多个接收者
mailModel.setSendTime(new Date()); // 设置邮件发送日期
mailModel.setMailText("text:这是测试邮件的正文内容:我是testMail"); // 设置邮件的正文
sendMailBuild.sendSimpleMail(mailModel);
/**
* 发送带附件的邮件
*/
@Test
void sendSimpleMailForDoc() throws MessagingException
AccessoryMail mailModel = new AccessoryMail();
mailModel.setTheme("这是一封测试邮件"); // 设置邮件主题
mailModel.setSendMailAccount("luoyong0603@foxmail.com"); // 设置邮箱发送者
mailModel.setAcceptMailAccount("luoyong0603@foxmail.com"); // 设置邮件接收者,可以有多个接收者
mailModel.setSendTime(new Date()); // 设置邮件发送日期
mailModel.setMailText("这是测试邮件的正文"); // 设置邮件的正文
mailModel.setAttachmentName("2022.png");//附件名
mailModel.setAttachmentPath("C:\\\\Users\\\\Administrator\\\\Desktop\\\\2022.png");//附件地址
sendMailBuild.sendAccessoryMail(mailModel);
/**
* 发送带图片资源的邮件
* 图片资源和附件的区别就在于 图片资源是放在邮件正文中的,就是一打开邮件就能看到图片
*/
@Test
public void sendImgResMail() throws MessagingException
ImgResMail mailModel = new ImgResMail();
mailModel.setTheme("这是一封测试邮件"); // 设置邮件主题
mailModel.setSendMailAccount("luoyong0603@foxmail.com"); // 设置邮箱发送者
mailModel.setAcceptMailAccount("luoyong0603@foxmail.com"); // 设置邮件接收者,可以有多个接收者
mailModel.setSendTime(new Date()); // 设置邮件发送日期
mailModel.setMailText("<p>hello 大家好,我是一封测试邮件,我包含了两张图片,分别如下</p><p>第一张图片:</p><img src='cid:img1'/><p>第二张图片:</p><img src='cid:img2'/>");
List<String> paths = new ArrayList<>();
paths.add("C:\\\\Users\\\\Administrator\\\\Desktop\\\\2022.png");
paths.add("C:\\\\Users\\\\Administrator\\\\Desktop\\\\test.png");
mailModel.setPaths(paths);
List<String> contentIds = new ArrayList<>();
contentIds.add("img1");
contentIds.add("img2");
mailModel.setContentIds(contentIds);
sendMailBuild.sendImgResMail(mailModel);
/**
* 配置静态模板 这里使用了Thymeleaf 邮件模板
*/
@Test
public void testSendThymeleafMail() throws MessagingException
ThymeleafMail mailModel = new ThymeleafMail();
mailModel.setTheme("这是一封测试邮件"); // 设置邮件主题
mailModel.setSendMailAccount("luoyong0603@foxmail.com"); // 设置邮箱发送者
mailModel.setAcceptMailAccount("luoyong0603@foxmail.com"); // 设置邮件接收者,可以有多个接收者
mailModel.setSendTime(new Date()); // 设置邮件发送日期
List<Variable> variables = new ArrayList<>();
Variable variable1 = new Variable();
variable1.setName("school");
variable1.setValue("清华附属小学");
Variable variable2 = new Variable();
variable2.setName("className");
variable2.setValue("六(1)班");
Variable variable3 = new Variable();
variable3.setName("name");
variable3.setValue("小罗");
variables.add(variable1);
variables.add(variable2);
variables.add(variable3);
mailModel.setVariables(variables);
mailModel.setTemplate("mail.html");
sendMailBuild.sendThymeleafMail(mailModel);
如下是我实现这个功能块的项目结构。
大家也可以像我一样,一个组件就是一个功能点,然后所涉及的model类,单独封装方法一个component中,日后,项目进行维护,后人一看也就明白了,原来这一组件就是干了一件邮件发送等功能点,自己用起来或他人进行调用,一看文件目录便知。
五、静态模板文件🔥
1、mail.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Thymeleaf邮件模板</title>
</head>
<body>
<p>这是一份学生名单:请查收</p>
<table border="1">
<tr>
<td>学校</td>
<td th:text="$school"></td>
</tr>
<tr>
<td>班级</td>
<td th:text="$className"></td>
</tr>
<tr>
<td>姓名</td>
<td th:text="$name"></td>
</tr>
</table>
<div style="color: red;">以上是学生名单!</div>
</body>
</html>
2、user.html
这套模板暂时没用上,这主要是一个循环遍历集合的模板。也供大家参考:
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta content="text/html;charset=UTF-8"/>
</head>
<body>
<h6>Thymeleaf 模板引擎</h6>
<table border="1" bgcolor="#f0ffff">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>地址</th>
</tr>
</thead>
<!--th:each表示循环遍历,和Vue一样-->
<tbody th:each="user : $users">
<tr>
<td th:text="$user.name"></td>
<td th:text="$user.age"></td>
<td th:text="$user.sex"></td>
<td th:text="$user.address"></td>
</tr>
</tbody>
</table>
</body>
</html>
这里我就有必要向大家介绍一下:html的xmlns
属性。
问:为什么返回的是集合 数组结构的,xmlns属性配了两个链接指向?答:xmlns 属性 是可以配置多个命名空间的,就比如上方,我就配置了两个命名空间。该属性可以放在文档内任何元素的开始标签中,比如:
<div xmlns="http://www.w3.org/1999/Math/MathMl">这是一个div</div>。
然后该属性的值类似于url,定义了一个命名空间,在进行浏览器访问的时候,就会将此命名空间用于该属性所在元素内的所有内容。
例如,如果需要使用符合 XML 规范的 XHTML 文档,则应该在文档中的<html> 标签中至少使用一个 xmlns 属性,以指定整个文档所使用的主要命名空间:
<html xmlns="http://www.w3.org/1999/xhtml">
一个简单的 XHTML 文档,带有最少的必需标签应该如此,大家请看:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<title>文档标题</title>
</head>
<body>
文档内容......
</body>
</html>
以上是对html 的xmlns
属性拓展。供大家参考。
接着,如下是我的静态模板目录结构:
如果是要指定返回静态模板类,那你就要配置环境了,比如spring.thymeleaf.xxx 相关属性值了,其中就有一个属性是配置这个templeates文件夹的,这个在我以前的教程中,也专门出了一期,大家想看的也可以去看看,至于为啥我本文没有配置静态路径,却邮件模板能正确找到呢?这个大家可以思考一下,为何能正确找到mail.html.
说到这儿,就要跟大家说拜拜了,以上就是针对如何代码实现邮件提醒功能的全部内容啦,如果你还卡在途中某个点,但说无妨,bug菌是不会嘲笑你的,只会耐心的对你的疑惑进行全面解答,我为人人,人人才会为我!对吧,没有付出,哪有回报,所以尽情的把问题抛出来把,下下方留言或者加我的交流群,都可。可能就会有小伙伴问了,bug菌你这么倾囊相授,到底图啥呀?图我们回报你啥呀?
如果非要论回报,那就帮我把文章左上角的大拇指点亮吧。如果能一键三连,那bug菌更是喜笑颜开啦,更加充满动力为大家奉献自己的时间,要知道上班时间拿来写文章,是一件多么危险的事。
... ...
ok,以上就是我这期的全部内容啦,如果还想学习更多,你可以看看我的往期热文推荐哦,每天积累一个奇淫小知识,日积月累下去,你一定能成为令人敬仰的大佬的。好啦,咱们下期见~
六、往期推荐🔥
七、文末🔥
如果还想要学习更多,小伙伴们可关注bug菌专门为大家创建的专栏《springboot零基础入门教学》,从无到有,从零到一!希望能帮助到更多小伙伴们。
我是bug菌,一名想走👣出大山改变命运的程序猿。接下来的路还很长,都等待着我们去突破、去挑战。来吧,小伙伴们,我们一起加油!未来皆可期,fighting!
最后送大家两句我很喜欢的话,与诸君共勉!
☘️做你想做的人,没有时间限制,只要愿意,什么时候都可以start。
🍀你能从现在开始改变,也可以一成不变,这件事,没有规矩可言,你可以活出最精彩的自己。
💌如果文章对您有所帮助,就请留下您的赞吧!(#^.^#);
💝如果喜欢bug菌分享的文章,就请给bug菌点个关注吧!(๑′ᴗ‵๑)づ╭❤~;
💗如果对文章有任何疑问,还请文末留言或者加群吧;
💞鉴于个人经验有限,所有观点及技术研点,如有异议,请直接回复参与讨论(请勿发表攻击言论,谢谢);
💕版权声明:原创不易,转载请附上原文出处链接和本文声明,版权所有,盗版必究!!!谢谢。
以上是关于springboot系列(十六):如何实现发送邮件提醒,附完整源码(完结篇)的主要内容,如果未能解决你的问题,请参考以下文章
springboot系列(十六):如何实现发送邮件提醒,附完整源码(完结篇)
springboot系列:如何实现邮件发送提醒,你一定得会(准备篇)
springboot系列:如何实现邮件发送提醒,你一定得会(准备篇)