SpringBoot整合(三)SpringBoot发送邮件
使用SpringBoot发送邮件
邮件发送其实是一个非常常见的需求,用户注册,找回密码等地方,都会用到,Spring Boot 中对于邮件发送,提供了相关的自动化配置类,使得邮件发送变得非常容易。
1、前置工作
目前国内大部分的邮件服务商都不允许直接使用用户名/密码的方式来在代码中发送邮件,都是要先申请授权码,这里以 QQ 邮箱为例,向大家演示授权码的申请流程:
首先我们需要先登录 QQ 邮箱网页版,点击上方的设置按钮:然后点击账户选项卡:在账户选项卡中找到开启POP3/SMTP选项,如下:
点击开启,开启相关功能,开启过程需要手机号码验证,按照步骤操作即可,不赘述。开启成功之后,即可获取一个授权码,将该号码保存好,一会使用。
2、引入依赖、配置邮箱基本信息
<!--集成发送邮件的功能-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId>
</dependency>
然后在yml配置文件中进行配置
spring:mail:host: smtp.qq.com # 设置邮箱主机port: 587 # SMTP 服务器的端口username: yyds@qq.com # 设置用户名password: yyds # 设置密码,该处的密码是QQ邮箱开启SMTP的授权码而非QQ密码mail:from: ${spring.mail.username}to: yyds@163.com
做完这些之后,Spring Boot 就会自动帮我们配置好邮件发送类,相关的配置在
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration
类中,部分源码如下:
@Configuration
@ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class })
@ConditionalOnMissingBean(MailSender.class)
@Conditional(MailSenderCondition.class)
@EnableConfigurationProperties(MailProperties.class)
@Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class })
public class MailSenderAutoConfiguration {}
可以看到,导入了另外一个配置 MailSenderPropertiesConfiguration
类,这个类中,提供了邮件发送相关的工具类,源码如下:
@Configuration
@ConditionalOnProperty(prefix = "spring.mail", name = "host")
class MailSenderPropertiesConfiguration {private final MailProperties properties;MailSenderPropertiesConfiguration(MailProperties properties) {this.properties = properties;}@Bean@ConditionalOnMissingBeanpublic JavaMailSenderImpl mailSender() {JavaMailSenderImpl sender = new JavaMailSenderImpl();applyProperties(sender);return sender;}
}
可以看到,这里创建了一个 JavaMailSenderImpl
的实例, JavaMailSenderImpl
是 JavaMailSender
的一个实现,我们将使用 JavaMailSenderImpl
来完成邮件的发送工作。
3、Service层代码
自定义的MailProperties配置类,用于解析mail开头的配置属性
package com.yyds.domain;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "mail")
public class MailProperties {private String from;private String to;}
service层
package com.yyds.service;import freemarker.template.TemplateException;import javax.mail.MessagingException;
import java.io.IOException;
import java.util.Map;public interface MailService {void sendSimpleMail(String subject, String text) ;void sendHtmlMail(String subject, String text, Map<String, String> attachmentMap) throws MessagingException;void sendTemplateMail(String subject, Map<String, Object> params) throws MessagingException, IOException, TemplateException;
}
package com.yyds.service.impl;import com.yyds.domain.MailProperties;
import com.yyds.service.MailService;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
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.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
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.util.Map;@Service
public class MailServiceImpl implements MailService {@Autowiredprivate JavaMailSender javaMailSender;@Autowiredprivate MailProperties myMailProperties;/*** 发送简单文本邮件*/@Overridepublic void sendSimpleMail(String subject, String text) {SimpleMailMessage mailMessage = new SimpleMailMessage();mailMessage.setFrom(myMailProperties.getFrom());mailMessage.setTo(myMailProperties.getTo());mailMessage.setSubject(subject);mailMessage.setText(text);javaMailSender.send(mailMessage);}/*** 发送带有链接和附件的复杂邮件*/@Overridepublic void sendHtmlMail(String subject, String text, Map<String, String> attachmentMap) throws MessagingException {MimeMessage mimeMessage = javaMailSender.createMimeMessage();//是否发送的邮件是富文本(附件,图片,html等)MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);messageHelper.setFrom(myMailProperties.getFrom());messageHelper.setTo(myMailProperties.getTo());messageHelper.setSubject(subject);messageHelper.setText(text, true);//重点,默认为false,显示原始html代码,无效果if(attachmentMap != null){attachmentMap.entrySet().stream().forEach(entrySet -> {try {File file = new File(entrySet.getValue());if(file.exists()){messageHelper.addAttachment(entrySet.getKey(), new FileSystemResource(file));}} catch (MessagingException e) {e.printStackTrace();}});}javaMailSender.send(mimeMessage);}/*** 发送模版邮件*/@Overridepublic void sendTemplateMail(String subject, Map<String, Object> params) throws MessagingException, IOException, TemplateException {MimeMessage mimeMessage = javaMailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);helper.setFrom(myMailProperties.getFrom());helper.setTo(myMailProperties.getTo());freemarker.template.Configuration configuration = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_19);TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), "/templates/");configuration.setTemplateLoader(templateLoader);Template template = configuration.getTemplate("mail.ftl");String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, params);helper.setSubject(subject);helper.setText(html, true);//重点,默认为false,显示原始html代码,无效果javaMailSender.send(mimeMessage);}
}
4、发送邮件
4.1 测试发送简单文本邮件
@SpringBootTest(classes = BootStartApplication.class)
public class MimeMailTest {@Autowiredprivate MailService mailService;@Testpublic void sendMail() {mailService.sendSimpleMail("测试Springboot发送邮件", "发送邮件...");}
}
4.2 测试发送带有链接和附件的复杂邮件
package com.yyds;import com.yyds.service.MailService;
import freemarker.template.TemplateException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import javax.mail.MessagingException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@SpringBootTest(classes = BootStartApplication.class)
public class MimeMailTest {@Autowiredprivate MailService mailService;@Testpublic void testMail() throws MessagingException {Map<String, String> attachmentMap = new HashMap<>();attachmentMap.put("附件", "D:\\D_ENL_MRO数据统计.xlsx");mailService.sendHtmlMail("测试Springboot发送带附件的邮件2", "欢迎进入<a href=\"http://www.baidu.com\">百度首页</a>", attachmentMap);}}
4.3 测试发送发送模版邮件
首先需要引入 Freemarker 依赖:
<!--整合freemarker--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency>
然后在 resources/templates
目录下创建一个 mail.ftl
作为邮件发送模板:
<html><body><h3>你好, <span style="color: red;">${username}</span>, 这是一封模板邮件!</h3></body>
</html>
package com.yyds;import com.yyds.service.MailService;
import freemarker.template.TemplateException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import javax.mail.MessagingException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@SpringBootTest(classes = BootStartApplication.class)
public class MimeMailTest {@Autowiredprivate MailService mailService;@Testpublic void testFreemarkerMail() throws MessagingException, IOException, TemplateException {Map<String, Object> params = new HashMap<>();params.put("username", "Tom");mailService.sendTemplateMail("测试Springboot发送模版邮件", params);}}
相关文章:

SpringBoot整合(三)SpringBoot发送邮件
使用SpringBoot发送邮件 邮件发送其实是一个非常常见的需求,用户注册,找回密码等地方,都会用到,Spring Boot 中对于邮件发送,提供了相关的自动化配置类,使得邮件发送变得非常容易。 1、前置工作 目前国内…...

【docker知识】联合文件系统(unionFS)原理
一、说明 Docker CLI 操作起来比较简单——您只需掌握Create、Run、InspPull和Push容器和图像,但是谁想过Docker 背后的内部机制是如何工作的?在这个简单的表象背后隐藏着许多很酷的技术, UnionFS(统一文件系统)就是其…...

使用Lame库实现wav、pcm转mp3
文章目录 前言 一、Lame库是什么? 二、使用步骤 0.创建native项目 1.下载Lame库 2.pcm转MP3 3.wav转MP3 4、native方法如下 三、注意 总结 前言 因为使用android录音后生成的文件是wav或者pcm格式,项目要求最后的文件需要是mp3格式,于…...

c++11 标准模板(STL)(std::multimap)(三)
定义于头文件 <map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class multimap;(1)namespace pmr { template <class Key, class T…...

【报复性赚钱】2023年5大风口行业
今天就来和大家分享一下,在时代的洪流下,普通人如何顺应大势抓住机遇! 实现人在风口上,猪都会飞起来。 根据对市场的观察及各平台数据分析结果,结合国家政策和经济专家的分析,小编预测了2023年将会迎来大…...

单目相机、双目相机和RGB-D相机学习笔记(一些视频和博文网址)
目录1. 单目相机1.1 摄像头原理1.2 单目相机的标定2 双目相机2.1 双目相机定位原理2.2 双目相机的缺陷3 RGB-D相机3.1 深度相机结构光原理3.2 RGB-D相机的应用1. 单目相机 1.1 摄像头原理 视频网址:【全网最详细】摄像头原理分析(约25分钟课程…...

word和wps添加mathtype选项卡
word或wps添加mathtype选项卡 前提 安装好word或wps安装好mathtype 步骤 确认word或wps具体安装位置确认word或wps位数为32位还是64位复制mathtype中的MathPage.wll文件和MathType Commands 2016.dotm文件到STARTUP位置添加受信任位置添加加载项 安装位置 通过开始页面&a…...

获取成员userID
文章目录一、简介二、获取token1、获取秘钥2、获取Token三、获取部门数据1、获取部门列表2、获取子部门ID列表3、获取单个部门详情四、获取成员信息1、读取成员2、获取部门成员3、获取部门成员详情一、简介 同步数据到企微: 企业如果需要从自有的系统同步通讯录到…...

DOM编程-显示网页时钟
<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>显示网页时钟</title> </head> <body bgcolor"antiquewhite"> <script type"text/javascrip…...

浅谈保护数据的加密策略
加密是一种将信息从可读格式转换为混乱字符串的技术。这样做可以防止数据传输中的机密数据泄露。文档、文件、消息和所有其他形式的网络通信都可以加密。加密策略和身份验证服务的结合,还能保障企业机密信息只对授权用户开启访问权限。常见的数据加密包括以下两种&a…...
Java中String,StringBuffer和StringBuilder
String类 我们在定义string变量时 常常写 String str "hello word"; 这样的代码,看起来和int a 0; 是一样的声明方式, 但其实两者是不同的, int 是java中定义的基本数据类型, 而String是一个类,是一个特殊的类,可以像基本数据类型一样直接赋…...

华为认证常见技术问答整理:什么是Datacom认证?
一、关于Datacom认证Q:什么是Datacom认证?A:Datacom,即DatacomCommunication的缩写,中文为“数据通信”,属于ICT技术架构认证类别(华为认证包含ICT技术架构认证、平台与服务认证和行业ICT认证三…...
Read book Netty in action (Chapter II) (Netty Introduction)
前言 支持15W的并发客户端,我们应该视为理所当然的事情,很多公司甚至能够支撑更多,例如我们熟知的 BAT,当几年前双十一的夜晚,并发量是不可估计的。还有春节的时候购票的时候的并发。作为一个优秀的开发人员ÿ…...
python--route
routes是用python重新实现的Rails routes系统,用于将url映射到应用程序的actions ,并反过来生成url 它也是在openstack实现restful通信的方式,它被用来做将 URL 映射为 App 的 action,以及为 App的action 产生 URL 两个重要的方法…...

java面试中被问到项目中的难点,怎么回答
java面试中被问到项目中的难点,怎么回答回答步骤举例说明回答步骤 回答这个问题的方法取决于你的项目的类型和难度。 但是,一般来说,你可以遵循以下步骤来回答这个问题: 描述你的项目:首先简要描述你的项目的类型和目…...

【速通版】吴恩达机器学习笔记Part1
准备速通一下吴恩达的机器学习 很快做个笔记5.2.3 监督学习 part 2_哔哩哔哩_bilibili 目录 1.概述(P1-P3) 2.supervised learning:(P4,P5) regression: classification 3.unsupervised learning (P6- 1.聚类算…...

面试(九)小米C++开发一面 21.11.02
1、局部变量与全局变量的区别?可以同名嘛? 首先是作用域: 局部变量只在变量声明的代码块范围内生效 全局变量在其声明后的所有位置都能访问到 在局部变量与全局变量同名的情况下,全局变量会被屏蔽掉,只会使用局部变量的内容 2、extern 当在a.c中想要使用b.c中的函数fu…...

儿童书写台灯哪个牌子比较好?2023儿童护眼台灯分享
现在儿童的近视率高达52.7%,有科技水平的提高和电子产品的普及,近视率逐年攀升,出现低龄化现象,调查结果显示,其中6岁儿童达到14.3%,小学生为35.6%。初中生71.1%,高中生高达80.5%,可…...

市场调研计划书如何写?
想要做好一个产品,市场调研是必不可少的一步,也是第一步,那么如何进行市场调研呢?以下是我整理的一份市场调研计划书,希望能够帮助到大家!!! 一、文档版本控制 主要记录文档的版本…...

python网络爬虫—快速入门(理论+实战)(七)
系列文章目录 (1)python网络爬虫—快速入门(理论实战)(一) (2)python网络爬虫—快速入门(理论实战)(二) (3) p…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...

mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...