配置邮件发送
2025/5/19大约 4 分钟
配置邮件发送
redis的配置
- 在
pom.xml
配置redis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置yml
spring: data: redis: database: 5 host: localhost port: 6379
Spring Boot 框架会自动装配 RedisTemplate 对象,但是默认的key序列化器为
JdkSerializationRedisSerializer,导致我们存到Redis中后的数据和原始数据有差别,故设置为
StringRedisSerializer序列化器。
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
log.info("创建redis模板对象");
RedisTemplate redisTemplate =new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
mail组件的配置
- 在
pom.xml
文件下配置spring-boot-starter-mail
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
- 在
yml
配置:
spring:
mail:
username: [email protected]
password: JTun7K8rgXsXXXX
default-encoding: utf-8
host: smtp.163.com
消息队列的配置
在163邮箱获得16位的授权码:XXX
在
pom.xml
文件下配置spring-boot-starter-mail
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- 在
yml
配置:
spring:
rabbitmq:
username: admin
password: 123321
host: 192.168.154.128 #自己的虚拟机地址
virtual-host: /
邮件发送工具类的编写
写一个验证码的基础样式:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>验证码邮件</title> </head> <body style="font-family: Arial, sans-serif; background-color: #f5f5f5; padding: 20px;"> <div class="container" style="max-width: 600px; margin: auto; background-color: #ffffff; padding: 20px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1);"> <h1 style="color: #333333;">您的验证码</h1> <p style="color: #666666;">亲爱的用户,您正在尝试登录您的账户或执行某些操作。<br> 请使用以下验证码完成验证:</p> <div class="highlight" style="background-color: #ffdd9e; padding: 10px; border-radius: 4px; text-align: center;"> 123456 </div> <p style="color: #666666;">如果您没有请求此验证码,请忽略此邮件。</p> <p style="color: #666666;">此验证码将在5分钟后过期。</p> </div> </body> </html>
- 再在
utils
文件夹加入邮件工具类:
@Data @RequiredArgsConstructor @Slf4j @Component public class EmailUtils { private final JavaMailSender mailSender; private final RedisTemplate<String, String> redisTemplate; private final String subject = "山西大学算法队OnlineJudge验证码"; private final String VERIFICATION_CODE_PREFIX = "email:verification:"; private final int EXPIRATION_SECONDS = 300; // 5 minutes @Value("${spring.mail.username}") private String from; private String preEmail = "<!DOCTYPE html>\n" + "<html lang=\"zh-CN\">\n" + "<head>\n" + " <meta charset=\"UTF-8\">\n" + " <title>验证码邮件</title>\n" + "</head>\n" + "<body style=\"font-family: Arial, sans-serif;\n" + " background-color: #f5f5f5;\n" + " padding: 20px;\">\n" + "<div class=\"container\" style=\"max-width: 600px;\n" + " margin: auto;\n" + " background-color: #ffffff;\n" + " padding: 20px;\n" + " border-radius: 8px;\n" + " box-shadow: 0 4px 8px rgba(0,0,0,0.1);\">\n" + " <h1 style=\"color: #333333;\">您的验证码</h1>\n" + " <p style=\"color: #666666;\">亲爱的用户,您正在尝试登录您的账户或执行某些操作。<br>\n" + " 请使用以下验证码完成验证:</p>\n" + " <div class=\"highlight\" style=\"background-color: #ffdd9e;\n" + " padding: 10px;\n" + " border-radius: 4px;\n" + " text-align: center;\">"; private String afterEmail = "</div>\n" + " <p style=\"color: #666666;\">如果您没有请求此验证码,请忽略此邮件。</p>\n" + " <p style=\"color: #666666;\">此验证码将在5分钟后过期。</p>\n" + "</div>\n" + "</body>\n" + "</html>"; public String setCodeToHTML(String code) { return preEmail + code + afterEmail; } public Boolean sendHtmlMail(String to, String subject, String content) { //获取MimeMessage对象 MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper messageHelper; try { messageHelper = new MimeMessageHelper(message, true); //邮件发送人 messageHelper.setFrom(from); //邮件接收人,设置多个收件人地址 InternetAddress[] internetAddressTo = InternetAddress.parse(to); messageHelper.setTo(internetAddressTo); //messageHelper.setTo(to); //邮件主题 message.setSubject(subject); //邮件内容,html格式 messageHelper.setText(content, true); //发送 mailSender.send(message); //日志信息 log.info("邮件已经发送。"); return true; } catch (Exception e) { log.error("发送邮件时发生异常!", e); return false; } } public void storeVerificationCode(String email, String code) { String key = VERIFICATION_CODE_PREFIX + email + ":" + System.currentTimeMillis(); redisTemplate.opsForValue().set(key, code, EXPIRATION_SECONDS, TimeUnit.SECONDS); } public boolean checkCode(String email, String code) { // 获取该邮箱下的所有验证码键 for (String key : redisTemplate.keys(VERIFICATION_CODE_PREFIX + email + ":*")) { // 检查验证码是否匹配 if (code.equals(redisTemplate.opsForValue().get(key))) { return true; } } return false; } public void sendCode(String to) { Random random = new Random(); int code = random.nextInt(900000) + +100000; String codeToString = Integer.toString(code); Boolean isSend = sendHtmlMail(to, subject, setCodeToHTML(codeToString)); if (isSend) { storeVerificationCode(to, codeToString); } } }
这样发送邮件邮件发送时间太慢,需要有以下配置:
session.getProperties().setProperty("mail.smtp.localhost", "自定义"); System.getProperties().setProperty("mail.mime.address.usecanonicalhostname", "false");
这样就可以把发送邮件时间从40s减到0.6s了
- 再在
将邮件发送让消息队列监听
创建
EmailListener.java
文件,配置队列监听邮件发送请求@Component @RequiredArgsConstructor public class EmailListener { private final EmailUtils emailUtils; @RabbitListener(bindings = @QueueBinding( value = @Queue(name = "email.send.queue",durable = "true"), exchange = @Exchange(name = "email.direct"), key = "email.send" )) public void listenEmail(String email){ emailUtils.sendCode(email); } }
在
LoginController.java
发送消息@Operation(summary = "用户验证码发送") @PostMapping("/login/sendCode") public Result sendCode(@RequestBody EmailDTO email) { //emailUtils.sendCode(email.getEmail()); rabbitTemplate.convertAndSend("email.direct","email.send",email.getEmail()); return Result.success(); }
测试功能
Clip_2024-10-22_22-42-35
