本文目录导读:

- 项目结构
- Maven依赖(pom.xml)
- 邮箱服务类(EmailService.java)
- 验证码服务类(EmailVerificationService.java)
- 配置文件(application.properties)
- 测试类(Main.java)
- 配置说明
- 安全性增强建议
- 使用Spring Boot后的接口版本
- 使用建议
我来为你提供一个完整的Java邮箱验证案例,包含发送验证码和验证功能。
项目结构
email-verification/
├── pom.xml
├── src/main/java/com/example/email/
│ ├── EmailService.java
│ ├── EmailVerificationService.java
│ └── Main.java
└── src/main/resources/
└── application.properties
Maven依赖(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>email-verification</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- JavaMail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<!-- Spring Boot Mail Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.7.0</version>
</dependency>
<!-- Redis (可选,用于存储验证码) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.7.0</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<!-- JSON处理 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
</dependencies>
</project>
邮箱服务类(EmailService.java)
package com.example.email;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.mail.internet.MimeMessage;
@Service
public class EmailService {
private final JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String fromEmail;
public EmailService(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
/**
* 发送普通文本邮件
*/
public void sendSimpleEmail(String to, String subject, String content) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(fromEmail);
message.setTo(to);
message.setSubject(subject);
message.setText(content);
mailSender.send(message);
}
/**
* 发送HTML邮件
*/
public void sendHtmlEmail(String to, String subject, String htmlContent) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setFrom(fromEmail);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(htmlContent, true); // true表示HTML格式
mailSender.send(message);
} catch (Exception e) {
throw new RuntimeException("发送HTML邮件失败", e);
}
}
}
验证码服务类(EmailVerificationService.java)
package com.example.email;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.security.SecureRandom;
import java.util.concurrent.TimeUnit;
@Service
public class EmailVerificationService {
private static final String VERIFICATION_CODE_PREFIX = "email:verification:";
private static final String LOCK_PREFIX = "email:lock:";
private static final long CODE_EXPIRE_MINUTES = 5; // 验证码有效期
private static final long LOCK_EXPIRE_MINUTES = 10; // 发送锁定时间
private static final int MAX_SEND_COUNT = 3; // 最大发送次数
@Autowired
private EmailService emailService;
@Autowired(required = false)
private StringRedisTemplate redisTemplate;
// 简单的内存缓存(不使用Redis时)
private Map<String, VerificationInfo> verificationCache = new ConcurrentHashMap<>();
/**
* 发送验证码
* @param email 邮箱地址
* @return 成功返回true,失败返回false
*/
public boolean sendVerificationCode(String email) {
// 1. 检查发送频率
if (isTooFrequent(email)) {
throw new RuntimeException("发送太频繁,请稍后再试");
}
// 2. 生成6位数字验证码
String code = generateCode();
// 3. 存储验证码
saveVerificationCode(email, code);
// 4. 发送邮件
try {
String content = buildEmailContent(code);
emailService.sendHtmlEmail(email, "邮箱验证码", content);
// 5. 更新发送记录
incrementSendCount(email);
return true;
} catch (Exception e) {
// 发送失败,清除验证码
deleteVerificationCode(email);
throw new RuntimeException("验证码发送失败", e);
}
}
/**
* 验证邮箱验证码
* @param email 邮箱地址
* @param code 验证码
* @return 是否验证成功
*/
public boolean verifyCode(String email, String code) {
if (email == null || code == null) {
return false;
}
// 获取存储的验证码
String storedCode = getVerificationCode(email);
// 验证码不存在或已过期
if (storedCode == null) {
return false;
}
// 验证码匹配
if (storedCode.equals(code)) {
// 验证成功后删除验证码
deleteVerificationCode(email);
return true;
}
return false;
}
/**
* 生成6位数字验证码
*/
private String generateCode() {
SecureRandom random = new SecureRandom();
int code = 100000 + random.nextInt(900000);
return String.valueOf(code);
}
/**
* 保存验证码
*/
private void saveVerificationCode(String email, String code) {
String key = VERIFICATION_CODE_PREFIX + email;
if (redisTemplate != null) {
redisTemplate.opsForValue().set(key, code, CODE_EXPIRE_MINUTES, TimeUnit.MINUTES);
} else {
VerificationInfo info = new VerificationInfo(code,
System.currentTimeMillis() + CODE_EXPIRE_MINUTES * 60 * 1000);
verificationCache.put(email, info);
}
}
/**
* 获取验证码
*/
private String getVerificationCode(String email) {
String key = VERIFICATION_CODE_PREFIX + email;
if (redisTemplate != null) {
return redisTemplate.opsForValue().get(key);
} else {
VerificationInfo info = verificationCache.get(email);
if (info != null) {
if (System.currentTimeMillis() > info.expireTime) {
verificationCache.remove(email);
return null;
}
return info.code;
}
return null;
}
}
/**
* 删除验证码
*/
private void deleteVerificationCode(String email) {
String key = VERIFICATION_CODE_PREFIX + email;
if (redisTemplate != null) {
redisTemplate.delete(key);
} else {
verificationCache.remove(email);
}
}
/**
* 检查发送是否过于频繁
*/
private boolean isTooFrequent(String email) {
String key = LOCK_PREFIX + email;
if (redisTemplate != null) {
Boolean locked = redisTemplate.hasKey(key);
return Boolean.TRUE.equals(locked);
} else {
// 简单的内存检查
return false;
}
}
/**
* 增加发送计数
*/
private void incrementSendCount(String email) {
String key = LOCK_PREFIX + email;
if (redisTemplate != null) {
// 设置锁定时间,防止重复发送
redisTemplate.opsForValue().set(key, "1", LOCK_EXPIRE_MINUTES, TimeUnit.MINUTES);
}
}
/**
* 构建邮件HTML内容
*/
private String buildEmailContent(String code) {
return String.format("""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
.header {
background-color: #4CAF50;
color: white;
padding: 20px;
text-align: center;
border-radius: 5px 5px 0 0;
}
.content {
padding: 20px;
background-color: #f9f9f9;
border: 1px solid #ddd;
}
.code {
font-size: 36px;
font-weight: bold;
color: #4CAF50;
text-align: center;
letter-spacing: 10px;
margin: 20px 0;
}
.warning {
color: #999;
font-size: 12px;
margin-top: 20px;
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h2>邮箱验证</h2>
</div>
<div class="content">
<p>亲爱的用户:</p>
<p>您正在请求操作验证,您的验证码为:</p>
<div class="code">%s</div>
<p><b>验证码有效期:</b>5分钟</p>
<p><b>请勿泄露给他人!</b></p>
<div class="warning">
如果您没有请求此操作,请忽略此邮件。
</div>
</div>
</div>
</body>
</html>
""", code);
}
/**
* 验证码信息类(内存缓存使用)
*/
private static class VerificationInfo {
String code;
long expireTime;
VerificationInfo(String code, long expireTime) {
this.code = code;
this.expireTime = expireTime;
}
}
}
配置文件(application.properties)
# 邮件配置 spring.mail.host=smtp.qq.com spring.mail.port=587 spring.mail.username=your-email@qq.com # 授权码(不是邮箱密码) spring.mail.password=your-authorization-code spring.mail.protocol=smtp spring.mail.default-encoding=UTF-8 # SSL/TLS配置 spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.connectiontimeout=10000 spring.mail.properties.mail.smtp.timeout=10000 spring.mail.properties.mail.smtp.writetimeout=10000 # Redis配置(可选) spring.redis.host=localhost spring.redis.port=6379 spring.redis.database=0
测试类(Main.java)
package com.example.email;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import java.util.Scanner;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
@Bean
public CommandLineRunner demo(EmailVerificationService verificationService) {
return args -> {
Scanner scanner = new Scanner(System.in);
System.out.println("=== 邮箱验证码演示程序 ===");
System.out.println("请输入要验证的邮箱地址:");
String email = scanner.nextLine();
// 发送验证码
try {
verificationService.sendVerificationCode(email);
System.out.println("验证码已发送到 " + email);
System.out.println("请查看邮箱获取验证码");
// 输入验证
System.out.println("请输入验证码:");
String code = scanner.nextLine();
// 验证码验证
boolean result = verificationService.verifyCode(email, code);
if (result) {
System.out.println("✅ 验证码正确,邮箱验证成功!");
} else {
System.out.println("❌ 验证码错误或已过期,验证失败!");
}
} catch (Exception e) {
System.out.println("发送验证码失败:" + e.getMessage());
}
scanner.close();
};
}
}
配置说明
QQ邮箱配置
- 登录QQ邮箱设置
- 开启SMTP服务
- 获取授权码(16位)
163邮箱配置
spring.mail.host=smtp.163.com spring.mail.port=465 spring.mail.username=your-email@163.com spring.mail.password=your-authorization-code
Gmail配置
spring.mail.host=smtp.gmail.com spring.mail.port=587 spring.mail.username=your-email@gmail.com spring.mail.password=your-app-password
安全性增强建议
// 添加验证码防暴力破解
@Service
public class SecureVerificationService {
private static final int MAX_ATTEMPTS = 5;
/**
* 带尝试次数限制的验证
*/
public boolean verifyWithAttemptLimit(String email, String code) {
String attemptsKey = "email:attempts:" + email;
// 检查尝试次数
int attempts = getAttempts(attemptsKey);
if (attempts >= MAX_ATTEMPTS) {
throw new RuntimeException("验证次数过多,请重新获取验证码");
}
// 验证逻辑
boolean success = verifyCode(email, code);
if (!success) {
incrementAttempts(attemptsKey);
} else {
clearAttempts(attemptsKey);
}
return success;
}
}
使用Spring Boot后的接口版本
package com.example.email.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/email")
public class EmailVerificationController {
@Autowired
private EmailVerificationService verificationService;
@PostMapping("/send-code")
public ApiResult sendCode(@RequestParam String email) {
try {
verificationService.sendVerificationCode(email);
return ApiResult.success("验证码已发送");
} catch (Exception e) {
return ApiResult.error(e.getMessage());
}
}
@PostMapping("/verify")
public ApiResult verify(@RequestParam String email,
@RequestParam String code) {
boolean success = verificationService.verifyCode(email, code);
if (success) {
return ApiResult.success("验证成功");
}
return ApiResult.error("验证失败");
}
}
使用建议
- 验证码有效期:建议5-10分钟
- 发送频率限制:避免频繁发送
- 验证码长度:6位数字较为合适
- 使用HTTPS:传输安全
- 日志记录:记录发送和验证的日志
- 异常处理:做好各种异常情况的处理
这个案例提供了完整的邮箱验证功能,你可以根据实际需求调整配置和使用方式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播