Spring Boot 整合网易163邮箱发送邮件实现找回密码功能

在开发用户系统时,发送邮件是一项常见需求,例如用户忘记密码时,通过邮箱发送验证码来验证身份并重置密码。本文将结合 Spring Boot 和 163 邮箱,演示如何实现邮件发送功能。


一、前提条件

普通用户的 163 邮箱可以在 Spring Boot 项目中用于发送邮件,但需要完成以下配置:

1. 登录 163 邮箱

使用普通账号登录 163 邮箱官网

2. 开启 SMTP 服务

  1. 点击邮箱右上角「设置」→「POP3/SMTP/IMAP」;
  2. 在 SMTP 服务选项中勾选「开启 SMTP 服务」;
  3. 按提示完成手机验证(163 邮箱要求绑定手机号才能开启该服务)。

3. 获取授权码

  1. 开启 SMTP 后,页面会提示生成授权码;
  2. 按照提示生成 16 位授权码(例如 abcdefghijklmnop),保存好;
  3. 该授权码将在 Spring Boot 邮件配置中替代邮箱密码。

⚠️ 注意:普通 163 邮箱每天发送量有限,适合开发和测试用途。


二、Spring Boot 邮件依赖

pom.xml 中添加 Spring Boot 邮件依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

三、Spring Boot 邮件配置

application.ymlapplication.properties 中添加 163 邮箱 SMTP 配置:

yaml 复制代码
spring:
# 配置邮箱服务器,账号密码等
  mail:
    host: smtp.163.com
    username: 1888888888@163.com
    password: agagtfgsdhd
    code:
      overtime: 5

其中 password 是生成的授权码,而非邮箱密码。


四、邮件发送服务实现

创建 MailService 接口:

java 复制代码
public interface MailService {
    Result<String> getCode(String username, String mailAddress);
}

创建 MailServiceImpl 实现类:

java 复制代码
@Service
public class MailServiceImpl implements MailService {

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Value("${spring.mail.username}")
    private String mailUserName;

    @Value("${spring.mail.code.overtime}")
    private Integer overtime; // 验证码过期时间(分钟)

    @Override
    public Result<String> getCode(String username, String mailAddress) {
        // 校验用户名和邮箱
        if (StringUtils.isBlank(username)) return Result.fail("账号不能为空!");
        if (StringUtils.isBlank(mailAddress)) return Result.fail("邮箱不能为空!");
        
        User user = userMapper.selectUserByUsername(username);
        if (user == null) return Result.fail("账号不存在!");
        if (!user.getEmail().equals(mailAddress)) return Result.fail("输入邮箱和预留邮箱不一致!");

        // 生成验证码
        String verifyCode = redisTemplate.opsForValue().get("MAIL_CODE_" + username);
        if (verifyCode == null) {
            verifyCode = String.valueOf(new Random().nextInt(899999) + 100000);
        }
        redisTemplate.opsForValue().set("MAIL_CODE_" + username, verifyCode, overtime, TimeUnit.MINUTES);

        // 构建邮件内容
        String content = "<html><body>"
                + "您好<br/>"
                + "您的验证码是:" + verifyCode + "<br/>"
                + "在" + overtime + "分钟内有效,请尽快使用。<br/>"
                + "若非本人操作,请忽略此邮件。"
                + "</body></html>";

        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(mailUserName);
            helper.setTo(mailAddress);
            helper.setSubject("找回密码验证码");
            helper.setText(content, true);
            mailSender.send(message);
        } catch (MessagingException e) {
            e.printStackTrace();
            return Result.fail("邮件发送失败!");
        }

        return Result.ok("验证码已发送至邮箱:" + mailAddress);
    }
}

五、邮件控制器

java 复制代码
@RestController
@RequestMapping("/mail")
public class MailController {

    @Autowired
    private MailService mailService;

    @GetMapping("/getCode")
    @ApiOperation("获取重置密码验证码")
    public Result<String> getCode(String username, String mailAddress){
        return mailService.getCode(username, mailAddress);
    }
}

六、Redis 验证码存储

  • 使用 StringRedisTemplate 存储验证码:

    • Key: MAIL_CODE_用户名
    • Value: 验证码
    • TTL: spring.mail.code.overtime 分钟
  • 发送邮件后验证码会被存入 Redis,用户提交时进行比对。

相关推荐
计算机编程小咖几秒前
《基于大数据的农产品交易数据分析与可视化系统》选题不当,毕业答辩可能直接挂科
java·大数据·hadoop·python·数据挖掘·数据分析·spark
新法国菜11 分钟前
MySql知识梳理之DML语句
数据库·mysql
老华带你飞17 分钟前
校园交友|基于SprinBoot+vue的校园交友网站(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·校园交友网站
许泽宇的技术分享28 分钟前
Text2API与Text2SQL深度对比:自然语言驱动的数据交互革命
数据库·windows·microsoft
川石课堂软件测试40 分钟前
技术干货|使用Prometheus+Grafana监控Tomcat实例详解
redis·功能测试·单元测试·tomcat·测试用例·grafana·prometheus
zhangfeng11331 小时前
以下是基于图论的归一化切割(Normalized Cut)图像分割工具的完整实现,结合Tkinter界面设计及Python代码示
开发语言·python·图论
flashlight_hi2 小时前
LeetCode 分类刷题:2529. 正整数和负整数的最大计数
python·算法·leetcode
Ashlee_code2 小时前
香港券商櫃台系統跨境金融研究
java·python·科技·金融·架构·系统架构·区块链
Jia-Hui Su3 小时前
GDSFactory环境配置(PyCharm+Git+KLayout)
git·python·pycharm
陪我一起学编程3 小时前
创建Vue项目的不同方式及项目规范化配置
前端·javascript·vue.js·git·elementui·axios·企业规范