From 2c8b0a7b2b6bd63b965231b8e338d543fb4b0e64 Mon Sep 17 00:00:00 2001 From: zhoujinhua Date: Mon, 20 Oct 2025 16:42:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=82=AE=E4=BB=B6=E5=8F=91?= =?UTF-8?q?=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.properties | 16 +- .../corewing/app/util/SmtpConnectionTest.java | 224 ++++++++++++++++++ 2 files changed, 234 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/corewing/app/util/SmtpConnectionTest.java diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 842c78d..a9a7896 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -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 diff --git a/src/test/java/com/corewing/app/util/SmtpConnectionTest.java b/src/test/java/com/corewing/app/util/SmtpConnectionTest.java new file mode 100644 index 0000000..e9fc33c --- /dev/null +++ b/src/test/java/com/corewing/app/util/SmtpConnectionTest.java @@ -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; + } +}