Delphi 11发送邮件时出现SSL negotiation failed错误求助
问题描述
我尝试使用一段Delphi代码发送邮件,但未成功。客户端能成功连接到服务器,但执行Send(IdMessage1)时,持续收到错误:两次socket error 10054 connection reset by peer,最终出现SSL negotiation failed。
PS1:在任意MAPI服务器(自建服务器、GMail、Yahoo等)上均会出现相同问题
PS2:SSL DLL已存在,且同一应用程序使用它们进行其他连接时无此问题。
涉事代码
procedure SendEmailClick(Sender: TObject); var IdMessage1: TIdMessage; Attachmentfile: TIdAttachmentFile; begin // IO HANDLER SETTINGS // With TIdSSLIOHandlerSocketOpenSSL.Create(nil) do begin Destination := 'mySrver.com:587'; Host := 'mySrver.com'; MaxLineAction := maException; Port := 587; SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2]; SSLOptions.Mode := sslmUnassigned; SSLOptions.VerifyMode := []; SSLOptions.VerifyDepth := 0; end; //SETTING SMTP COMPONENT DATA // with TIdSMTP.Create(nil) do begin Host := 'mySrver.com'; Port := 587; Username := myMailAddress; // please change to your gmail address // Password := myPassword; IOHandler := TIdSSLIOHandlerSocketOpenSSL.create; AuthType := satDefault; UseTLS := utUseExplicitTLS; // SETTING email MESSAGE DATA // IdMessage1:= TIdMessage.Create(nil); IdMessage1.Clear; // add recipient list // with IdMessage1.Recipients.Add do begin Name := 'Recipient 1'; Address := recipient1Address; // please change email address as required // end; //add Attachment to mail // Attachmentfile := TIdAttachmentFile.Create(IdMessage1.MessageParts,'Τιμολόγιο 659.PDF'); IdMessage1:= TIdMessage.Create(nil); IdMessage1.From.Address := myMailAddress; // please change to your gmail address //; IdMessage1.Subject := 'Test Email Subject'; IdMessage1.Body.Add('Test Email Body'); IdMessage1.Priority := mpHigh; TRY Connect(); // no problem here. it connects always Send(IdMessage1); // raises the error SSL negotiation failed ShowMessage('Email sent'); Disconnect(); except on e:Exception do begin ShowMessage(e.Message); Disconnect(); end; END; IdMessage1.Free; IOHandler.Free; end; AttachmentFile.Free; end;
问题分析与解决
你的代码存在几个关键错误,导致SSL协商失败:
- 重复创建
IdMessage1导致数据丢失:你先创建了一个IdMessage1并添加了收件人和附件,但随后又重新创建了新的IdMessage1实例,直接丢弃了之前的配置数据,同时造成原实例内存泄漏。 - IOHandler配置无效:开头创建的
TIdSSLIOHandlerSocketOpenSSL实例未赋值给任何变量,创建后直接被丢弃;给SMTP组件的IOHandler赋值时,新建的实例未配置SSL选项,默认配置不兼容服务器要求。 - Attachment释放逻辑错误:重新创建
IdMessage1后,原Attachmentfile已绑定到无效实例,后续释放可能引发问题。
修正后的代码
procedure SendEmailClick(Sender: TObject); var IdMessage1: TIdMessage; Attachmentfile: TIdAttachmentFile; SMTP: TIdSMTP; SSLHandler: TIdSSLIOHandlerSocketOpenSSL; begin // 创建并配置SSL Handler SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); try SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_3]; // 优先使用新版TLS,适配主流服务器 SSLHandler.SSLOptions.Mode := sslmClient; SSLHandler.SSLOptions.VerifyMode := []; SSLHandler.SSLOptions.VerifyDepth := 0; // 创建SMTP组件并配置 SMTP := TIdSMTP.Create(nil); try SMTP.Host := 'mySrver.com'; SMTP.Port := 587; SMTP.Username := myMailAddress; SMTP.Password := myPassword; SMTP.IOHandler := SSLHandler; SMTP.AuthType := satDefault; SMTP.UseTLS := utUseExplicitTLS; // 创建并配置邮件内容 IdMessage1 := TIdMessage.Create(nil); try IdMessage1.Clear; IdMessage1.From.Address := myMailAddress; IdMessage1.Subject := 'Test Email Subject'; IdMessage1.Body.Add('Test Email Body'); IdMessage1.Priority := mpHigh; // 添加收件人 with IdMessage1.Recipients.Add do begin Name := 'Recipient 1'; Address := recipient1Address; end; // 添加附件 Attachmentfile := TIdAttachmentFile.Create(IdMessage1.MessageParts, 'Τιμολόγιο 659.PDF'); try // 连接并发送邮件 SMTP.Connect; try SMTP.Send(IdMessage1); ShowMessage('Email sent'); finally SMTP.Disconnect; end; finally Attachmentfile.Free; end; finally IdMessage1.Free; end; finally SMTP.Free; end; finally SSLHandler.Free; end; end;
额外注意事项
- 优先启用
sslvTLSv1_2和sslvTLSv1_3,目前大部分邮件服务器已不再支持老旧的TLSv1.0和TLSv1.1。 - 确保使用的Indy版本为较新的稳定版,旧版本可能存在SSL协商的兼容性问题。
- 确认服务器SMTP端口对应的TLS模式:587端口通常使用
utUseExplicitTLS,465端口使用utUseImplicitTLS,不要混淆。
内容的提问来源于stack exchange,提问作者user3140961
相关产品推荐
相关产品推荐

