实现功能的前置配置
- Maven版本大于3.5
- JDK大于17
- 邮箱发送验证码存储验证码所需的Redis
目录
打开SMTP服务
邮箱默认是没有打开的,这里举例163邮箱.
打开首页点击设置
选择框选的那一项
开启相应的SMTP服务,通过相关验证会出现授权码,记得把这个码保存下来,这个只会出现一次
创建SpringBoot3项目工程
这里起步依赖选择Spring web和lombok
引入依赖
在 Spring Boot 3 中整合 Email 发送功能可以使用 spring-boot-starter-mail
,它基于 JavaMail 实现邮件发送。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在application中配置邮件服务
host中如果你是qq邮箱就改成smtp.qq.com,只需修改中间的即可。根据邮件服务商调整
username注意要替换成自己的打开smtp服务的邮箱号
password不是邮箱的密码,而是打开smtp生成的授权码
port是相关的端口号
redis中password默认是没有密码的
spring:
mail:
host: smtp.163.com
port: 465
username: XXX@163.com
password: XXXX
protocol: smtp
properties:
mail:
smtp:
auth: true
ssl:
enable: true
data:
redis:
host: localhost
port: 6379
password: #默认没有密码
connect-timeout: 5000ms
database: 1
创建邮件实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Mail {
private String to;
private String subject;
private String content;
private String attachment;
}
创建邮件发送工具类
新建 MailService
类,封装邮件发送逻辑
@Service
public class MailService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private StringRedisTemplate redisTemplate; // Redis
@Value("${spring.mail.username}")
private String username;
private static final String CODE_PREFIX = "email_code:"; // Redis key 前缀
/**
* 发送普通文本
* @param mail 邮件类
* @return
* @throws MessagingException
*/
public Boolean sendTextMail(Mail mail) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage(); //创建一个 MimeMessage 对象,表示一封邮件
MimeMessageHelper helper = new MimeMessageHelper(message, false); // 第二个参数 false 表示纯文本
helper.setFrom(username);
helper.setTo(mail.getTo());
helper.setSubject(mail.getSubject());
helper.setText(mail.getContent(), true);
mailSender.send(message);
return true;
}
/**
* 发送HTML
* @param mail 邮件类
* @return
* @throws MessagingException
*/
public Boolean sendHtmlMail(Mail mail) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);// 允许HTML
helper.setFrom(username);
helper.setTo(mail.getTo());
helper.setSubject(mail.getSubject());
helper.setText("<h1>你好</h1><p>这是 <b>HTML</b> 格式的邮件!</p>", true);// 第二个参数 true 表示 HTML
mailSender.send(message);
return true;
}
/**
* 发送附件
* @param mail 邮件
* @return
* @throws MessagingException,FileNotFoundException
*/
public Boolean sendAttachmentMail(Mail mail) throws MessagingException, FileNotFoundException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(username);
helper.setTo(mail.getTo());
helper.setSubject(mail.getSubject());
helper.setText(mail.getContent(),false);
// 获取附件路径
String attachmentPath = mail.getAttachment();
// 创建 File 对象并检查是否存在
File file = new File(attachmentPath);
if (!file.exists()) {
throw new FileNotFoundException("附件文件未找到: " + attachmentPath);
}
// 创建 FileSystemResource Spring 用于读取文件的封装类,可以用来处理附件。
FileSystemResource resource = new FileSystemResource(file);
// 添加附件 file.getName()文件名 resource 文件资源
helper.addAttachment(file.getName(), resource);
mailSender.send(message);
return true;
}
/**
* 发送图片
* @param mail 邮件
* @return
* @throws MessagingException
* @throws FileNotFoundException
*/
public Boolean sendPictureMail(Mail mail) throws MessagingException, FileNotFoundException {
// 创建 MimeMessage 和 MimeMessageHelper 对象
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 获取图片路径
String picturePath = mail.getAttachment();
// 检查图片路径是否为空
if (picturePath == null || picturePath.trim().isEmpty()) {
throw new IllegalArgumentException("图片路径不能为空");
}
// 创建 File 对象并检查是否存在
File file = new File(picturePath);
if (!file.exists()) {
throw new FileNotFoundException("附件文件未找到图片: " + picturePath);
}
// 设置邮件的发件人、收件人、主题和内容
helper.setFrom(username);
helper.setTo(mail.getTo());
helper.setSubject(mail.getSubject());
helper.setText("<p>这是一封带图片的邮件:</p><img src='cid:" + file.getName() + "'/>", true); // true 表示 HTML 内容
// 如果文件存在,添加内嵌图片
FileSystemResource res = new FileSystemResource(file);
// 添加图片,确保图片名是唯一且正确的
helper.addInline(file.getName(), res); // 使用文件名作为 cid
// 发送邮件
mailSender.send(message);
return true;
}
/**
* 发送验证码
* @param to 请求邮箱地址
* @throws MessagingException
*/
public void sendVerificationCode(String to) throws MessagingException {
String code = generateCode(); // 生成 6 位验证码
// 存入 Redis,2 分钟有效 将验证码存储在 Redis 中,键名是 CODE_PREFIX + to,即基于邮箱地址作为唯一标识。
redisTemplate.opsForValue().set(CODE_PREFIX + to, code, 2, TimeUnit.MINUTES);
Mail mail = new Mail();
// 发送邮件
mail.setTo(to);
mail.setSubject("验证码");
mail.setContent("您的验证码是:" + code + ",有效期 2 分钟,请勿泄露。");
sendTextMail(mail);
}
// 生成 6 位随机验证码
private String generateCode() {
return String.valueOf(new Random().nextInt(899999) + 100000);
}
//验证验证码
public boolean verifyCode(String to, String code) {
//从 Redis 中获取指定邮箱对应的验证码。如果 Redis 中没有找到该验证码,说明验证码已经过期或不存在。
String redisCode = redisTemplate.opsForValue().get(CODE_PREFIX + to);
//如果 redisCode 为 null,则表示验证码已经过期或未生成,方法返回 false,表示验证码验证失败。
if (redisCode == null) {
return false; // 验证码已过期
}
//如果 Redis 中存在验证码,接下来就与用户传入的验证码进行比较。如果两者相等,则返回 true,表示验证码验证成功,否则返回 false。
return redisCode.equals(code);
}
}
创建Controller调用方法
测试邮件发送
@RestController
public class MailController {
@Autowired
private MailService mailService;
/**
* 发送text文本
* @param mail
* @return
* @throws MessagingException
*/
@PostMapping("/sendText")
public String sendText(@RequestBody Mail mail) throws MessagingException {
Boolean b = mailService.sendTextMail(mail);
if (!b){
return "发送失败";
}
return "发送文本成功";
}
/**
* 发送HTML
* @param mail
* @return
* @throws MessagingException
*/
@PostMapping("/sendHtml")
public String sendHtml(@RequestBody Mail mail) throws MessagingException {
Boolean b = mailService.sendHtmlMail(mail);
if (!b){
return "发送HTML失败";
}
return "发送HTML成功";
}
/**
* 发送附件
* @param mail
* @return
* @throws MessagingException
* @throws FileNotFoundException
*/
@PostMapping("/sendAttachment")
public String sendAttachment(@RequestBody Mail mail) throws MessagingException, FileNotFoundException {
Boolean b = mailService.sendAttachmentMail(mail);
if (!b){
return "发送附件失败";
}
return "发送附件成功";
}
/**
* 发送图片
* @param mail
* @return
* @throws MessagingException
* @throws FileNotFoundException
*/
@PostMapping("/sendPicture")
public String sendPicture(@RequestBody Mail mail) throws MessagingException, FileNotFoundException {
Boolean b = mailService.sendPictureMail(mail);
if (!b){
return "发送图片失败";
}
return "发送图片成功";
}
/**
* 发送验证码给指定的邮箱
* @param requestBody email-->指定的邮箱
* @return
*/
@PostMapping("/sendCode")
public String sendCode(@RequestBody Map<String ,String> requestBody) throws MessagingException {
String email = requestBody.get("email");
if (email == null||email.isEmpty()) {
return "error:email参数不能为空";
}
mailService.sendVerificationCode(email);
return "验证码已发送";
}
/**
* 验证验证码
* @param requestBody email-->指定的邮箱 code-->验证码
* @return
*/
@PostMapping("/verifyCode")
public String verifyCode(@RequestBody Map<String ,String> requestBody) {
String email = requestBody.get("email");
String code = requestBody.get("code");
if (email == null || code == null) {
return "error";
}
boolean isValid = mailService.verifyCode(email, code);
return isValid ? "验证码正确" : "验证码错误或已过期";
}
}
Postman测试
相关的测试集合我放在链接里面
打开postman点击import直接粘贴这个url就可以获取
总结
本次就是利用springboot3整合的mail依赖集成邮件功能,实现对各种类型的邮件发送。
还通过redis缓存验证码实现一个邮箱验证验证码功能。
最后的最后,新人报道欢迎大佬们指正,需要源码的私信。谢谢大家 q v q