Delphi ISAPI连接内的TidSMPT在一段时间后关闭

Delphi ISAPI连接内的TidSMPT在一段时间后关闭,delphi,smtp,indy,delphi-xe7,isapi,Delphi,Smtp,Indy,Delphi Xe7,Isapi,我们所看到的情况: 我有一个ISAPI应用程序,它使用TidMessage发送电子邮件。它运行在我们的实时网络服务器上,发送电子邮件在相当长一段时间内没有问题。然后它会突然停止工作,我们开始看到一个错误,表示连接正常关闭。我所要做的就是重新启动IIS,或者重新启动服务器,一切都会重新开始工作,没有问题 我们正在做的是: ISAPI在第一次需要时创建一个TIDSSMTP和TIdSSLIOHandlerSocketOpenSSL。当系统卸载时,这些实例是空闲的。当ISS卸载ISAPI时(它可能没有卸

我们所看到的情况:

我有一个ISAPI应用程序,它使用TidMessage发送电子邮件。它运行在我们的实时网络服务器上,发送电子邮件在相当长一段时间内没有问题。然后它会突然停止工作,我们开始看到一个错误,表示连接正常关闭。我所要做的就是重新启动IIS,或者重新启动服务器,一切都会重新开始工作,没有问题

我们正在做的是:

ISAPI在第一次需要时创建一个TIDSSMTP和TIdSSLIOHandlerSocketOpenSSL。当系统卸载时,这些实例是空闲的。当ISS卸载ISAPI时(它可能没有卸载),或者当我们重新启动、回收、重新启动iis时

然后,每次我们需要发送电子邮件时,我们都会创建一条TidMessage和任何其他需要的对象。然后我们会在邮件发送后释放他们

我的理论是:

我记得几年前,我在一个旧的NT机箱上处理了一个类似的问题,问题是系统的管道用完了,然后我们会重新启动,所有这些都会再工作几个月

问题:

我想知道是否有人知道这可能是什么原因? 我们能用光管道吗,或者类似的东西

我们的发送电子邮件代码:

    procedure TSendMailEngine.sendEmail(
  const recipient, cc, replyTo, subject: string;
  const plainTextList, attachmentList, htmlTextList: TStrings);

  procedure AddMailSection(parts: TIdMessageParts; const section, contentType: string; const parentPart: integer); overload;
  var
    msgPart: TIdText;
  begin
    msgPart := TIdText.Create(parts, nil);
    msgPart.Body.Text   := section;
    msgPart.ContentType := contentType;
    msgPart.ParentPart  := parentPart; // set to 0 if hasHtml and hasPlainText and hasAttachments, otherwise it defaults to -1
  end;

  procedure AddMailSection(eMailMessage: TIdMessage; const section, contentType: string); overload;
  begin
    eMailMessage.Body.Text   := section;
    eMailMessage.ContentType := contentType;
  end;

  procedure AddAttachments(parts: TIdMessageParts; attachments: TStrings);
  var
    cntr: Integer;
  begin
    for cntr := 0 to attachments.Count - 1 do
      if FileExists(attachments[cntr]) then
        TIdAttachmentFile.Create(parts, attachments[cntr]).FileName := ExtractFileName(attachments[cntr]);
  end;

var
  hasPlainText,
  hasHtml,
  hasAttachments: boolean;
  parentPart: Integer;
  eMailMessage: TIdMessage;
  //contentIndex: Integer;
begin
  parentPart := -1;
  eMailMessage := TIdMessage.Create;
  try
    InitMessage(eMailMessage); // adds date, encoding, from info, etc

    SetMessageHeader(eMailMessage, recipient, cc, replyTo, subject);

    hasPlainText   := Assigned(plainTextList ) and (plainTextList.Count  > 0);
    hasAttachments := Assigned(attachmentList) and (attachmentList.Count > 0);
    hasHtml        := Assigned(htmlTextList  ) and (htmlTextList.Count   > 0);


    if hasPlainText and not(hasHtml or hasAttachments) then
      AddMailSection(eMailMessage, plainTextList.Text, 'text/plain')  // only a text body
    else if hasHtml and not(hasPlainText or hasAttachments) then
      AddMailSection(eMailMessage, htmlTextList.Text, 'text/html')    // only an html body
    else // mixed message type
    begin
      eMailMessage.ContentType := 'multipart/alternative';

      if hasPlainText and hasAttachments and hasHtml then
      begin
        parentPart := 0;
        TIdText.Create(eMailMessage.MessageParts, nil).ContentType := 'multipart/alternative';
      end;

      if hasPlainText then
        AddMailSection(eMailMessage.MessageParts, plainTextList.Text, 'text/plain', parentPart);
      if hasHtml then
        AddMailSection(eMailMessage.MessageParts, htmlTextList.Text, 'text/html', parentPart);

      if hasAttachments then
      begin
        AddAttachments(eMailMessage.MessageParts, attachmentList);
        eMailMessage.Encoding := meMIME;
        eMailMessage.ContentType := 'multipart/mixed';
      end;
    end;

    Send(eMailMessage);
  finally
    FreeAndNil(eMailMessage);
  end;
end;
编辑: 对Send的调用执行连接、身份验证、发送和断开连接:

procedure TSendMailEngine.Send(eMailMessage: TIdMessage);
begin
  try
    if not fSMTP.Connected then
      fSMTP.Connect;

    if fSMTP.Connected then
    begin
      if fSMTP.Authenticate then
        fSMTP.Send(eMailMessage);

      fSMTP.Disconnect;
    end;
  except
    // there will be an exception if the sendFile is cancelled
    // we want to wait until it completes before emailing the config file
    on goodE: EIdConnClosedGracefully do
      fSMTP.Disconnect;//nothing
    //on another exception just let it rise up
  end;
end;

您是否在两封电子邮件之间长时间保持与SMTP服务器的SMTP连接?如果是这样的话,那么SMTP就不是为此而设计的,根据RFC 5321第4.5.3.2.7节,服务器或防火墙可能会在空闲一段时间后断开您的连接,通常长达5分钟。您必须定期发送其他SMTP命令以使其保持活动状态。SMTP中没有类似心跳信号的命令。否则,如果发送电子邮件导致关闭正常错误,只需重新连接并重试电子邮件即可。@RemyLebeau此代码正在间歇性调用,我们的负载不是很重。每天只有几封电子邮件。据此,最后发送电子邮件前的最后一行;调用一个函数,该函数在内部调用connect、authenticate、send,然后disconnect。。。在不查看实际TCP通信量的情况下,将该代码添加到我的问题中,我只能假设1服务器不喜欢它正在接收的电子邮件数据,因此它立即关闭了连接,或者2在发送过程中发生了一些其他异常,导致TIdSMTP在内部调用Disconnect。您是否使用SSL/TLS?然后在您再次调用Connect之前,它会在下一个套接字操作中引发closed gracefully错误。