修复邮件发送
Some checks failed
CI Build and Test / build (push) Has been cancelled
Deploy to Server / build-and-deploy (push) Has been cancelled

This commit is contained in:
2025-10-20 16:42:32 +08:00
parent a7b3a4f293
commit 2c8b0a7b2b
2 changed files with 234 additions and 6 deletions

View File

@@ -61,17 +61,21 @@ smsbao.password=your_password
# 邮件配置
# SMTP 服务器地址
spring.mail.host=smtp.chengmail.cn
# SMTP 服务器端口
spring.mail.host=smtp.em.dingtalk.com
# SMTP 服务器端口465 为 SSL 加密端口)
spring.mail.port=465
# 发件人邮箱
spring.mail.username=dev@corewing.com
# 邮箱授权码(不是邮箱密码!需要在邮箱设置中开启 SMTP 服务并获取授权码)
spring.mail.password=HRTmmNrBRjSxfwAk
spring.mail.password=t035gngwYl0xgvZF
# 编码格式
spring.mail.default-encoding=UTF-8
# 其他配置
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.ssl.enable=false
# 465 端口使用 SSL 加密,需要启用 SSL
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.smtp.ssl.required=true
# SSL Socket Factory 配置
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
spring.mail.properties.mail.smtp.socketFactory.port=465
spring.mail.properties.mail.smtp.socketFactory.fallback=false

View File

@@ -0,0 +1,224 @@
package com.corewing.app.util;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import javax.mail.*;
import java.util.Properties;
/**
* SMTP 连接诊断测试
* 用于排查邮件发送问题
*/
@SpringBootTest
public class SmtpConnectionTest {
@Value("${spring.mail.host}")
private String host;
@Value("${spring.mail.port}")
private int port;
@Value("${spring.mail.username}")
private String username;
@Value("${spring.mail.password}")
private String password;
/**
* 测试 SMTP 服务器连接和认证
*/
@Test
public void testSmtpConnection() {
System.out.println("========== SMTP 连接诊断 ==========");
System.out.println("📧 邮件服务器配置信息:");
System.out.println(" SMTP 服务器: " + host);
System.out.println(" SMTP 端口: " + port);
System.out.println(" 发件人邮箱: " + username);
System.out.println(" 授权码长度: " + (password != null ? password.length() : 0) + "");
System.out.println(" 授权码(隐藏中间部分): " + maskPassword(password));
System.out.println();
// 测试 465 端口SSL
if (port == 465) {
testSslConnection();
}
// 测试 587 端口STARTTLS
else if (port == 587) {
testStartTlsConnection();
}
// 测试 25 端口(无加密或 STARTTLS
else if (port == 25) {
testPort25Connection();
} else {
System.out.println("❓ 未知的端口: " + port);
}
}
/**
* 测试 SSL 连接465 端口)
*/
private void testSslConnection() {
System.out.println("🔐 正在测试 SSL 连接(端口 465...");
System.out.println();
Properties props = new Properties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", port);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.ssl.required", "true");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.port", port);
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.timeout", "10000");
props.put("mail.smtp.connectiontimeout", "10000");
testConnection(props);
}
/**
* 测试 STARTTLS 连接587 端口)
*/
private void testStartTlsConnection() {
System.out.println("🔐 正在测试 STARTTLS 连接(端口 587...");
System.out.println();
Properties props = new Properties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", port);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.starttls.required", "true");
props.put("mail.smtp.ssl.enable", "false");
props.put("mail.smtp.timeout", "10000");
props.put("mail.smtp.connectiontimeout", "10000");
testConnection(props);
}
/**
* 测试端口 25 连接
*/
private void testPort25Connection() {
System.out.println("🔓 正在测试端口 25 连接...");
System.out.println();
Properties props = new Properties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", port);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.timeout", "10000");
props.put("mail.smtp.connectiontimeout", "10000");
testConnection(props);
}
/**
* 执行连接测试
*/
private void testConnection(Properties props) {
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
// 开启调试模式
session.setDebug(true);
Transport transport = null;
try {
System.out.println("⏳ 正在连接到 SMTP 服务器...");
transport = session.getTransport("smtp");
transport.connect(host, username, password);
System.out.println();
System.out.println("========================================");
System.out.println("✅ SMTP 连接成功!");
System.out.println("========================================");
System.out.println("📝 诊断结果:");
System.out.println(" ✓ 服务器地址正确");
System.out.println(" ✓ 端口配置正确");
System.out.println(" ✓ 用户名正确");
System.out.println(" ✓ 授权码正确");
System.out.println();
System.out.println("💡 邮件配置没有问题,可以正常发送邮件了!");
} catch (AuthenticationFailedException e) {
System.out.println();
System.out.println("========================================");
System.out.println("❌ 认证失败!");
System.out.println("========================================");
System.out.println("📝 错误原因:用户名或密码(授权码)错误");
System.out.println();
System.out.println("💡 解决方案:");
System.out.println(" 1. 检查邮箱地址是否正确: " + username);
System.out.println(" 2. 确认是否使用授权码而非登录密码");
System.out.println(" 3. 登录邮箱管理后台查找「SMTP设置」或「客户端授权密码」");
System.out.println(" 4. 确认是否需要先开启 SMTP 服务");
System.out.println(" 5. 重新生成授权码并更新到 application.properties");
System.out.println();
System.out.println("🔗 常见企业邮箱 SMTP 设置:");
System.out.println(" • 腾讯企业邮箱: smtp.exmail.qq.com:465 (SSL)");
System.out.println(" • 阿里企业邮箱: smtp.qiye.aliyun.com:465 (SSL)");
System.out.println(" • 网易企业邮箱: smtp.qiye.163.com:465 (SSL)");
System.out.println();
System.out.println("⚠️ 详细错误信息: " + e.getMessage());
} catch (MessagingException e) {
System.out.println();
System.out.println("========================================");
System.out.println("❌ 连接失败!");
System.out.println("========================================");
System.out.println("📝 错误类型:" + e.getClass().getSimpleName());
System.out.println();
System.out.println("💡 可能的原因:");
System.out.println(" 1. SMTP 服务器地址错误: " + host);
System.out.println(" 2. 端口号错误或被防火墙封禁: " + port);
System.out.println(" 3. 网络连接问题");
System.out.println(" 4. SSL/TLS 配置不匹配");
System.out.println();
System.out.println("🔧 建议尝试:");
System.out.println(" • 如果当前是 465 端口,尝试改为 587 + STARTTLS");
System.out.println(" • 检查防火墙是否封禁了邮件端口");
System.out.println(" • 联系邮箱服务商确认正确的 SMTP 配置");
System.out.println();
System.out.println("⚠️ 详细错误信息: " + e.getMessage());
} catch (Exception e) {
System.out.println();
System.out.println("========================================");
System.out.println("❌ 未知错误!");
System.out.println("========================================");
System.out.println("⚠️ 错误信息: " + e.getMessage());
e.printStackTrace();
} finally {
if (transport != null && transport.isConnected()) {
try {
transport.close();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
}
/**
* 隐藏密码中间部分
*/
private String maskPassword(String password) {
if (password == null || password.length() <= 4) {
return "****";
}
int showChars = Math.min(2, password.length() / 4);
String start = password.substring(0, showChars);
String end = password.substring(password.length() - showChars);
int maskLength = password.length() - (showChars * 2);
String mask = "*".repeat(maskLength);
return start + mask + end;
}
}