Domino Java Agent连接TLS1.2要求的SMTP服务器握手失败问题排查
问题场景与排查需求
我们的业务需要通过Domino Java Agent(使用mailapi-1.6.2.jar)直接向仅支持TLS1.2的远程SMTP服务器发送邮件,不同业务逻辑使用不同用户名密码认证,远程服务器已禁用TLS1.0和TLS1.1。
报错信息
javax.mail.MessagingException: Can't send command to SMTP host; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol, may be no appropriate cipher suite specified or protocols are deactivated
已通过WireShark确认连接尝试使用TLS1.2,推测问题出在Domino使用的密码套件与远程服务器不匹配,但无法验证缺失或尝试使用的套件。
已做的配置与尝试
Domino 9 服务器配置
- 密码套件:
- RC4 encryption with 128-bit key and MD5 MAC
- RC4 encryption with 128-bit key and SHA-1 MAC
- Triple DES encryption with 168-bit key and SHA-1 MAC
- DES encryption with 56-bit key and SHA-1 MAC
- RC4 encryption with 40-bit key and MD5 MAC
- Java版本:java version "1.8.0_151"
- notes.ini 配置:
DISABLE_SSLV3=1 SSL_DISABLE_TLS_10=1 JavaUserOptionsFile=C:\Progra~1\IBM\Lotus\Domino\jvm\jvmoptions.txt - jvmoptions.txt 配置:
https.protocols=TLSv1.2 -Dcom.ibm.jsse2.overrideDefaultTLS=true
Domino 14 服务器配置
- 密码套件:
- ECDHE_RSA_WITH_AES_256_GCM_SHA384 [C030]
- DHE_RSA_WITH_AES_256_GCM_SHA384 [9F]
- ECDHE_RSA_WITH_AES_128_GCM_SHA256 [C02F]
- DHE_RSA_WITH_AES_128_GCM_SHA256 [9E]
- Java版本:openjdk version "17.0.8.1" 2023-08-24
- 注意:服务器由Domino 9升级而来,可能继承了需禁用的旧密码套件。
- java.security 禁用算法配置(强制Java Agent使用TLS1.2):
jdk.tls.disabledAlgorithms=SSLv3, SHA-0, SHA-1, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, DH keySize < 1024, \ DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ include jdk.disabled.namedCurves
测试代理代码与调试日志
测试代码
String smtpHost = "smtp.example.com"; // 替换为目标SMTP服务器 int smtpPort = 587; // STARTTLS通常用587端口 String username = "your_email@example.com"; // 替换为发件人邮箱 String password = "your_password"; // 替换为邮箱密码 // 收件人与邮件内容 String toEmail = "recipient@example.com"; // 替换为收件人邮箱 String subject = "Test Email with TLS 1.2"; String body = "This is a test email sent using JavaMail 1.5 enforcing TLS 1.2."; // 设置邮件属性 Properties props = new Properties(); props.put("mail.smtp.host", smtpHost); props.put("mail.smtp.port", smtpPort); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); // 启用STARTTLS props.put("mail.smtp.debug", "true"); // 强制使用TLS1.2 props.put("mail.smtp.ssl.protocols", "TLSv1.2"); // 创建会话 Session session = Session.getInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password); } }); session.setDebug(true); // 创建邮件 Message message = new MimeMessage(session); message.setFrom(new InternetAddress(username)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail)); message.setSubject(subject); message.setText(body); // 发送邮件 Transport.send(message); System.out.println("Email sent successfully with TLS 1.2!");
调试日志
TLSv1.3 <---JavaMail支持的协议版本 TLSv1.2 TLSv1.1 TLSv1 SSLv3 SSLv2Hello NHSNetSMTPClientClass.send() DEBUG: setDebug: JavaMail version 1.4ea <-----实际使用的JavaMail版本 NHSNetSMTPClientClass.send() DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc] DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "send.nhs.net", port 587, isSSL false 220 send.nhs.net ESMTP DEBUG SMTP: connected to host "XXXX_HOST_WE_ARE_CONNECTING_TO_XXXX", port: 587 EHLO ash-tst-domino 250-send.nhs.net 250-PIPELINING 250-SIZE 52428800 250-ETRN 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SIZE", arg "52428800" DEBUG SMTP: Found extension "ETRN", arg "" DEBUG SMTP: Found extension "STARTTLS", arg "" DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg "" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "DSN", arg "" STARTTLS 220 2.0.0 Ready to start TLS EHLO ash-tst-domino javax.mail.MessagingException: Can't send command to SMTP host; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
排查建议
1. 确认远程SMTP服务器支持的密码套件
使用openssl命令获取服务器支持的TLS1.2密码套件:
openssl s_client -connect smtp.example.com:587 -starttls smtp
在输出中查找Cipher Suite相关字段,记录所有支持的套件。
2. 检查Domino JVM可用的密码套件
在测试代理中添加代码,打印当前JVM支持的TLS1.2密码套件:
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLParameters; // ... 现有代码 ... // 在创建Session前添加以下代码 SSLContext tlsContext = SSLContext.getInstance("TLSv1.2"); tlsContext.init(null, null, null); SSLParameters params = tlsContext.getDefaultSSLParameters(); String[] availableSuites = params.getCipherSuites(); System.out.println("JVM可用的TLS1.2密码套件:"); for (String suite : availableSuites) { System.out.println(suite); }
对比SMTP服务器的套件列表,确认是否存在交集。
3. 解决JavaMail版本冲突
调试日志显示实际使用的是JavaMail 1.4ea,但业务要求使用mailapi-1.6.2.jar。Domino可能自带旧版本JavaMail,导致类加载优先级问题:
- 将mailapi-1.6.2.jar上传到代理所在的Domino数据库中,确保代理优先加载该版本。
- 检查Domino服务器的类路径配置,排除自带的旧版本JavaMail。
4. 强制指定兼容的密码套件
在JavaMail的Properties中添加指定的密码套件,使用步骤1中获取的SMTP服务器支持的套件:
// 替换为实际兼容的套件列表 props.put("mail.smtp.ssl.ciphersuites", "ECDHE_RSA_WITH_AES_256_GCM_SHA384,DHE_RSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_128_GCM_SHA256");
5. 调整Domino服务器SSL密码套件
- Domino 9:当前配置的密码套件均为RC4、DES等已被Java安全配置禁用的旧套件,需在服务器文档中添加支持TLS1.2的现代套件(如AES-GCM系列),然后重启Domino服务器。
- Domino 14:确认服务器文档中的密码套件未被java.security配置禁用,若存在重复禁用项,调整java.security文件保留必要的套件。
6. 验证JVM安全配置生效
在代理中添加代码,打印当前JVM的安全配置参数:
System.out.println("jdk.tls.disabledAlgorithms: " + System.getProperty("jdk.tls.disabledAlgorithms")); System.out.println("https.protocols: " + System.getProperty("https.protocols")); System.out.println("com.ibm.jsse2.overrideDefaultTLS: " + System.getProperty("com.ibm.jsse2.overrideDefaultTLS"));
确认配置与预期一致,尤其是jdk.tls.disabledAlgorithms未禁用必要的密码套件。
内容的提问来源于stack exchange,提问作者nick wall
相关产品推荐
相关产品推荐

