package com.xuqm.tenant.service; import com.xuqm.common.exception.BusinessException; import com.xuqm.tenant.entity.EmailVerificationEntity; import com.xuqm.tenant.repository.EmailVerificationRepository; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.security.SecureRandom; import java.time.LocalDateTime; import java.util.UUID; @Service public class EmailService { private final JavaMailSender mailSender; private final EmailVerificationRepository verificationRepository; @Value("${spring.mail.username}") private String fromAddress; @Value("${email-verify.expire-seconds:600}") private int expireSeconds; private static final SecureRandom random = new SecureRandom(); public EmailService(JavaMailSender mailSender, EmailVerificationRepository verificationRepository) { this.mailSender = mailSender; this.verificationRepository = verificationRepository; } @Transactional public void sendVerificationCode(String email, String purpose) { String code = String.format("%06d", random.nextInt(1_000_000)); EmailVerificationEntity entity = new EmailVerificationEntity(); entity.setId(UUID.randomUUID().toString()); entity.setEmail(email); entity.setCode(code); entity.setPurpose(purpose); entity.setUsed(false); entity.setCreatedAt(LocalDateTime.now()); entity.setExpiresAt(LocalDateTime.now().plusSeconds(expireSeconds)); SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(fromAddress); message.setTo(email); message.setSubject("XuqmGroup - 邮箱验证码"); message.setText(String.format("您的验证码是:%s,%d分钟内有效。", code, expireSeconds / 60)); verificationRepository.save(entity); mailSender.send(message); } public void verify(String email, String code, String purpose) { EmailVerificationEntity entity = verificationRepository .findTopByEmailAndPurposeAndUsedFalseOrderByCreatedAtDesc(email, purpose) .orElseThrow(() -> new BusinessException("验证码无效")); if (entity.getExpiresAt().isBefore(LocalDateTime.now())) { throw new BusinessException("验证码已过期"); } if (!entity.getCode().equals(code)) { throw new BusinessException("验证码错误"); } entity.setUsed(true); verificationRepository.save(entity); } }