Enviar e-mail no Delphi [Indy]


Olá pessoal, hoje iremos desenvolver uma simples aplicação para o envio de e-mail com o componente Indy no Delphi XE. Não vamos fazer nada muito complexo, vamos apenas ver como é o funcionamento e conhecer melhor a ferramenta Indy na parte do envio.
Pessoal, para o exemplo utilizarei novamente o servidor do Gmail, mas nada impede o uso de outros servidores.
Vamos criar em tempo de execução os objetos "TIdSMTP, TIdText, TIdAttachmentFileTIdMessage e TIdSSLIOHandlerSocketOpenSSL". Primeiro passo vamos precisar ter as .dll (ssleay32.dll e libeay32.dll) nas pasta com o executável do sistema, abas tem que estarem na mesma versão e compatível com a versão do Delphi que estão utilizando!

Então vamos começar, vamos iniciar um novo projeto (File > New > Multi-Device Application – Delphi)

Primeiro passo e adicionar as declarações das classes do Indy na seção uses do formulário, já que vamos criar em tempo de execução elas não se adicionam automaticamente.
uses
  System.SysUtils, Vcl.Forms, IdSMTP, IdSSLOpenSSL, IdMessage, IdText, IdAttachmentFile, 
IdExplicitTLSClientServerBase;

Antes vamos criar uma classe que irá nos retornar a mensagem de como esta o nosso envio de e-mail!
Vamos para o menu (File > New > Unit - Delphi), e salvamos com o nome "Service.Mail". Agora colocamos nossa Classe TMensagemMail.
type
  TMensagemMail = class
  private
    FMensagem: String;
  public
    property Mensagem: String read FMensagem write FMensagem;
  end;
Por enquanto esta classe só irá nos retornar uma mensagem de enviado com sucesso! 

Já podemos implementar a Classe TServiceMail para o envio do e-mail.
  TServiceMail = class
  public
    function EnviarMail: TMensagemMail;
  end;

implementation

uses
  System.SysUtils, IdSMTP, IdSSLOpenSSL, IdMessage, IdText, IdAttachmentFile, IdExplicitTLSClientServerBase;

{ TEnvioEmail }

function TServiceMail.EnviarMail: TMensagemMail;
var
  lSSL: TIdSSLIOHandlerSocketOpenSSL;
  lSMTP: TIdSMTP;
  lMessage: TIdMessage;
  lText: TIdText;
  lAnexo: string;
begin
  Result := TMensagemMail.Create;
  lSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  try
    lSMTP := TIdSMTP.Create(nil);
    try
      lMessage := TIdMessage.Create(nil);
      try
        lSSL.SSLOptions.Method := sslvSSLv23;
        lSSL.SSLOptions.Mode := sslmClient;
        lSMTP.IOHandler := lSSL;
        lSMTP.AuthType := satDefault;
        lSMTP.UseTLS := utUseImplicitTLS;
        lSMTP.Host := 'smtp.gmail.com';
        lSMTP.Port := 465;
        lSMTP.Username := 'EmailDeEnvio@gmail.com';
        lSMTP.Password := 'Senha do e-mail';
        lMessage.From.Address := 'EmailDeEnvio@gmail.com';
        lMessage.From.Name := 'Nome do remetente';
        lMessage.ReplyTo.EMailAddresses := lMessage.From.Address;
        lMessage.Recipients.Add.Text := 'QuemIraReceber@hotmail.com';
        {lMessage.Recipients.Add.Text := 'QuemIraReceber02@email.com';
        lMessage.Recipients.Add.Text := 'QuemIraReceber03@email.com';}
        lMessage.Subject := 'Assunto no envio de e-mail';
        lMessage.Encoding := meMIME;
        lText := TIdText.Create(lMessage.MessageParts);
        lText.Body.Add('Corpo do e-mail');
        lText.ContentType := 'text/plain; charset=iso-8859-1';
        lAnexo := ExtractFilePath(Application.ExeName) + 'Anexo.pdf';
        if FileExists(lAnexo) then begin
          TIdAttachmentFile.Create(lMessage.MessageParts, lAnexo);
        end;
        lAnexo := ExtractFilePath(Application.ExeName) + 'Anexo02.pdf';
        if FileExists(lAnexo) then begin
          TIdAttachmentFile.Create(lMessage.MessageParts, lAnexo);
        end;
        try
          lSMTP.Connect;
          lSMTP.Authenticate;
        except
          on E:Exception do begin
            Result.Mensagem := E.Message;
            Exit;
          end;
        end;
        try
          lSMTP.Send(lMessage);
          Result.Mensagem := 'E-mail enviado com sucesso!';
        except
          On E:Exception do begin
            Result.Mensagem := E.Message;
          end;
        end;
      finally
        lMessage.Free;
      end;
    finally
      lSMTP.Free;
    end;
  finally
    lSSL.Free;
    UnLoadOpenSSLLibrary;
  end;
end;

TIdSSLIOHandlerSocketOpenSSL = Configuração do protocolo SSL
TIdSMTP = Configuração do servidor SMTP
lSMTP.Connect = Conexão e autenticação
TIdMessage = Configuração da mensagem
TIdText = Configuração do corpo do e-mail
TIdAttachmentFile = Opcional - Anexo da mensagem
UnLoadOpenSSLLibrary = liberação da DLL

No form principal colocamos um botão para colocar o código do envio do e-mail.
procedure TFSistema.ButtonEnviarEmailClick(Sender: TObject);
var
  lEmailService: TServiceMail;
begin
  try
    lEmailService := TServiceMail.Create;
    ShowMessage(lEmailService.EnviarMail.Mensagem);
  finally
    lEmailService.Free;
  end;
end;

Ao realizar o envio, haverá uma pausa de alguns segundos durante a conexão, autenticação e envio da mensagem. Então pode se utilizar uma Thread para que o envio seja feito em um fluxo paralelo de processamento e com isso não trave a aplicação do cliente.

Para enviar um e-mail formatado em HTML, basta utilizar o objeto TIdText no exemplo acima e inserir as tags da linguagem:
    lText := TIdText.Create(lMessage.MessageParts);
    lText.Body.Add('<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"></head>');
    lText.Body.Add('<body text="#000000" bgcolor="#FFFFFF">');
    lText.Body.Add('<h1>Texto - HTML.</h1><br>');
    lText.Body.Add('<p>Texto de envio com caracteres especiais ÁÉÍÓÚÇçáéíúó ÝÍÃãõÕ</p><br>');
    lText.Body.Add('</body></html>');
    lText.ContentType := 'text/html; charset=iso-8859-1';

Anexar arquivos à mensagem também requer uma nova classe mas o uso dela é mais simples. Para cada arquivo que desejar anexar, instancie um TIdAttachment vinculado à mensagem antes de enviá-la:
    TIdAttachment.Create(IdMessage.MessageParts, 'C:\Anexo.pdf');

Dificilmente um servidor não exigirá autenticação AuthenticationType do usuário. Mas, essa configuração é apenas passar o nome do usuário e sua senha antes de tentar se conectar:
  if (UsarAutenticacao) then begin
    lSMTP.AuthenticationType := atLogin;
    lSMTP.Username := 'a.ana.paulanovello@gmail.com';
    lSMTP.Password := 'SenhaDoEmail;
  end;

Já a segurança na comunicação através de SSL ou TLS. Isso envolve a criação de instância de uma nova classe -TIdSSLIOHandlerSocket (Versão 9 do Indy) ou TIdSSLIOHandlerSocketOpenSSL (Versão 10 do Indy). O código abaixo mostra um exemplo:
  lSSL.SSLOptions.Method := sslvSSLv23;
  lSSL.SSLOptions.Mode := sslmClient;
  { Associa ao SMTP a configuração para segurança }
  lSMTP.IOHandler := lSSL;

Para enviar o mesmo e-mail para múltiplos destinatários de uma só vez, basta você adicionar os endereços de e-mails dos destinatários lMessage.Recipients.Add.Text.
  lMessage.Recipients.Add.Text := 'a.ana.paulanovello@gmail.com';

Exemplo: Download do exemplo

10 comentários:

  1. Ana Paula, infelizmente não consegui usar seu exemplo pra enviar email com
    minha conta no Gmail, tentei porta 465 e 587. acredito que seja devido ao
    sistema de proteção de contas do Gmail, pois verificando não vi jeito de adicionar e autorizar meu sistema a fazer login com minha conta.
    estou usando assim e esta funcionando:
    procedure TFEmail.btEnviarClick(Sender: TObject);
    var
    i: integer;
    //anexo: TIdAttachmentFile;
    body: TIdText;
    provedor: string;
    begin
    try
    StreamMessage := TMemoryStream.Create;
    IdMessage.SaveToStream(StreamMessage);
    Screen.Cursor:= crHourGlass;
    IdSMTP.Host := 'smtp';
    IdSMTP.Username := 'seu email';
    IdSMTP.Password := 'senha';
    IdSMTP.Port := 587;
    if CheckBox.Checked then
    IdSMTP.AuthType:= satDefault
    else IdSMTP.AuthType:= satNone;

    //IdMessage1.Body.Text := mmoMsg.Lines.Text;
    body:= TIdText.Create(IdMessage.MessageParts, mmoMsg.Lines);
    body.ContentType:= 'text/html';
    //provedor := RightStr(EdtPara.Text,Pos('@', EdtPara.Text)-2);

    IdMessage.Encoding:= meDefault;
    if ListBoxAnexos.Items.Count > 0 then
    begin
    IdMessage.Encoding:= meMIME;
    IdMessage.ContentType:= 'multipart/mixed';
    //IdMessage.ContentType:= 'multipart/alternative'; Esta envia o anexo separado da menssagem
    for i:= 0 to ListBoxAnexos.Items.Count - 1 do
    begin
    TIdAttachmentFile.Create(IdMessage.MessageParts, ListBoxAnexos.Items[i]);
    end;
    end;

    IdMessage.From.Address:= EdtOrigem.Text;
    IdMessage.Subject:= EdtAssunto.Text;
    IdMessage.Recipients.EMailAddresses := EdtPara.Text;
    //IdMessage.BccList.EMailAddresses := EdtBCC.Text;
    //IdMessage.CCList.EMailAddresses := EdtCC.Text;

    if not IdSMTP.Connected then
    IdSMTP.Connect();
    IdSMTP.Send(IdMessage);
    finally
    IdSMTP.Disconnect;
    IdMessage.Clear;
    Screen.Cursor:= crDefault;
    StreamMessage.Free;
    end;
    Application.MessageBox('Email enviado com sucesso!', 'Confirmação',
    MB_ICONINFORMATION + MB_OK);
    end;

    ResponderExcluir
  2. Olá, estou com erro no momento do "lSMTP.Authenticate;". Estou com usuario e senha corretos, as "dll's" estão com o executável na pasta, tenho a permissão na conta Gmail para aplicações menos seguras e não autentica. Poderia me dar uma luz?

    ResponderExcluir
  3. Ana Paula querida, você tem os fonte pra envio de email no delphi 7, se puder disponibilizar pra mim ficaria muito agradecido. albertosantos_se@hotmail.com

    ResponderExcluir
  4. Funcionou direitinho! Você me poupou horas de pesquisas e testes. Obrigado!

    ResponderExcluir