SpringBoot 整合 Mail 轻松实现邮件自动推送
简单使用
1、pom 包配置
pom 包里面添加 spring-boot-starter-mail 包引用
<dependencies><dependency> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>
</dependencies>
2、在 application.properties 中添加邮箱配置
spring.mail.host=smtp.qiye.163.com //邮箱服务器地址
spring.mail.username=xxx@oo.com //用户名
spring.mail.password=xxyyooo //密码
spring.mail.default-encoding=UTF-8mail.fromMail.addr=xxx@oo.com //以谁来发送邮件
3、编写 mailService,这里只提出实现类。
@Component
public class MailServiceImpl implements MailService{private final Logger logger = LoggerFactory.getLogger(this.getClass());@Autowiredprivate JavaMailSender mailSender;@Value("${mail.fromMail.addr}")private String from;@Overridepublic void sendSimpleMail(String to, String subject, String content) {SimpleMailMessage message = new SimpleMailMessage();message.setFrom(from);message.setTo(to);message.setSubject(subject);message.setText(content);try {mailSender.send(message);logger.info("简单邮件已经发送。");} catch (Exception e) {logger.error("发送简单邮件时发生异常!", e);}}
}
4、编写 test 类进行测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class MailServiceTest {@Autowiredprivate MailService MailService;@Testpublic void testSimpleMail() throws Exception {MailService.sendSimpleMail("test@126.com","test simple mail"," hello this is simple mail");}
}
至此一个简单的文本发送就完成了。
高级玩法
但是在正常使用的过程中,我们通常在邮件中加入图片或者附件来丰富邮件的内容,下面讲介绍如何使用 Spring Boot 来发送丰富的邮件。
发送 html 格式邮件
其它都不变在 MailService 添加 sendHtmlMail 方法.
public void sendHtmlMail(String to, String subject, String content) {MimeMessage message = mailSender.createMimeMessage();try {//true表示需要创建一个multipart messageMimeMessageHelper helper = new MimeMessageHelper(message, true);helper.setFrom(from);helper.setTo(to);helper.setSubject(subject);helper.setText(content, true);mailSender.send(message);logger.info("html邮件发送成功");} catch (MessagingException e) {logger.error("发送html邮件时发生异常!", e);}
}
在测试类中构建 html 内容,测试发送
@Test
public void testHtmlMail() throws Exception {String content="<html>\n" +"<body>\n" +" <h3>hello world ! 这是一封Html邮件!</h3>\n" +"</body>\n" +"</html>";MailService.sendHtmlMail("test@126.com","test simple mail",content);
}
发送带附件的邮件
在 MailService 添加 sendAttachmentsMail 方法.
public void sendAttachmentsMail(String to, String subject, String content, String filePath){MimeMessage message = mailSender.createMimeMessage();try {MimeMessageHelper helper = new MimeMessageHelper(message, true);helper.setFrom(from);helper.setTo(to);helper.setSubject(subject);helper.setText(content, true);FileSystemResource file = new FileSystemResource(new File(filePath));String fileName = filePath.substring(filePath.lastIndexOf(File.separator));helper.addAttachment(fileName, file);mailSender.send(message);logger.info("带附件的邮件已经发送。");} catch (MessagingException e) {logger.error("发送带附件的邮件时发生异常!", e);}
}
添加多个附件可以使用多条
helper.addAttachment(fileName,file)
在测试类中添加测试方法
@Test
public void sendAttachmentsMail() {String filePath="e:\\tmp\\application.log";mailService.sendAttachmentsMail("test@126.com", "主题:带附件的邮件", "有附件,请查收!", filePath);
}
发送带静态资源的邮件
邮件中的静态资源一般就是指图片,在 MailService 添加 sendAttachmentsMail 方法.
public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId){MimeMessage message = mailSender.createMimeMessage();try {MimeMessageHelper helper = new MimeMessageHelper(message, true);helper.setFrom(from);helper.setTo(to);helper.setSubject(subject);helper.setText(content, true);FileSystemResource res = new FileSystemResource(new File(rscPath));helper.addInline(rscId, res);mailSender.send(message);logger.info("嵌入静态资源的邮件已经发送。");} catch (MessagingException e) {logger.error("发送嵌入静态资源的邮件时发生异常!", e);}
}
在测试类中添加测试方法
@Test
public void sendInlineResourceMail() {String rscId = "neo006";String content="<html><body>这是有图片的邮件:<img src=\'cid:" + rscId + "\' ></body></html>";String imgPath = "C:\\Users\\summer\\Pictures\\favicon.png";mailService.sendInlineResourceMail("test@126.com", "主题:这是有图片的邮件", content, imgPath, rscId);
}
添加多个图片可以使用多条
<imgsrc='cid:" + rscId + "'>
和helper.addInline(rscId,res)
来实现
到此所有的邮件发送服务已经完成了。
邮件系统
上面发送邮件的基础服务就这些了,但是如果我们要做成一个邮件系统的话还需要考虑以下几个问题:
邮件模板
我们会经常收到这样的邮件:
尊敬的xxx用户:恭喜您注册成为xxx网的用户,,同时感谢您对xxx的关注与支持并欢迎您使用xx的产品与服务。...
其中只有 xxx 这个用户名在变化,其它邮件内容均不变,如果每次发送邮件都需要手动拼接的话会不够优雅,并且每次模板的修改都需要改动代码的话也很不方便,因此对于这类邮件需求,都建议做成邮件模板来处理。模板的本质很简单,就是在模板中替换变化的参数,转换为 html 字符串即可,这里以 thymeleaf为例来演示。
1、pom 中导入 thymeleaf 的包
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2、在 resorces/templates 下创建 emailTemplate.html
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"/><title>Title</title></head><body>您好,这是验证邮件,请点击下面的链接完成验证,<br/><a href="#" th:href="@{ http://www.test.com/{id}(id=${id}) }">激活账号</a></body></html>
3、解析模板并发送
@Test
public void sendTemplateMail() {//创建邮件正文Context context = new Context();context.setVariable("id", "006");String emailContent = templateEngine.process("emailTemplate", context);mailService.sendHtmlMail("test@126.com","主题:这是模板邮件",emailContent);
}
发送失败
因为各种原因,总会有邮件发送失败的情况,比如:邮件发送过于频繁、网络异常等。在出现这种情况的时候,我们一般会考虑重新重试发送邮件,会分为以下几个步骤来实现:
-
1、接收到发送邮件请求,首先记录请求并且入库。
-
2、用邮件发送接口发送邮件,并且将发送结果记录入库。
-
3、启动定时系统扫描时间段内,未发送成功并且重试次数小于3次的邮件,进行再次发送
异步发送
很多时候邮件发送并不是我们主业务必须关注的结果,比如通知类、提醒类的业务可以允许延时或者失败。这个时候可以采用异步的方式来发送邮件,加快主交易执行速度,在实际项目中可以采用MQ发送邮件相关参数,监听到消息队列之后启动发送邮件。
最后。
相关文章:
SpringBoot 整合 Mail 轻松实现邮件自动推送
简单使用 1、pom 包配置 pom 包里面添加 spring-boot-starter-mail 包引用 <dependencies><dependency> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency> </de…...
MyBatis 核心知识与实践
一、MyBatis 概述 1. 框架简介 MyBatis 是一款支持自定义 SQL、存储过程以及高级映射的持久层框架。它避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的操作,使开发人员能够更专注于 SQL 语句的编写和业务逻辑的处理。 2. 核心组件 SqlSessionFactoryB…...

机器学习期末速成
文章目录 一、机器学习分类二、逻辑回归三、决策树四、集成学习算法五、支持向量机六、聚类七、特征工程和指标 文章参考自B站机器学习期末速成课 本文仅作者个人复习使用 一、机器学习分类 聚类和分类的区别: 分类:一开始就知道有哪些类别 聚类&#…...

Linux中的线程
目录 线程的概念 进程与线程的关系 线程创建 线程终止 线程等待 线程分离 原生线程库 线程局部存储 自己实现线程封装 线程的优缺点 多线程共享与独占资源 线程互斥 互斥锁 自己实现锁的封装 加锁实现互斥的原理 死锁 线程同步 线程的概念 回顾进程相关概念 …...

AI大模型学习笔记|多目标算法梳理、举例
多目标算法学习内容推荐: 1.通俗易懂讲算法-多目标优化-NSGA-II(附代码讲解)_哔哩哔哩_bilibili 2.多目标优化 (python pyomo pareto 最优)_哔哩哔哩_bilibili 学习笔记: 通过网盘分享的文件:多目标算法学习笔记 链接: https://pan.baidu.com…...
蓝桥杯刷题——day3
蓝桥杯刷题——day3 题目一题干题目解析代码 题目二题干题目解析代码 题目一 题干 每张票据有唯一的 ID 号,全年所有票据的 ID 号是连续的,但 ID 的开始数码是随机选定的。因为工作人员疏忽,在录入 ID 号的时候发生了一处错误,造…...

企业级日志分析系统ELK之ELK概述
ELK 概述 ELK 介绍 什么是 ELK 早期IT架构中的系统和应用的日志分散在不同的主机和文件,如果应用出现问题,开发和运维人员想排 查原因,就要先找到相应的主机上的日志文件再进行查找和分析,所以非常不方便,而且还涉及…...

【开源项目】经典开源项目数字孪生体育馆—开源工程及源码
飞渡科技数字孪生体育馆管理平台,融合物联网IOT、BIM数据模型、三维GIS等技术,实现体育馆的全方位监控和实时全局掌握,同时,通过集成设备设施管理、人员管理等子系统,减少信息孤岛,让场馆“可视、可控、可管…...

C++多线程实战:掌握图像处理高级技巧
文章结尾有最新热度的文章,感兴趣的可以去看看。 本文是经过严格查阅相关权威文献和资料,形成的专业的可靠的内容。全文数据都有据可依,可回溯。特别申明:数据和资料已获得授权。本文内容,不涉及任何偏颇观点,用中立态度客观事实描述事情本身 导读 在当今的计算世界中,…...

解决MAC装win系统投屏失败问题(AMD显卡)
一、问题描述 电脑接上HDMI线后,电脑上能显示有外部显示器接入,但是外接显示器无投屏画面 二、已测试的方法 1 更改电脑分辨,结果无效 2 删除BootCamp,结果无效 3更新电脑系统,结果无效 4 在设备管理器中&#…...
网易游戏分享游戏场景中MongoDB运行和分析实践
在游戏行业中,数据库的稳定和性能直接影响了游戏质量和用户满意度。在竞争激烈的游戏市场中,一个优秀的数据库产品无疑能为游戏的开发和后期的运营奠定良好的基础。伴随着MongoDB在不同类型游戏场景中的应用越来越广泛,许多知名的游戏公司都在…...
Android14 AOSP 允许system分区和vendor分区应用进行AIDL通信
在Android14上,出于种种原因,system分区的应用无法和vendor分区的应用直接通过AIDL的方法进行通信,但是项目的某个功能又需要如此。 好在Binder底层其实是支持的,只是在上层进行了屏蔽。 修改 frameworks/native/libs/binder/Bp…...

R学习——因子
目录 1 定义因子(factor函数) 2因子的作用 一个数据集中的 只需要考虑可以用哪个数据来进行分类就可以了,可以用来分类就可以作为因子。 Cy1这个因子对应的水平level是4 6 8: 1 定义因子(factor函数) 要…...

pytest入门三:setup、teardown
https://zhuanlan.zhihu.com/p/623447031 function对应类外的函数,每个函数调用一次 import pytest def setup_module():print(开始 module)def teardown_module():print(结束 module)def setup_function():print(开始 function)def teardown_function():print(结…...
前端面试准备问题2
1.防抖和节流分别是什么,应用场景 防抖:在事件被触发后,只有在指定的延迟时间内没有再次触发,才执行事件处理函数。 在我的理解中,简单的说就是在一个指定的时间内,仅触发一次,如果有多次重复触…...
web前端sse封装
这是一个基于microsoft/fetch-event-source包封装的sse函数,包含开始、停止功能; 可传更多参数、使用非常简单。 使用前: 安装 microsoft/fetch-event-source 代码: // sse import { fetchEventSource } from microsoft/fetch-event-source import { …...

智能家居WTR096-16S录放音芯片方案,实现语音播报提示及录音留言功能
前言: 在当今社会的高速运转之下,夜幕低垂之时,许多辛勤工作的父母尚未归家。对于肩负家庭责任的他们而言,确保孩童按时用餐与居家安全成为心头大事。此时,家居留言录音提示功能应运而生,恰似家中的一位无形…...
【创建模式-蓝本模式(Prototype Pattern)】
目录 Overview应用场景代码演示JDK Prototype pattern 更优实践泛型克隆接口 https://doc.hutool.cn/pages/Cloneable/#%E6%B3%9B%E5%9E%8B%E5%85%8B%E9%9A%86%E7%B1%BB The prototype pattern is a creational design pattern in software development. It is used when the t…...
Spring Boot应用开发深度解析与实战案例
Spring Boot应用开发深度解析与实战案例 在当今快速发展的软件开发领域,Spring Boot凭借其“约定优于配置”的理念,极大地简化了Java应用的开发、配置和部署过程,成为了微服务架构下不可或缺的技术选型。本文将深入探讨Spring Boot的核心特性、最佳实践,并通过一个具体的…...

优化Go语言中的网络连接:设置代理超时参数
网络连接优化的重要性 在分布式系统和微服务架构中,网络请求的效率直接影响到整个系统的响应速度。合理的超时设置可以防止系统在等待网络响应时陷入无限期的阻塞,从而提高系统的吞吐量和用户体验。特别是在使用代理服务器时,由于增加了网络…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...