You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 04:42:08