C++Builder 11.0下Indy 10.6.2.0无法启用TLS 1.1及以上版本
问题描述
尝试使用仅支持TLS 1.1及更高版本的SMTP服务器发送邮件,但在C++Builder 11.0环境下使用Indy 10.6.2.0时无法启用正确的TLS版本。已将libcrypto-1_1.dll和libssl-1_1.dll复制到应用程序目录,但问题仍未解决。
抛出EIdOSSLUnderlyingCryptoError异常,错误信息为:
error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version
相关代码
IdSMTP *IdSMTP1; TIdText *IdText1; TIdMessage *IdMessage1; TIdAntiFreeze *IdAntiFreeze1; TIdAttachmentFile *IdAttachment1, *IdAttachment2; try { Form1->AX0CPos = 109900; UnicodeString UX0SNom = " "+ AX0SNom.SubString(0, AX0SNom.Length()-1); if(!GAntiFreeze) { IdAntiFreeze1 = new TIdAntiFreeze(NULL); IdAntiFreeze1->IdleTimeOut = 250; } Form1->AX0CPos = 109901; IdSMTP1 = new TIdSMTP(NULL); TIdSSLIOHandlerSocketOpenSSL *IdSSLIOHandlerSocketOpenSSL1 = new TIdSSLIOHandlerSocketOpenSSL(IdSMTP1); //IdSSLIOHandlerSocketOpenSSL1->SSLOptions->Method = sslvTLSv1_1; // Either Version or Method !!! IdSSLIOHandlerSocketOpenSSL1->SSLOptions->SSLVersions.Clear(); IdSSLIOHandlerSocketOpenSSL1->SSLOptions->SSLVersions << sslvTLSv1_1 << sslvTLSv1_2; IdSSLIOHandlerSocketOpenSSL1->SSLOptions->Mode = sslmClient; // ? IdSSLIOHandlerSocketOpenSSL1->PassThrough = false; Form1->AX0CPos = 109902; IdSMTP1->IOHandler = IdSSLIOHandlerSocketOpenSSL1; //IdSMTP1->Host = _D("ssl0.ovh.net"); IdSMTP1->Host = _D("smtp.mail.ovh.net"); IdSMTP1->Port = 465; IdSMTP1->UseTLS = utUseImplicitTLS; //utUseRequireTLS; utUseExplicitTLS; IdSMTP1->Username = _D("MyUserName"); IdSMTP1->Password = _D("MyPassWord"); IdSMTP1->AuthType = satDefault; Form1->AX0CPos = 109903; IdMessage1 = new TIdMessage(NULL); IdMessage1->Priority = mpHigh; IdMessage1->Recipients->EMailAddresses = "Recipients@Recipients.com"; IdMessage1->Subject = _D("User #"+ String(CODOPharmacie) + UX0SNom); // Form1->NRSOPharmacie IdMessage1->Encoding = meMIME; IdMessage1->ContentType = _D("multipart/mixed"); IdMessage1->CharSet = _D("UTF-8"); IdMessage1->From->Address = _D("MyUserName"); IdMessage1->From->Name = _D("MyApp"); IdMessage1->AttachmentEncoding = "MIME"; Form1->AX0CPos = 109904; IdText1 = new TIdText(IdMessage1->MessageParts, NULL); IdText1->Body->Text = AX0LMes; IdText1->ContentType = _D("text/plain"); IdText1->CharSet = _D("utf-8"); Form1->AX0CPos = 109905; if(FileExists(UX0CPDMyApp + "\OrtErr.log")) IdAttachment1 = new TIdAttachmentFile(IdMessage1->MessageParts, UX0CPDMyApp + "\OrtErr.log"); Form1->AX0CPos = 109906; if(FileExists(UX0CPDMyApp + "\HTPErr.htm")) IdAttachment2 = new TIdAttachmentFile(IdMessage1->MessageParts, UX0CPDMyApp + "\HTPErr.htm"); Form1->AX0CPos = 109907; IdSMTP1->Connect(); IdSMTP1->Send(IdMessage1); IdSMTP1->Disconnect(); } catch(Exception &EX0Vl){ AX0SNom = "Form1/SendEmail/"; AX0LMes = EX0Vl.Message; ORTErr(); } catch(...) { AX0SNom = "Form1/SendEmail/"; AX0LMes = "Exception non planifiée"; ORTErr(); }
解决思路
- 确认OpenSSL版本兼容性:Indy 10.6.2.0对OpenSSL 1.1的支持有版本细分要求,需使用1.1.1q及以上的小版本。检查当前dll版本,替换为Indy官方匹配的版本。
- 修正TLS配置逻辑:删除
IdSSLIOHandlerSocketOpenSSL1->PassThrough = false;这行代码——当UseTLS = utUseImplicitTLS时,Indy会自动处理SSL握手,手动设置PassThrough会干扰流程。保留SSLVersions的配置即可。 - 检查端口与UseTLS的匹配:端口465对应隐式TLS是正确的,但部分服务器可能要求显式TLS(端口587)。尝试切换到端口587并设置
UseTLS = utUseExplicitTLS测试。 - 强制TLS版本范围:添加代码限定最小和最大TLS版本,避免握手时协商到被服务器拒绝的旧协议:
IdSSLIOHandlerSocketOpenSSL1->SSLOptions->MinVersion = sslvTLSv1_1; IdSSLIOHandlerSocketOpenSSL1->SSLOptions->MaxVersion = sslvTLSv1_2; - 升级Indy组件:Indy 10.6.2.0存在已知的TLS配置bug,升级到最新的Indy 10稳定版本(如10.6.2.5及以上)可修复此类问题。
- 验证库位数匹配:如果编译的是64位应用,必须使用64位的
libcrypto-1_1.dll和libssl-1_1.dll;32位应用则用32位库,位数不匹配会导致SSL握手异常。
内容的提问来源于stack exchange,提问作者ibouka
相关产品推荐
相关产品推荐

