This commit is contained in:
wangli 2026-01-22 00:18:29 +08:00
parent bd1d81c0a5
commit f27bd6055d
2 changed files with 96 additions and 45 deletions

View File

@ -2,15 +2,22 @@ package top.biwin.xinayu.server.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import top.biwin.xianyu.core.entity.SystemSetting;
import top.biwin.xianyu.core.repository.SystemSettingRepository;
import java.util.Properties;
/**
* 邮件发送服务
* 负责发送各类邮件验证码通知等
* <p>
* 邮件配置从 system_settings 表动态读取支持运行时更新配置
*
* @author wangli
* @since 2026-01-21
@ -20,10 +27,71 @@ import org.springframework.stereotype.Service;
public class EmailService {
@Autowired
private JavaMailSender mailSender;
private SystemSettingRepository systemSettingRepository;
@Value("${spring.mail.username:noreply@xianyu-freedom.com}")
private String fromEmail;
/**
* 从数据库读取邮件配置并创建 JavaMailSender
*
* @return JavaMailSender 实例
* @throws RuntimeException 如果邮件配置不完整
*/
private JavaMailSender createMailSender() {
// 从数据库读取配置
String smtpServer = getSettingValue("smtp_server");
String smtpPort = getSettingValue("smtp_port");
String smtpUser = getSettingValue("smtp_user");
String smtpPassword = getSettingValue("smtp_password");
String smtpUseTls = getSettingValue("smtp_use_tls");
String smtpUseSsl = getSettingValue("smtp_use_ssl");
// 验证必要的配置
if (!StringUtils.hasText(smtpServer) || !StringUtils.hasText(smtpUser) || !StringUtils.hasText(smtpPassword)) {
throw new RuntimeException("邮件服务配置不完整,请在系统设置中配置 SMTP 服务器信息");
}
// 创建 JavaMailSender
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(smtpServer);
mailSender.setPort(Integer.parseInt(smtpPort));
mailSender.setUsername(smtpUser);
mailSender.setPassword(smtpPassword);
// 配置 SMTP 属性
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
// TLS/SSL 配置
if ("true".equalsIgnoreCase(smtpUseTls)) {
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.starttls.required", "true");
}
if ("true".equalsIgnoreCase(smtpUseSsl)) {
props.put("mail.smtp.ssl.enable", "true");
}
props.put("mail.smtp.connectiontimeout", "5000");
props.put("mail.smtp.timeout", "5000");
props.put("mail.smtp.writetimeout", "5000");
log.debug("📧 邮件服务配置SMTP={}:{}, 用户={}, TLS={}, SSL={}",
smtpServer, smtpPort, smtpUser, smtpUseTls, smtpUseSsl);
return mailSender;
}
/**
* 从数据库读取配置项
*
* @param key 配置键
* @return 配置值如果不存在则返回空字符串
*/
private String getSettingValue(String key) {
return systemSettingRepository.findByKey(key)
.map(SystemSetting::getValue)
.orElse("");
}
/**
* 异步发送验证码邮件
@ -33,20 +101,18 @@ public class EmailService {
*/
@Async
public void sendVerificationCode(String toEmail, String code) {
// TODO: 主人这里需要配置邮件发送逻辑
// 步骤
// 1. 创建 SimpleMailMessage 对象
// 2. 设置发件人message.setFrom(fromEmail)
// 3. 设置收件人message.setTo(toEmail)
// 4. 设置主题message.setSubject("【闲鱼自由】邮箱验证码")
// 5. 设置邮件内容message.setText("您的验证码是:" + code + "有效期5分钟。")
// 6. 调用 mailSender.send(message) 发送邮件
// 7. 记录日志log.info("验证码邮件已发送到: {}", toEmail)
// 8. 异常处理catch (Exception e) { log.error("邮件发送失败", e); }
try {
// 动态创建 MailSender
JavaMailSender mailSender = createMailSender();
// 获取发件人显示名如果配置了
String smtpFrom = getSettingValue("smtp_from");
String smtpUser = getSettingValue("smtp_user");
String fromAddress = StringUtils.hasText(smtpFrom) ? smtpFrom : smtpUser;
// 创建邮件消息
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(fromEmail);
message.setFrom(fromAddress);
message.setTo(toEmail);
message.setSubject("【闲鱼自由】邮箱验证码");
message.setText(
@ -57,12 +123,13 @@ public class EmailService {
"——闲鱼自由团队"
);
// 发送邮件
mailSender.send(message);
log.info("✅ 验证码邮件已成功发送到: {}", toEmail);
} catch (Exception e) {
log.error("❌ 邮件发送失败,收件人: {}, 错误信息: {}", toEmail, e.getMessage(), e);
throw new RuntimeException("邮件发送失败,请稍后重试", e);
throw new RuntimeException("邮件发送失败" + e.getMessage(), e);
}
}
@ -75,20 +142,29 @@ public class EmailService {
*/
@Async
public void sendEmail(String toEmail, String subject, String content) {
// TODO: 主人可以在这里实现通用邮件发送逻辑哦
// 参考上面的 sendVerificationCode 方法实现即可
try {
// 动态创建 MailSender
JavaMailSender mailSender = createMailSender();
// 获取发件人显示名
String smtpFrom = getSettingValue("smtp_from");
String smtpUser = getSettingValue("smtp_user");
String fromAddress = StringUtils.hasText(smtpFrom) ? smtpFrom : smtpUser;
// 创建邮件消息
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(fromEmail);
message.setFrom(fromAddress);
message.setTo(toEmail);
message.setSubject(subject);
message.setText(content);
// 发送邮件
mailSender.send(message);
log.info("✅ 邮件已发送到: {}, 主题: {}", toEmail, subject);
} catch (Exception e) {
log.error("❌ 邮件发送失败: {}", e.getMessage(), e);
throw new RuntimeException("邮件发送失败:" + e.getMessage(), e);
}
}
}

View File

@ -37,31 +37,6 @@ spring:
max-file-size: 10MB
max-request-size: 10MB
# 邮件服务配置
mail:
# TODO: 主人需要配置邮件服务器信息!
# 示例Gmail SMTP 配置
# 1. host: smtp.gmail.com
# 2. port: 587
# 3. username: 你的Gmail邮箱
# 4. password: Gmail应用专用密码不是登录密码
# 5. 需要在 Gmail 账户设置中开启"两步验证"并生成"应用专用密码"
host: ${MAIL_HOST:smtp.gmail.com} # 邮件服务器地址
port: ${MAIL_PORT:587} # SMTP 端口
username: ${MAIL_USERNAME:} # 发件人邮箱(请在环境变量中配置)
password: ${MAIL_PASSWORD:} # 邮箱密码或应用专用密码(请在环境变量中配置)
properties:
mail:
smtp:
auth: true # 启用 SMTP 认证
starttls:
enable: true # 启用 TLS 加密
required: true # 强制使用 TLS
connectiontimeout: 5000 # 连接超时(毫秒)
timeout: 5000 # 读取超时(毫秒)
writetimeout: 5000 # 写入超时(毫秒)
logging:
level:
root: INFO