在用户注册场景中,邮件验证是保证用户身份真实性的常用手段,Java可以通过SMTP协议对接邮件服务器实现验证邮件的发送。整个流程包含依赖引入、邮件服务器配置、验证码生成、邮件内容组装、发送逻辑实现以及验证校验几个核心环节。

环境准备与依赖引入
Java发送邮件通常使用JavaMail API,如果是Maven项目,需要在pom.xml中添加以下依赖:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
SMTP邮件服务器配置
首先需要准备邮件服务器的相关参数,以QQ邮箱为例,需要开启SMTP服务并获取授权码,配置参数如下:
| 参数名 | 参数值 | 说明 |
|---|---|---|
| mail.smtp.host | smtp.qq.com | QQ邮箱SMTP服务器地址 |
| mail.smtp.port | 465 | SSL加密端口 |
| mail.smtp.auth | true | 开启身份验证 |
| mail.smtp.ssl.enable | true | 开启SSL加密 |
邮件发送工具类实现
封装一个邮件发送的工具类,包含配置初始化和邮件发送方法:
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class MailUtil {
// 发件人邮箱
private static final String SENDER_EMAIL = "xxx@qq.com";
// 发件人邮箱授权码,替换为自己的授权码
private static final String AUTH_CODE = "xxxxxx";
// SMTP服务器地址
private static final String SMTP_HOST = "smtp.qq.com";
// SMTP端口
private static final String SMTP_PORT = "465";
/**
* 发送验证邮件
* @param receiverEmail 收件人邮箱
* @param code 验证码
* @throws MessagingException 邮件发送异常
*/
public static void sendVerifyMail(String receiverEmail, String code) throws MessagingException {
// 配置邮件服务器属性
Properties props = new Properties();
props.put("mail.smtp.host", SMTP_HOST);
props.put("mail.smtp.port", SMTP_PORT);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.ssl.enable", "true");
// 创建会话,传入身份验证器
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(SENDER_EMAIL, AUTH_CODE);
}
});
// 创建邮件对象
Message message = new MimeMessage(session);
// 设置发件人
message.setFrom(new InternetAddress(SENDER_EMAIL));
// 设置收件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress(receiverEmail));
// 设置邮件主题
message.setSubject("用户注册验证码");
// 设置邮件正文
String content = "您好,您的注册验证码为:" + code + ",有效期为5分钟,请勿泄露给他人。";
message.setText(content);
// 发送邮件
Transport.send(message);
}
}
注册验证码生成与发送逻辑
在用户注册的接口中,生成随机验证码,调用邮件发送工具类发送邮件,同时将验证码和过期时间存入缓存(如Redis):
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
public class RegisterService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String CODE_PREFIX = "register:code:";
// 验证码有效期5分钟
private static final long CODE_EXPIRE = 5;
/**
* 处理用户注册请求,发送验证邮件
* @param email 用户注册邮箱
*/
public void handleRegister(String email) {
// 生成6位随机验证码
String code = generateVerifyCode(6);
try {
// 发送验证邮件
MailUtil.sendVerifyMail(email, code);
// 将验证码存入Redis,设置过期时间
redisTemplate.opsForValue().set(CODE_PREFIX + email, code, CODE_EXPIRE, TimeUnit.MINUTES);
} catch (Exception e) {
throw new RuntimeException("发送验证邮件失败", e);
}
}
/**
* 生成指定长度的随机数字验证码
* @param length 验证码长度
* @return 验证码字符串
*/
private String generateVerifyCode(int length) {
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append(random.nextInt(10));
}
return sb.toString();
}
}
验证码校验逻辑
用户收到邮件后输入验证码,后端需要从缓存中取出对应邮箱的验证码进行比对:
public class RegisterService {
// 省略其他代码
/**
* 校验注册验证码
* @param email 用户邮箱
* @param inputCode 用户输入的验证码
* @return 校验是否通过
*/
public boolean verifyCode(String email, String inputCode) {
String cacheKey = CODE_PREFIX + email;
String cacheCode = redisTemplate.opsForValue().get(cacheKey);
if (cacheCode == null) {
throw new RuntimeException("验证码已过期,请重新获取");
}
if (cacheCode.equals(inputCode)) {
// 校验通过后删除缓存中的验证码
redisTemplate.delete(cacheKey);
return true;
}
return false;
}
}
注意事项
- 不同邮箱服务商的SMTP服务器地址和端口不同,需要根据实际使用的邮箱调整配置
- 邮箱授权码不是登录密码,需要在邮箱设置中单独开启SMTP服务获取
- 验证码需要设置合理的过期时间,避免长期有效带来安全风险
- 生产环境中建议对邮件发送逻辑做异常重试和日志记录,提高稳定性