Java实现邮箱验证案例

wen java案例 1

本文目录导读:

Java实现邮箱验证案例

  1. 项目结构
  2. Maven依赖(pom.xml)
  3. 邮箱服务类(EmailService.java)
  4. 验证码服务类(EmailVerificationService.java)
  5. 配置文件(application.properties)
  6. 测试类(Main.java)
  7. 配置说明
  8. 安全性增强建议
  9. 使用Spring Boot后的接口版本
  10. 使用建议

我来为你提供一个完整的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邮箱配置

  1. 登录QQ邮箱设置
  2. 开启SMTP服务
  3. 获取授权码(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("验证失败");
    }
}

使用建议

  1. 验证码有效期:建议5-10分钟
  2. 发送频率限制:避免频繁发送
  3. 验证码长度:6位数字较为合适
  4. 使用HTTPS:传输安全
  5. 日志记录:记录发送和验证的日志
  6. 异常处理:做好各种异常情况的处理

这个案例提供了完整的邮箱验证功能,你可以根据实际需求调整配置和使用方式。

抱歉,评论功能暂时关闭!