Viktor Anastasov
Viktor Anastasov

Reputation: 1113

Check if mail is sent with TIdSmtpRelay and handle error if not

I'm trying to send mail with the TIdSMTPRelay component of Indy and this is the procedure I use :

procedure tryRelayTask;
var
  relayMsg : TIdMessage;
  LRelayRecipients: TIdEMailAddressList;
  LRelay : TIdSmtpRelay;
  SSLHandler : TIdSSLIOHandlerSocketOpenSSL;
begin
  relayMsg := TIdMessage.Create;
  relayMsg.LoadFromFile(mailFileName);
  try
    LRelayRecipients := TIdEMailAddressList.Create(nil);
    try
      LRelayRecipients.Add.Address := recipientEmailAddress;
      LRelay := TIdSMTPRelay.Create(nil);
      try
        SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create;
        try
          SSLHandler.SSLOptions.KeyFile := myKeyFile;
          SSLHandler.SSLOptions.CertFile := myCertFile;
          SSLHandler.SSLOptions.RootCertFile := myRootCertFile;
          LRelay.IOHandler := SSLHandler;
          LRelay.SSLOptions.SSLSupport := SupportSSL;
          LRelay.DNSServer := myRelayDNSServer;            
          LRelay.Send(relayMsg, LRelayRecipients) ;
          if Lrelay.StatusList.Items[0].Sent then begin
            // message is sent ok ?
          end
          else begin
            // message is not sent ok - handleError
            handleRelayError(LRelay.StatusList.Items[0].ExceptionMessage);
          end;
        finally
          SSLHandler.Free;
        end;
      finally
        LRelay.Free;
      end;
    finally
      LRelayRecipients.Free;
    end;
  finally
    relayMsg.Free;
  end;
end;

Sometimes the property Lrelay.StatusList.Items[0].Sent is False but the message is actually sent and therefore if I try to send it again I will end up sending it successfully N times instead of only 1. Can someone help me to send messages correctly with the TIdSMTPRealy component ?

Upvotes: 1

Views: 831

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596352

The TIdSMTPRelayStatusItem.Sent property tells you whether the email was accepted by the SMTP server of the recipient specified in the TIdSMTPRelayStatusItem.EmailAddress property. That does not tell you whether or not the email was actually delivered to the recipient itself. The SMTP protocol does not provide that information to senders. An SMTP server may accept an email for a recipient that it has to then forward/relay to another SMTP server in the background. The only way to know if the email was delivered to the recipient is if the recipient itself sends an acknowledgement email back to the sender's mailbox.

If the TIdSMTPRelayStatusItem.Sent property is False, it means that an exception was raised during delivery to the recipient's SMTP server. The Message of the exception is available in the TIdSMTPRelayStatusItem.ExceptionMessage property. If the exception was raised due to an error message sent by the SMTP server, the TIdSMTPRelayStatusItem.ReplyCode and TIdSMTPRelayStatusItem.EnhancedCode properties are also populated. Either way, you will also get an TIdSMTPRelay.OnDirectSMTPStatus event with its Action parameter set to dmWorkEndWithException instead of dmWorkEndOK.

So, the only way the email could have been delivered to a given recipient but its Sent value is False is if either:

  1. the SMTP server accepted the email but sent an error reply back to TIdSMPTRelay

  2. an uncaught exception was raised after delivery was successful but before a Sent=True status item could be created/populated.

Upvotes: 1

Related Questions