【Email】基于SpringBoot3.4.x集成发送邮件功能
- 摘要
- 本地开发环境说明
- pom.xml
- 启动类
- application.yaml
- 写一个邮件模板
- 定义模板引擎工具类
- 定义一个邮件发送对象
- 封装一个邮件发送器
- 单元测试
- 邮件模板单元测试
- 发送邮件单元测试
- 邮件效果
- 参考资料
摘要
在业务系统开发过程中,经常有发送邮件的需求,希望可以系统在某个时候自动触发邮件,或者支持用户主动触发邮件,Spring Boot
框架提供了发送邮件的功能,通过简单的配置即可实现。
有时候不仅要发送邮件,对邮件内容格式、样式还有更高要求,我们也可以利用模板引擎来实现,比如Thymeleaf
,Freemarker
等等。
本着"最新"原则,这篇文章依然采用最新版的Spring Boot 3.4.0
,OpenJDK
最新LTS
版21
,IntelliJ IDEA
最新社区版2024.3.1
。
本地开发环境说明
开发用到的主要框架、工具版本如下
开发依赖 | 版本 |
---|---|
Spring Boot | 3.4.0 |
spring-boot-starter-mail | 3.4.0 |
spring-boot-starter-thymeleaf | 3.4.0 |
JDK | 21 |
IntelliJ IDEA | 2024.3.1 |
工程目录结构大致如下
pom.xml
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><!-- thymeleaf模板 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
</dependencies>
启动类
package com.wen3.demo.email;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** @author: tangheng*/
@SpringBootApplication
public class EmailDemoApplication {public static void main(String[] args) {SpringApplication.run(EmailDemoApplication.class, args);}
}
application.yaml
spring:mail:host: "smtp.sina.com" # 发件服务器地址,不同邮件平台地址不同port: 25 #常用邮件端口25、109、110、143、465、995、993、994 如果开启了SSL安全则使用对应的端口号,25为非加密端口号username: xxxx@sina.com #发送邮件的账号password: xxxxxxxxxxxxxxxx #发送邮件账号的授权码,这里的授权码不是验证码.需要到邮箱default-encoding: utf-8 #设置编码properties: # 设置邮件超时时间防止服务器阻塞timeout: 5000connection-timeout: 5000write-timeout: 5000mail:smtp:auth: truestarttls:enable: truerequired: true
写一个邮件模板
email-template.html
内容如下
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>[[${title}]]</title>
</head>
<body>
<div style="background-color:#ECECEC; padding: 15px;"><table cellpadding="0" align="center"style="width: 600px; margin: 0px auto; text-align: left; position: relative; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; font-size: 14px; font-family:微软雅黑, 黑体; line-height: 1.5; box-shadow: rgb(153, 153, 153) 0px 0px 5px; border-collapse: collapse; background-position: initial initial; background-repeat: initial initial;background:#fff;"><tbody><tr><th valign="middle"style="height: 25px; line-height: 25px; padding: 15px 35px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #42a3d3; background-color: #49bcff; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px;"><font face="微软雅黑" size="5" style="color: rgb(255, 255, 255); ">测试邮件</font></th></tr><tr><td><div style="padding:25px 35px 40px; background-color:#fff;"><h2 style="margin: 5px 0px; "><font color="#333333" style="line-height: 20px; "><font style="line-height: 22px; " size="4">亲爱的<b>[[${email}]]</b>用户,您好:</font></font></h2><p>首先感谢您加入【运维自助平台】!请在验证页面输入以下验证码:<br><b style="font-size: 18px">[[${code}]]</b><br>本验证码5分钟内有效,为了保障您的账户安全,请勿向任何人提供此验证码。感谢您的支持!<br>如果您有什么疑问可以联系管理员,Email: admin@xxx.com</p><p align="right">运维自助平台</p><p align="right">[[${date}]]</p><div style="width:700px;margin:0 auto;"><div style="padding:10px 10px 0;border-top:1px solid #ccc;color:#747474;margin-bottom:20px;line-height:1.3em;font-size:12px;"><p>本邮件系统自动发送,请勿回复!<br>请保管好您的邮箱,避免账号被他人盗用</p><p>©运维自助平台</p></div></div></div></td></tr></tbody></table>
</div>
</body>
</html>
定义模板引擎工具类
TemplateUtil.java
内容如下
package com.wen3.demo.email.template;import cn.hutool.core.date.DateUtil;
import jakarta.annotation.Resource;
import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;import java.util.Date;/*** @author: tangheng*/
@Service
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TemplateUtil {@Resourceprivate TemplateEngine templateEngine;/*** 获得验证码模板*/public String getCaptchaTempl(String email, String code) {Context context = new Context();//设置模板所需的参数context.setVariable("title","验证码");context.setVariable("email",email);context.setVariable("code",code);context.setVariable("date", DateUtil.format(new Date(),"yyyy-MM-dd hh:mm:ss"));//通过模板类将动态参数传入HTML模板,并返回模板内容 参数一:模板名字,参数二:动态参数Web文本String content = templateEngine.process("/email-template", context);return content;}
}
定义一个邮件发送对象
package com.wen3.demo.email.dto;import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.FieldDefaults;
import lombok.experimental.SuperBuilder;import java.util.List;/*** 邮件发送对象** @author: tangheng*/
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@SuperBuilder
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class EMailCmd {List<String> tos;String subject;String text;
}
封装一个邮件发送器
package com.wen3.demo.email.sender;import com.wen3.demo.email.dto.EMailCmd;
import jakarta.annotation.Resource;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.AccessLevel;
import lombok.SneakyThrows;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
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.Service;/*** @author: tangheng*/
@Slf4j
@Service
@FieldDefaults(level = AccessLevel.PRIVATE)
public class EmailSender {@ResourceJavaMailSender mailSender;public void sendEMail(EMailCmd eMailCmd) {try {SimpleMailMessage simpleMailMessage = new SimpleMailMessage();simpleMailMessage.setFrom("太空眼睛<best5721@sina.com>"); //设置发送邮件账号simpleMailMessage.setTo(eMailCmd.getTos().toArray(String[]::new)); //设置接收邮件的人,可以多个simpleMailMessage.setSubject(eMailCmd.getSubject()); //设置发送邮件的主题simpleMailMessage.setText(eMailCmd.getText()); //设置发送邮件的内容mailSender.send(simpleMailMessage);} catch (MailException e) {log.error("邮件发送失败!");}}@SneakyThrowspublic void sendHtmlEMail(EMailCmd eMailCmd) {try {MimeMessage message = mailSender.createMimeMessage();MimeMessageHelper minehelper = new MimeMessageHelper(message, true);minehelper.setFrom("太空眼睛<best5721@sina.com>");
// minehelper.setFrom("best5721@sina.com", "太空眼睛");minehelper.setTo(eMailCmd.getTos().toArray(String[]::new)); //设置接收邮件的人,可以多个minehelper.setSubject(eMailCmd.getSubject()); //设置发送邮件的主题minehelper.setText(eMailCmd.getText(),true); //设置发送邮件的内容 第二个设置为true则可以发送带HTML的邮件mailSender.send(message);} catch (MessagingException e) {log.error("邮件发送失败!");}}
}
邮件地址的格式可以写成
best5721@sina.com
也可以写成太空眼睛<best5721@sina.com>
单元测试
邮件模板单元测试
package com.wen3.demo.email.template;import cn.hutool.core.util.RandomUtil;
import com.wen3.demo.email.EmailDemoSpringBootTestBase;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.*;class TemplateUtilTest extends EmailDemoSpringBootTestBase {@ResourceTemplateUtil templateUtil;@Testvoid getCaptchaTempl() {String email = "tangheng";String code = RandomUtil.randomNumbers(5);String testResult = templateUtil.getCaptchaTempl(email,code);log.info("testResult: {}", testResult);assertNotNull(testResult);}
}
发送邮件单元测试
package com.wen3.demo.email.sender;import cn.hutool.core.util.RandomUtil;
import com.wen3.demo.email.EmailDemoSpringBootTestBase;
import com.wen3.demo.email.dto.EMailCmd;
import com.wen3.demo.email.template.TemplateUtil;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.mail.MailProperties;import java.util.List;import static org.junit.jupiter.api.Assertions.*;class EmailSenderTest extends EmailDemoSpringBootTestBase {@ResourceEmailSender emailSender;@ResourceTemplateUtil templateUtil;@ResourceMailProperties mailProperties;@Testvoid sendHtmlEMail() {String to = "friendly1234@126.com";EMailCmd eMailCmd = EMailCmd.builder().tos(List.of(to)).subject("测试邮件").text(templateUtil.getCaptchaTempl(to, RandomUtil.randomNumbers(5))).build();emailSender.sendHtmlEMail(eMailCmd);}
}
邮件效果
参考资料
- SpringBoot集成EMail