Search code examples
androiddelphiopensslindy10delphi-10.2-tokyo

Delphi, Android, SSL - IdSMTP ConnectTimeout - after preset timeout does not terminate connection to the server


When I set ConnectTimeout at IdSMTP (for example, 30 sec) and the SMTP server is unavailable, it takes off from the SMTP server approximately 105 sec.

This is the Indy component in version 10 - *250.bpl, OpenSSL v1.0.2.

With IdFTP ConnectTimeout work without any problems.

Where may be a bug?

...
IdOpenSSLSetLibPath(FDocumentsPath);

SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
SMTP:= TIdSMTP.Create(nil);
MSG:= TIdMessage.Create(nil);

try
  SSLHandler.SSLOptions.Method:= sslvSSLv23;
  SSLHandler.SSLOptions.Mode := sslmClient;

  SMTP.IOHandler := SSLHandler;
  SMTP.UseTLS:= utUseImplicitTLS;
  SMTP.AuthType:= satDefault;

  SMTP.Port:= 465;
  SMTP.Host:= xxx.xxx.xxx.xxx;
  SMTP.Username:= xxxxx;
  SMTP.Password:= xxxxx;

  SMTP.ConnectTimeout:= 30000;
  SMTP.ReadTimeout:= 30000;

  try
    SMTP.Connect;
  except
  end;

  ...
finally
  SMTP.Disconnect;
  UnLoadOpenSSLLibrary;

  FreeAndNil(MSG);
  FreeAndNil(SSLHandler);
  FreeAndNil(SMTP);
end;

Solution

  • ConnectTimeout is implemented by TIdIOHandlerStack and so applies equally to all TCP client components (IOW, TIdFTP and TIdSMTP use the exact same timeout logic).

    However, you have to take into account that ConnectTimeout only applies to the actual connection attempt (the call to the socket API connect() function). It does not apply to the time needed to resolve a hostname to an IP address, or to the time needed to create and tear down the worker thread that performs the actual connection while the timeout is monitored. So ConnectTimeout is not exact.

    A 30 sec timeout taking 105 sec could mean DNS is taking a long time to resolve the hostname, or it could mean the socket API is not aborting the connect() call in a timely manner once the timeout has elapsed. Debug the code to see where the time is actually being spent. Check the OnStatus event to see how much time elapses between the hsResolving and hsConnecting notifications, and between the hsConnecting notification and subsequent exception when the socket fails to connect to the server.