Jump to content
NBilov

Sending email by Delphi Sydney on windows 7

Recommended Posts

I have windows 7 . My program sended mail by smtp , with ssl encoding. It worked without any problems on Delphi 2010 , when the same code was compiled on Delphi 10.4.2 it started to raise error " SSL negotiation failed." I need to send from @yandex.ru mail where ssl encoding is obligatory. How can i make such sending on this operation system and compiled with this version of Delphi ?

My code:

procedure TfmMain.buSimpSendClick(Sender: TObject);
var
  IdSMTP1: TIdSMTP;
  idMessage1: TIdMessage;
  idAttach: TidAttachment;
  idText1: TidText;
  msgParts: TidMessageParts;
  DT:TDateTime;
  IdSSLIOHandlerSocketOpenSSL1:TIdSSLIOHandlerSocketOpenSSL;
  MailHost,EmpPsw,EmpUser: string;
  EmPort: Integer;
  EmpEmail: string;
  EmpName: string;
  EmailTo: string;
  I: Integer;
  wassent: Boolean;
  ini: TIniFile;
begin
  EmPort := 587;

  EmailTo :=  '';

  ini := Tinifile.Create(ChangeFileExt(paramStr(0),'.ini')) ;
  try
    MailHost := ini.ReadString('C','MailHost','');
    EmpPsw := ini.ReadString('C','EmpPsw','');
    EmpUser := ini.ReadString( 'C','EmpUser','');
    EmPort := ini.ReadInteger('C','EmPort',0);
    EmailTo := ini.ReadString('C','EmailTo','');

  finally
    ini.Free;
  end;

  memo1.Text := '';
  Edit1.Text :=  'MailHost='+MailHost+','+'EmpPsw='+EmpPsw+','+'EmpUser='+EmpUser+','+'EmPort='+IntToStr(EmPort)+','+'EmailTo='+EmailTo
  ;
  EmpName := empemail;//(nil);

  wassent := True and false;//(nil);
 

  IdSMTP1 := TIdSMTP.Create(nil) ;
  try
  try
    IdSMTP1.Host:= MailHost;
    IdSMTP1.Password:= EmpPsw;
    IdSMTP1.Username:= EmpUser;
 

    IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP1);

    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;

    IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
    if EmPort>0 then
    IdSMTP1.Port := EmPort
    else
    IdSMTP1.Port := 465;
    IdSMTP1.UseTLS := utUseExplicitTLS;

    idMessage1 := TIdMessage.Create(IdSMTP1);

    idMessage1.OnInitializeISO := TCL.LInitializeISO;
    idMessage1.From.Address := EmpEmail;
    idMessage1.From.Name := EmpName;

    idMessage1.Subject := 'EmSubject'+DateTimeToStr(now);//'Письмо с картинкой AComp'+FormatDateTime('dd.mm.yyyy hh:mm:ss',Now);

    idMessage1.CharSet := 'Windows-1251';
    idMessage1.ContentTransferEncoding  := '8bit';

    msgParts := idMessage1.MessageParts;
    try
      // Load slBody with your HTML text...
      idText1 := TidText.Create(msgParts);//, slBody);
      idText1.ContentType := 'text/html';
      idText1.CharSet := 'Windows-1251';
      idText1.ContentTransfer := '8bit';
      //if FileExists(EmBodyFileName) then
      idText1.Body.Text := ' (EmailBody)'+ParamStr(0);
      idMessage1.Recipients.EMailAddresses := EmailTo;
      idSMTP1.Connect;
      idSMTP1.Send(idMessage1);
      ShowMessage('Sent ok,''EmPort='+IntToStr(EmPort)); wassent := True;

    finally
      if idSMTP1.Connected then
      idSMTP1.Disconnect;

    end;

  except on E: Exception do Memo1.text :=  Memo1.text + #13#10 + 'EmPort='+IntToStr(EmPort)+#13#10+ E.Message;
  end;
  finally
    IdSMTP1.Free;
    self.caption := TimeToStr(now);
  end;
end;

Share this post


Link to post

The first thing that comes to my mind is ... did you copy the proper / latest SSL lib DLLs onto your system? They are not distributed with Delphi.

 

I've got 10.4.2 and I had problems with something that were solved by downloading the latest SSL DLLs.

Share this post


Link to post

Try the @David Schwartz suggestion (this is the official library of Indy: https://github.com/IndySockets/OpenSSL-Binaries) and also the following.

 

You use port 465, (implicit TLS) so is better to put:

 

IdSMTP1.UseTLS := utUseImplicitTLS; 

And I use that:

 

    IdSMTP1.Connect;
    IdSMTP1.Authenticate;
    if IdSMTP1.DidAuthenticate then
      begin
        IdSMTP1.Send(IdMessage1);
      end;

Hope this help you.

 

Bye

Edited by DelphiUdIT

Share this post


Link to post
55 minutes ago, NBilov said:

IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;

Most servers are phasing out TLS 1.0, or already have, You should enable TLS 1.1 and TLS 1.2 as well:

IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
55 minutes ago, NBilov said:

    if EmPort>0 then
    IdSMTP1.Port := EmPort
    else

If you allow the Port to be configurable, you should also allow the UseTLS value to be configurable as well.  There is a functional difference between utUseImplicitTLS vs utUsseExplicitTLS, so you should let your config indicate which to use on a non-default Port.

55 minutes ago, NBilov said:

    IdSMTP1.Port := 465;
    IdSMTP1.UseTLS := utUseExplicitTLS;

As mentioned earlier, this is wrong.  You need to use utUseImplicitTLS on port 465.  Use utUseExplicitTLS on port 587 instead.

 

Share this post


Link to post

On my that server almost everything is extremely old, but i will try this , thanks.

Share this post


Link to post

"

IdSMTP1.Connect;

    IdSMTP1.Authenticate;

    if IdSMTP1.DidAuthenticate then

      begin

        IdSMTP1.Send(IdMessage1);

      end; "

Is this better than my previous "

idSMTP1.Connect;

      idSMTP1.Send(idMessage1);"

 With 587 port too ? Old variant was working being compiled on Delphi 2010 since 2016 with quite large volumes without much trouble.

Share this post


Link to post
4 hours ago, NBilov said:

"

IdSMTP1.Connect;

    IdSMTP1.Authenticate;

    if IdSMTP1.DidAuthenticate then

      begin

        IdSMTP1.Send(IdMessage1);

      end; "

Is this better than my previous "

idSMTP1.Connect;

      idSMTP1.Send(idMessage1);"

 With 587 port too ? Old variant was working being compiled on Delphi 2010 since 2016 with quite large volumes without much trouble.

I always use port 465 (implicit TLS) and I must do

IdSMTP1.Connect;
IdSMTP1.Authenticate;
if IdSMTP1.DidAuthenticate then
  begin
    IdSMTP1.Send(IdMessage1);
  end;

to avoid any problem. If the simple and short way is working with port 587 there is not need to change.

 

Bye

Share this post


Link to post

TIdSMTP.Send() will call TIdSMTP.Authenticate() for you if authentication hasn't succeeded yet.  If you try to send an email without being adequately authenticated, the server will report a failure, which TIdSMTP will raise as an exception.  So really, there is little reason to check TIdSMTP.DidAuthenticate and call TIdSMTP.Authenticate() manually.

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×