SpringBoot3整合Email

实现功能的前置配置

  • Maven版本大于3.5
  • JDK大于17
  • 邮箱发送验证码存储验证码所需的Redis

目录

实现功能的前置配置

打开SMTP服务

创建SpringBoot3项目工程

引入依赖

在application中配置邮件服务

创建邮件实体类

创建邮件发送工具类

创建Controller调用方法

Postman测试

总结


打开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测试

相关的测试集合我放在链接里面

http://verification.strcy.cn/share/mail.postman_collection.json

打开postman点击import直接粘贴这个url就可以获取

总结

本次就是利用springboot3整合的mail依赖集成邮件功能,实现对各种类型的邮件发送。

还通过redis缓存验证码实现一个邮箱验证验证码功能。

最后的最后,新人报道欢迎大佬们指正,需要源码的私信。谢谢大家 q v q 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值