3

I'm trying to send email from my application using the following code:

  Var
  MailMessage : TIdMessage;
  SMTP        : TIdSMTP
   .
   .
   .
 //setup SMTP
 SMTP.Host := 'smtp.gmail.com';
 SMTP.Port := 25;
 //setup mail message
 MailMessage.From.Address := 'fromMe@gmail.com';
 MailMessage.Recipients.EMailAddresses := 'ToSomeOne@hotmail.com';
 MailMessage.Subject := 'Test';
 MailMessage.Body.Text := 'Hello, It is Just for test';

 SMTP.Connect;
 SMTP.Send(MailMessage);

When i run it, it generates the following error

**ERROR: Must issue a STARTTLS command first. i29sm34080394wbp.22**

How can I solve this?

james.garriss
  • 12,959
  • 7
  • 83
  • 96
ae1080
  • 374
  • 2
  • 7
  • 14
  • You should familiarize yourself with STARTTLS: http://en.wikipedia.org/wiki/STARTTLS and https://www.fastmail.fm/help/technology_ssl_vs_tls_starttls.html are both helpful. – james.garriss Jan 18 '13 at 19:41

3 Answers3

8

By putting the answers together you can get the following code. Don't forget as Nathanial Woolls mentioned here to put the libeay32.dll and ssleay32.dll libraries for instance from here to your project folder or to a path from the following places.

uses
  IdMessage, IdSMTP, IdSSLOpenSSL, IdGlobal, IdExplicitTLSClientServerBase;

procedure SendEmail(const Recipients: string; const Subject: string; const Body: string);
var
  SMTP: TIdSMTP;
  Email: TIdMessage;
  SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
  SMTP := TIdSMTP.Create(nil);
  Email := TIdMessage.Create(nil);
  SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);

  try
    SSLHandler.MaxLineAction := maException;
    SSLHandler.SSLOptions.Method := sslvTLSv1;
    SSLHandler.SSLOptions.Mode := sslmUnassigned;
    SSLHandler.SSLOptions.VerifyMode := [];
    SSLHandler.SSLOptions.VerifyDepth := 0;

    SMTP.IOHandler := SSLHandler;
    SMTP.Host := 'smtp.gmail.com';
    SMTP.Port := 587;
    SMTP.Username := 'yourusername@gmail.com';
    SMTP.Password := 'yourpassword';
    SMTP.UseTLS := utUseExplicitTLS;

    Email.From.Address := 'yourusername@gmail.com';
    Email.Recipients.EmailAddresses := Recipients;
    Email.Subject := Subject;
    Email.Body.Text := Body;

    SMTP.Connect;
    SMTP.Send(Email);
    SMTP.Disconnect;

  finally
    SMTP.Free;
    Email.Free;
    SSLHandler.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SendEmail('recipient@whatever.com', 'Subject', 'Body');
end;

Hope this help

Community
  • 1
  • 1
TLama
  • 75,147
  • 17
  • 214
  • 392
  • 2
    Get rid of the assignments to the `SSLHandler.Destination`, `SSLHandler.Host`, and `SSLHandler.Port` properties. Those properties are filled in automatically by `Connect()`. – Remy Lebeau Oct 11 '11 at 00:08
6

smtp.gmail.com forces you to use an encrypted connection using STARTTLS.

Indy 9 does not support STARTTLS directly, but indy 10 does.

In Indy 10, before connecting to the server, you have to assign an SSL-enabled IOHandler, such as TIdSSLIOHandlerSocketOpenSSL,

See: http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdSSLIOHandlerSocketOpenSSL.html

Add the following code:

var
...
SSLHandler: TIdSSLIOHandlerSocketOpenSSL;

SSLHandler:= TIdSSLIOHandlerSocketOpenSSL.Create(Form1);
SMTP.IOHandler:= SSLHandler;
SMTP.UseTLS:= utUseExplicitTLS;
SMTP.Username:= 'username';
SMTP.Password:= 'password';
SMTP.Port:= 587; 

If you just SMTP to a non-encrypted SMTP-handler (your ISP's SMTP) you will not suffer this problem.

Johan
  • 74,508
  • 24
  • 191
  • 319
  • 2
    @Johna: saying _Indy 9 does not support this_ is wrong. Indy 9 does support SSL encryption, it just does not support the STARTTLS command that GMail's SMTP server requires. You can send the STARTTLS command manually with a few extra lines of code, though. As for the `OnGetPassword` event, that only applies if a password-protected SSL certificate is being used (which is not the case with GMail). – Remy Lebeau Oct 11 '11 at 00:11
  • @RemyLebeau-TeamB, thanks for pointing that out, it's been a while since I used Indy. – Johan Oct 11 '11 at 08:44
  • @RemyLebeau Is it possible to send STARTTLS manually with Indy 8? I have an app which uses Indy 8. I can send emails using SSL connection but only if the server is using implicit TLS. I would like to add the support of STARTTLS. If it's possible, please tell me how – CITBL Jul 21 '13 at 12:34
3

The error is because Gmail uses SSL and TLS. You're going to need to use Indy's SSL IO handler as well as the proper OpenSSL DLL's for your Indy version.

There a tutorial on getting this working here.

Community
  • 1
  • 1
Nathanial Woolls
  • 5,231
  • 24
  • 32