Problem with TIdSMTPBase.SendPipelining in Indy 10.0.52

Giganews Newsgroups
Subject: Problem with TIdSMTPBase.SendPipelining in Indy 10.0.52
Posted by:  Virgo Pärna (virgo.par…@mail.ee)
Date: Fri, 08 Jul 2005

    When you send a mail for several recipients and pipelining is enabled
at  Indy and in server and mail address of one recipient is incorrect
(server would detect it), then other recipients would receive partial
message without a subject and message body.
    Problem is in TIdSMTPBase.SendPipelining - it sends RSET, FROM,
recipients info and DATA commands in one batch and then checks for
errors. When there has been an error, it sends a '.' - but '.' after
DATA means end of body and the message would be sent.
    So I changed the SendPipelining to following:
begin
  LError := nil;
  try
    IOHandler.WriteBufferOpen;
    try
      IOHandler.WriteLn(RSET_CMD);
      IOHandler.WriteLn(MAILFROM_CMD+'<' + AMsg.From.Address + '>');
      WriteRecipientsPipeLine(ARecipients);
//Virgo Pärna - removed WriteLn(DATA_CMD), because if it's send here I
//cannot
//cancel sending with SendCmd(RSET_CMD) - real cancelling.
//      IOHandler.WriteLn(DATA_CMD);
    finally
      IOHandler.WriteBufferClose;
    end;
    //RSET
    GetResponse([]);
    //MAIL FROM:
    if PosInSmallIntArray(GetResponse([]),MAILFROM_ACCEPT)=-1 then
    begin
      LError := SetupErrorReply(Self);
    end;
    //RCPT TO:
    for i := 1 to ARecipients.Count do
    begin
      if PosInSmallIntArray(GetResponse([]),RCPTTO_ACCEPT)=-1 then
      begin
        if Assigned(LError)=False then
        begin
          LError := SetupErrorReply(Self);
        end;
      end;
    end;
    if Assigned(LError) then
    begin
      //cancel the message send - there was an error in the replies
      SendCmd(RSET_CMD); //Virgo Pärna - must be cancelled with RSET_CMD
      // - then no message is sent.
      //raise the exception from the first error code
      LError.RaiseReplyError;
    end
    else
    begin
    //Virgo Pärna - no error, send DATA_CMD
      SendCmd(DATA_CMD);
      //DATA - last in the batch
      //Virgo Pärna - is this necessary - could there be some error
      //at this state - but just in case
      if PosInSmallIntArray(GetResponse([]),DATA_ACCEPT)=-1 then
      begin
        if Assigned(LError)=False then
        begin
          LError := SetupErrorReply(Self);
        end;
        LError.RaiseReplyError;
      end;
      if Assigned(LError) then
      begin
        //cancel the message send - there was an error in the replies
        SendCmd('.');//Virgo Pärna - Message could still be sent.
        //raise the exception from the first error code
        LError.RaiseReplyError;
      end
      else
      begin
        SendMsg(AMsg);
        SendCmd('.', DATA_PERIOD_ACCEPT);    {Do not Localize}
      end;
    end;
  finally
    FreeAndNil(LError);
  end;
end;

Replies