使用Spring Boot发送邮件
在项目的维护过程中,我们通常会在应用中加入短信或者邮件预警功能,比如当应用出现异常宕机时应该及时地将预警信息发送给运维或者开发人员,本文将介绍如何在Spring Boot中发送邮件。在Spring Boot中发送邮件使用的是Spring提供的org.springframework.mail.javamail.JavaMailSender
,其提供了许多简单易用的方法,可发送简单的邮件、HTML格式的邮件、带附件的邮件,并且可以创建邮件模板。
引入依赖
在Spring Boot中发送邮件,需要用到spring-boot-starter-mail
,引入spring-boot-starter-mail
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
邮件配置
在application.yml(因为配置文件中整合了freemarker和thymeleaf的配置 可忽略)中进行简单的配置(以qq邮件为例):
#服务端口
server:
port: 8005
#springboot 整合发送邮件 配置
mail:
host: smtp.qq.com
username: 你的qq账号
password: 你的授权码
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
# springboot 整合 thymeleaf 详解配置查看 static/thymeleaf配置详解.text
thymeleaf:
prefix: classpath:/templates/
suffix: .html
check-template-location: true
encoding: UTF-8
mode: HTML5
#开启模板缓存(默认值:true)
cache: false
servlet:
content-type: text/html
template-resolver-order: 2
# springboot 整合 freemarker 详解配置查看 static/freemarker配置详解.text
freemarker:
template-loader-path: classpath:/templates/
suffix: .ftl
cache: false
charset: UTF-8
check-template-location: true
content-type: text/html
expose-request-attributes: true
expose-session-attributes: true
request-context-attribute: request
#Redis配置
redis:
host: 127.0.0.1
port: 6379
database: 0
timeout: 1800000
lettuce:
pool:
max-active: 20
max-wait: -1
#最大阻塞等待时间(负数表示没有限制)
max-idle: 5
min-idle: 0
1、发送简单的邮件
编写EmailController
,注入JavaMailSender
:
package com.atguigu.msmservice.controller;
import freemarker.template.Template;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
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.servlet.view.freemarker.FreeMarkerConfigurer;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @Author panghl
* @Date 2021/2/3 14:11
* @Description TODO
**/
@RestController
@RequestMapping("/mail")
@Api(tags = {"邮箱管理"})
@CrossOrigin
public class MailController {
@Autowired
private JavaMailSender jms;
@Value("${spring.mail.username}")
private String from;
@ApiOperation(value = "使用Spring Boot发送简单邮件。")
@PostMapping("/sendSimpleEmail")
public String sendSimpleEmail() {
try {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo("88888888@qq.com"); // 接收地址
message.setSubject("一封简单的邮件"); // 标题
message.setText("使用Spring Boot发送简单邮件。"); // 内容
jms.send(message);
return "发送成功";
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}
启动项目访问http://localhost:8005/email/sendSimpleEmail,提示发送成功:
2、发送HTML格式的邮件
改造EmailController
,SimpleMailMessage
替换为MimeMessage
package com.atguigu.msmservice.controller;
import freemarker.template.Template;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
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.servlet.view.freemarker.FreeMarkerConfigurer;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @Author panghl
* @Date 2021/2/3 14:11
* @Description TODO
**/
@RestController
@RequestMapping("/mail")
@Api(tags = {"邮箱管理"})
@CrossOrigin
public class MailController {
@Autowired
private JavaMailSender jms;
@Value("${spring.mail.username}")
private String from;
@PostMapping("/sendHtmlEmail")
@ApiOperation(value = "一封HTML格式的邮件")
public String sendHtmlEmail() {
MimeMessage message = null;
try {
message = jms.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo("88888888@qq.com"); // 接收地址
helper.setSubject("一封HTML格式的邮件"); // 标题
// 带HTML格式的内容
StringBuffer sb = new StringBuffer("<p style='color:#6db33f'>使用Spring Boot发送HTML格式邮件。</p>");
helper.setText(sb.toString(), true);
jms.send(message);
return "发送成功";
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}
3、发送带附件的邮件
发送带附件的邮件和普通邮件相比,其实就只是多了个传入附件的过程。不过使用的仍是MimeMessage
package com.atguigu.msmservice.controller;
import freemarker.template.Template;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
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.servlet.view.freemarker.FreeMarkerConfigurer;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @Author panghl
* @Date 2021/2/3 14:11
* @Description TODO
**/
@RestController
@RequestMapping("/mail")
@Api(tags = {"邮箱管理"})
@CrossOrigin
public class MailController {
@Autowired
private JavaMailSender jms;
@Value("${spring.mail.username}")
private String from;
@PostMapping("/sendAttachmentsMail")
@ApiOperation(value = "一封带附件的邮件")
public String sendAttachmentsMail() {
MimeMessage message = null;
try {
message = jms.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo("88888888@qq.com"); // 接收地址
helper.setSubject("一封带附件的邮件"); // 标题
helper.setText("详情参见附件内容!"); // 内容
// 传入附件
FileSystemResource file = new FileSystemResource(new File("D:\\axis.log"));
helper.addAttachment("axis.log", file);
jms.send(message);
return "发送成功";
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}
4、发送带静态资源的邮件
发送带静态资源的邮件其实就是在发送HTML邮件的基础上嵌入静态资源(比如图片),嵌入静态资源的过程和传入附件类似,唯一的区别在于需要标识资源的cid:
package com.atguigu.msmservice.controller;
import freemarker.template.Template;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
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.servlet.view.freemarker.FreeMarkerConfigurer;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @Author panghl
* @Date 2021/2/3 14:11
* @Description TODO
**/
@RestController
@RequestMapping("/mail")
@Api(tags = {"邮箱管理"})
@CrossOrigin
public class MailController {
@Autowired
private JavaMailSender jms;
@Value("${spring.mail.username}")
private String from;
@PostMapping("sendInlineMail")
@ApiOperation(value = "一封带静态资源的邮件")
public String sendInlineMail() {
MimeMessage message = null;
try {
message = jms.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo("88888888@qq.com"); // 接收地址
helper.setSubject("一封带静态资源的邮件"); // 标题
helper.setText("<html><body>请看图:<img src='cid:img'/></body></html>", true); // 内容
// 传入附件
FileSystemResource file = new FileSystemResource(new File("D:\\2021毕设\\网络学习平台\\01.jpg"));
helper.addInline("img", file);
jms.send(message);
return "发送成功";
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}
5、使用模板发送邮件
1、Thymeleaf
在发送验证码等情况下可以创建一个邮件的模板,唯一的变量为验证码。这个例子中使用的模板解析引擎为Thymeleaf,所以首先引入Thymeleaf依赖:
<!--thymeleaf模板启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
在templates目录下创建一个emailTemplate.html
模板:
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>thymeleaf模板</title>
</head>
<body>
您好,您的验证码为<span th:text="${code}"></span>,请在五分钟内使用完成操作。
</body>
</html>
发送模板邮件,本质上还是发送HTML邮件,只不过多了绑定变量的过程,详细如下所示
package com.atguigu.msmservice.controller;
import freemarker.template.Template;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
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.servlet.view.freemarker.FreeMarkerConfigurer;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @Author panghl
* @Date 2021/2/3 14:11
* @Description TODO
**/
@RestController
@RequestMapping("/mail")
@Api(tags = {"邮箱管理"})
@CrossOrigin
public class MailController {
@Autowired
private JavaMailSender jms;
@Value("${spring.mail.username}")
private String from;
@Autowired
private TemplateEngine templateEngine;
//发送邮件的模板引擎
@Autowired
private FreeMarkerConfigurer configurer;
@PostMapping("sendThymeleafEmail")
@ApiOperation(value = "thymeleaf邮件模板测试")
public String sendThymeleafEmail(String code) {
MimeMessage message = null;
try {
message = jms.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo("88888888@qq.com"); // 接收地址
helper.setSubject("thymeleaf邮件模板测试"); // 标题
// 处理邮件模板
Context context = new Context();
context.setVariable("code", code);
String template = templateEngine.process("emailTemplate", context);
helper.setText(template, true);
jms.send(message);
return "发送成功";
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}
2、Freemarker
在发送验证码等情况下可以创建一个邮件的模板,唯一的变量为验证码。这个例子中使用的模板解析引擎为Thymeleaf,所以首先引入Thymeleaf依赖:
<!--freemarker模板启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
在templates目录下创建一个emailTemplate.ftl
模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>freemarker模板</title>
</head>
<body>
您好,您的验证码为 ${code} ,请在五分钟内使用完成操作。
</body>
</html>
发送模板邮件,本质上还是发送HTML邮件,只不过多了绑定变量的过程,详细如下所示
package com.atguigu.msmservice.controller;
import freemarker.template.Template;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
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.servlet.view.freemarker.FreeMarkerConfigurer;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @Author panghl
* @Date 2021/2/3 14:11
* @Description TODO
**/
@RestController
@RequestMapping("/mail")
@Api(tags = {"邮箱管理"})
@CrossOrigin
public class MailController {
@Autowired
private JavaMailSender jms;
@Value("${spring.mail.username}")
private String from;
//发送邮件的模板引擎
@Autowired
private FreeMarkerConfigurer configurer;
@PostMapping("sendFreemarkerEmail")
@ApiOperation(value = "freemarker邮件模板测试")
public String sendFreemarkerEmail(String code) {
MimeMessage message = null;
try {
message = jms.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo("88888888@qq.com"); // 接收地址
helper.setSubject("freemarker邮件模板测试"); // 标题
// 处理邮件模板
Map<String,String> map = new HashMap<>();
map.put("code",code);
Template template = configurer.getConfiguration().getTemplate("emailTemplate.ftl");
String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
helper.setText(text, true);
jms.send(message);
return "发送成功";
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}
在线教育项目发送邮箱代替短信服务代码整合
1、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!--freemarker模板启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
2、配置文件
#服务端口
server:
port: 8005
#服务名
spring:
application:
name: service-sms
#服务地址
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
#返回json的全局时间格式
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
#springboot 整合发送邮件 配置
mail:
subject: 在线教育平台
host: smtp.qq.com
username: phl0425@qq.com
password: ccbtlgxmwwafffec
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
#Redis配置
redis:
host: 127.0.0.1
port: 6379
database: 0
timeout: 1800000
lettuce:
pool:
max-active: 20
max-wait: -1
#最大阻塞等待时间(负数表示没有限制)
max-idle: 5
min-idle: 0
3、Controller
package com.atguigu.msmservice.controller;
import com.atguigu.common.R;
import com.atguigu.msmservice.service.EmailService;
import com.atguigu.msmservice.utils.RandomUtil;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @Author panghl
* @Date 2021/2/3 16:51
* @Description 登录注册发送邮件
**/
@RestController
@RequestMapping("edumail/email")
@Api(tags = {"在线教育邮件管理"})
public class EmailController {
@Autowired
private EmailService emailService;
@Autowired
private RedisTemplate<String, String> redisTemplate;
@PostMapping("/{sendTo}")
public R sendEmail(@PathVariable("sendTo") String sendTo) {
String code = redisTemplate.opsForValue().get(sendTo);
if (!StringUtils.isEmpty(code)) {
R.ok();
}
code = RandomUtil.getSixBitRandom();
Map<String, Object> map = new HashMap<>();
map.put("code", code);
boolean isSuccess = emailService.sendCodeByEmail(map, sendTo);
if (isSuccess) {
redisTemplate.opsForValue().set(sendTo,code,5, TimeUnit.MINUTES);
return R.ok();
} else {
return R.error();
}
}
}
4、Service
package com.atguigu.msmservice.service.impl;
import com.atguigu.msmservice.service.EmailService;
import com.atguigu.msmservice.utils.ConstantPropertiesUtils;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
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.internet.MimeMessage;
import java.util.Map;
/**
* @Author panghl
* @Date 2021/2/3 16:53
**/
@Service
public class EmailServiceImpl implements EmailService {
@Autowired
private FreeMarkerConfigurer configurer;
@Autowired
private JavaMailSender jms;
@Override
public boolean sendCodeByEmail(Map<String, Object> map, String sendTo) {
MimeMessage message = null;
try {
message = jms.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(ConstantPropertiesUtils.USERNAME);
// 接收地址
helper.setTo(sendTo);
// 标题
helper.setSubject(ConstantPropertiesUtils.SUBJECT);
// 处理邮件模板
Template template = configurer.getConfiguration().getTemplate("emailTemplate.ftl");
String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
helper.setText(text, true);
jms.send(message);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
5、模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>freemarker模板</title>
</head>
<body>
您好,您的验证码为 ${code} ,请在五分钟内使用完成操作。
</body>
</html>