通过SMTP发送邮件时如何屏蔽"Connection Closed Gracefully"对话框
彻底屏蔽Indy SMTP的"Connection Closed Gracefully"对话框
你遇到的这个弹框不是来自代码里的ShowMessage,而是Indy组件的全局异常对话框机制在作祟——即便你在局部try-except里捕获了EIdConnClosedGracefully,Indy默认会弹出全局错误对话框,这是因为它的全局控制变量GIdShowExceptionDialogs默认设为True。以下是彻底解决的方法:
解决步骤
1. 关闭Indy全局异常对话框
在程序初始化阶段(比如主窗体的OnCreate事件),或者SendEmail函数开头添加代码(需引用IdGlobal单元):
GIdShowExceptionDialogs := False;
这个设置会彻底禁用Indy所有组件的默认异常弹框,所有异常都会交给你的代码处理。如果只想在SendEmail函数范围内禁用,可以先保存原有设置,执行完后恢复:
var OldShowState: Boolean; begin OldShowState := GIdShowExceptionDialogs; GIdShowExceptionDialogs := False; try // 原有邮件发送逻辑 finally GIdShowExceptionDialogs := OldShowState; end; end;
2. 完善Disconnect逻辑避免二次异常
当前代码的finally块直接调用IdSMTP.Disconnect,如果连接已被远程关闭,这个操作可能再次抛出EIdConnClosedGracefully。建议先检查连接状态再执行断开:
if IdSMTP.Connected then IdSMTP.Disconnect;
修改后的完整代码
uses ..., IdGlobal; // 需添加IdGlobal单元引用 procedure SendEmail(Host, From, Recipients, Subject, Body, CC, BCC, ReplyTo: string; Port: Integer; IsBodyHtml: Boolean); const CHARSET_UTF8 = 'utf-8'; var IdSMTP: TIdSMTP; IdMessage: TIdMessage; builder: TIdMessageBuilderHtml; OldShowState: Boolean; begin // 临时禁用Indy全局异常对话框,执行后恢复 OldShowState := GIdShowExceptionDialogs; GIdShowExceptionDialogs := False; IdMessage := TIdMessage.Create(nil); try builder := TIdMessageBuilderHtml.Create; try builder.PlainTextCharSet := CHARSET_UTF8; builder.HtmlCharSet := CHARSET_UTF8; if IsBodyHtml then builder.Html.Text := Body else builder.PlainText.Text := Body; builder.FillMessage(IdMessage); finally FreeAndNil(builder); end; IdMessage.From.Address := From; IdMessage.Recipients.EMailAddresses := Recipients; IdMessage.Subject := Subject; IdMessage.CCList.EMailAddresses := CC; IdMessage.BccList.EMailAddresses := BCC; IdMessage.ReplyTo.EMailAddresses := ReplyTo; IdSMTP := TIdSMTP.Create(nil); try IdSMTP.Host := Host; IdSMTP.Port := Port; IdSMTP.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8; try IdSMTP.Connect; IdSMTP.Send(IdMessage); except on E: EIdConnClosedGracefully do begin // 静默处理连接优雅关闭的异常,不做任何提示 end; on E: Exception do ShowMessage('SMTP Error: ' + E.Message); end; finally // 先检查连接状态再断开,避免二次抛出异常 if IdSMTP.Connected then IdSMTP.Disconnect; FreeAndNil(IdSMTP); end; finally FreeAndNil(IdMessage); // 恢复Indy全局异常对话框设置 GIdShowExceptionDialogs := OldShowState; end; end;
内容的提问来源于stack exchange,提问作者fourwhey
相关产品推荐
相关产品推荐

