google邮箱发送验证码

This commit is contained in:
cnc
2026-09-18 17:58:10 +08:00
parent e3b01e7b44
commit e4ef35c795
6 changed files with 289 additions and 1 deletions

View File

@@ -0,0 +1,64 @@
package org.dromara.web.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.RandomUtil;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.regex.RegexValidator;
import org.dromara.common.mail.core.GmailCodeService;
import org.dromara.common.redis.annotation.RateLimiter;
import org.dromara.common.redis.utils.RedisUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
/**
* Gmail 邮箱验证码接口。
*
* @author Qoder
*/
@SaIgnore
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
public class GmailCaptchaController {
private final GmailCodeService gmailCodeService;
/**
* 使用 Gmail 发送邮箱验证码。
*
* @param email 收件邮箱
* @return 操作结果
*/
@GetMapping("/resource/gmail/code")
public R<Void> gmailCode(@NotBlank(message = "{user.email.not.blank}") String email) {
if (!RegexValidator.isEmail(email)) {
return R.fail("请输入正确的邮箱地址!");
}
SpringUtils.getAopProxy(this).gmailCodeImpl(email);
return R.ok();
}
/**
* 发送邮箱验证码的实际执行方法,拆分出来以便限流注解生效。
*
* @param email 收件邮箱
*/
@RateLimiter(key = "#email", time = 60, count = 1)
public void gmailCodeImpl(String email) {
String key = GlobalConstants.CAPTCHA_CODE_KEY + email;
String code = RandomUtil.randomNumbers(4);
// 先落缓存再发信:即使发信异常,验证码也不会丢失;发信失败会抛 ServiceException 由全局异常处理
gmailCodeService.sendVerifyCode(email, code, Constants.CAPTCHA_EXPIRATION);
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
}
}

View File

@@ -206,6 +206,30 @@ mail:
# Socket连接超时值,单位毫秒,缺省值不超时
connectionTimeout: 0
--- # gmail 邮件发送(Gmail SMTP,用于邮箱验证码)
gmail:
# 是否启用;未启用时接口返回「未开启 Gmail 邮件功能」
enabled: true
host: smtp.gmail.com
# 465 走 SSL;若改用 587,请同时设 sslEnable=false 且 starttlsEnable=true
port: 465
auth: true
# 发信账号(Gmail 地址),由环境变量注入
user: ${GMAIL_USER:huzuming2@gmail.com}
# user: ${GMAIL_USER:}
# user: "chinarzcui@gmail.com"
# 发信凭据:Gmail 16 位「应用专用密码」(非登录密码),由环境变量注入
pass: ${GMAIL_PASS:lajl mccm ycqi uekj}
# pass: ${GMAIL_PASS:}
# 发件人,留空回落到 user;Gmail 要求发件人与认证账号一致
from: ${GMAIL_FROM:huzuming2@gmail.com}
# from: ${GMAIL_FROM:}
sslEnable: true
starttlsEnable: false
# smtp.gmail.com 在国内机房通常不可达,快速失败避免挂死请求线程
connectionTimeout: 5000
timeout: 10000
--- # 设备域 · APP 端配置(前缀 device.app,对应 org.dromara.device.config.AppProperties)
# 所有项在代码中均有默认值,此处显式列出仅为便于运维调参;整段删除不影响启动。
device:

View File

@@ -209,6 +209,27 @@ mail:
# Socket连接超时值,单位毫秒,缺省值不超时
connectionTimeout: 0
--- # gmail 邮件发送(Gmail SMTP,用于邮箱验证码)
gmail:
# 是否启用;未启用时接口返回「未开启 Gmail 邮件功能」
enabled: true
host: smtp.gmail.com
# 465 走 SSL;若改用 587,请同时设 sslEnable=false 且 starttlsEnable=true
port: 465
auth: true
# 发信账号(Gmail 地址),由环境变量注入
user: ${GMAIL_USER:huzuming2@gmail.com}
# user: "chinarzcui@gmail.com"
# 发信凭据:Gmail 16 位「应用专用密码」(非登录密码),由环境变量注入
pass: ${GMAIL_PASS:qbjo lajl mccm ycqi uekj}
# 发件人,留空回落到 user;Gmail 要求发件人与认证账号一致
from: ${GMAIL_FROM:huzuming2@gmail.com}
sslEnable: true
starttlsEnable: false
# smtp.gmail.com 在国内机房通常不可达,快速失败避免挂死请求线程
connectionTimeout: 5000
timeout: 10000
--- # 设备域 · APP 端配置(前缀 device.app,对应 org.dromara.device.config.AppProperties)
# 所有项在代码中均有默认值,此处显式列出仅为便于运维调参;整段删除不影响启动。
device: