[Delphi XE] Envio de e-mail com componentes Indy

Boa noite, leitores!
[Delphi XE] Envio de e-mail com componentes IndyO título do artigo parece um pouco familiar, não é? Sim, já postei um artigo referente a envio de e-mails pelo Delphi 7 em dezembro de 2013, porém, após a publicação, notei que muitas, muitas dúvidas foram postadas nos comentários e enviadas por e-mail, principalmente por desenvolvedores que utilizam as versões da família XE do Delphi. Pois bem, vamos considerar que o artigo de hoje é um “remake” daquela dica, trazendo algumas modificações e melhorias, claro, direcionadas para o Delphi XE.

 

Pessoal, para o exemplo apresentado no artigo, utilizarei novamente o servidor do Gmail, no entanto, nada impede o uso de outros servidores, desde que as configurações sejam definidas corretamente (servidor SMTP, porta, tipo de autenticação e protocolos de segurança).
Dessa vez, como estamos codificando a funcionalidade no Delphi XE, trabalharemos com 5 objetos do conjunto Indy, criados em tempo de execução: TIdSMTP, TIdMessage, TIdText, TIdAttachmentFile e TIdSSLIOHandlerSocketOpenSSL. Cada um destes objetos serão instanciados, interligados, utilizados e, após o envio, liberados da memória.

Primeiramente, é importante lembrar que as DLLs ssleay32.dll e libeay32.dll são necessárias para o envio do e-mail e devem ser copiadas para a mesma pasta onde está o executável. É aqui que a galera geralmente se perde. Muitos desenvolvedores copiam as DLLs para a pasta em que o arquivo DPROJ se encontra, já que o Delphi 7, por padrão, cria o arquivo executável na mesma pasta do projeto. Porém, as versões mais recentes do Delphi geram o executável no subdiretório “\plataforma\configuração”, como, por exemplo, “Win32\Debug”. É nesse diretório que as DLLs devem ser copiadas!
Antes que eu me esqueça, uma observação: existem várias versões disponíveis dessas DLLs. Já ajudei desenvolvedores que tentaram utilizar a versão compatível com o Delphi 7 em um projeto no Delphi XE e se depararam com alguns avisos de incompatibilidade. Portanto, para o Delphi XE, clique aqui para baixar a versão correta.

Bom, mãos à obra!
Antes de iniciarmos a codificação, devemos declarar as units das classes do Indy na seção uses do formulário:

uses
  IdSMTP, IdSSLOpenSSL, IdMessage, IdText, IdAttachmentFile,
  IdExplicitTLSClientServerBase;

 

Em seguida, já podemos implementar o código de envio do e-mail (atentem-se aos comentários):

var
  // variáveis e objetos necessários para o envio
  IdSSLIOHandlerSocket: TIdSSLIOHandlerSocketOpenSSL;
  IdSMTP: TIdSMTP;
  IdMessage: TIdMessage;
  IdText: TIdText;
  sAnexo: string;
begin
  // instanciação dos objetos
  IdSSLIOHandlerSocket := TIdSSLIOHandlerSocketOpenSSL.Create(Self);
  IdSMTP := TIdSMTP.Create(Self);
  IdMessage := TIdMessage.Create(Self);
 
  try
    // Configuração do protocolo SSL (TIdSSLIOHandlerSocketOpenSSL)
    IdSSLIOHandlerSocket.SSLOptions.Method := sslvSSLv23;
    IdSSLIOHandlerSocket.SSLOptions.Mode := sslmClient;
 
    // Configuração do servidor SMTP (TIdSMTP)
    IdSMTP.IOHandler := IdSSLIOHandlerSocket;
    IdSMTP.UseTLS := utUseImplicitTLS;
    IdSMTP.AuthType := satDefault;
    IdSMTP.Port := 465;
    IdSMTP.Host := 'smtp.gmail.com';
    IdSMTP.Username := 'usuario@gmail.com';
    IdSMTP.Password := 'senha';
 
    // Configuração da mensagem (TIdMessage)
    IdMessage.From.Address := 'remetente@gmail.com';
    IdMessage.From.Name := 'Nome do Remetente';
    IdMessage.ReplyTo.EMailAddresses := IdMessage.From.Address;
    IdMessage.Recipients.Add.Text := 'destinatario1@email.com'; 
    IdMessage.Recipients.Add.Text := 'destinatario2@email.com'; // opcional
    IdMessage.Recipients.Add.Text := 'destinatario3@email.com'; // opcional
    IdMessage.Subject := 'Assunto do e-mail';
    IdMessage.Encoding := meMIME;
 
    // Configuração do corpo do email (TIdText)
    IdText := TIdText.Create(IdMessage.MessageParts);
    IdText.Body.Add('Corpo do e-mail');
    IdText.ContentType := 'text/plain; charset=iso-8859-1';
 
    // Opcional - Anexo da mensagem (TIdAttachmentFile)
    sAnexo := 'C:\Anexo.pdf';
    if FileExists(sAnexo) then
    begin
      TIdAttachmentFile.Create(IdMessage.MessageParts, sAnexo);
    end;
 
    // Conexão e autenticação
    try
      IdSMTP.Connect;
      IdSMTP.Authenticate;
    except
      on E:Exception do
      begin
        MessageDlg('Erro na conexão ou autenticação: ' +
          E.Message, mtWarning, [mbOK], 0);
        Exit;
      end;
    end;
 
    // Envio da mensagem
    try
      IdSMTP.Send(IdMessage);
      MessageDlg('Mensagem enviada com sucesso!', mtInformation, [mbOK], 0);
    except
      On E:Exception do
      begin
        MessageDlg('Erro ao enviar a mensagem: ' +
          E.Message, mtWarning, [mbOK], 0);
      end;
    end;
  finally
    // desconecta do servidor
    IdSMTP.Disconnect;
    // liberação da DLL
    UnLoadOpenSSLLibrary;
    // liberação dos objetos da memória
    FreeAndNil(IdMessage);
    FreeAndNil(IdSSLIOHandlerSocket);
    FreeAndNil(IdSMTP);
  end;
end;

 

Ao realizar o envio, haverá uma pausa de alguns segundos durante a conexão, autenticação e envio da mensagem. Nesse meio tempo, teremos a impressão de que a aplicação não estará respondendo. Para evitar este efeito, eu sugiro implementar uma tela de espera (com um GIF animado, por exemplo), exibir uma mensagem de processamento ou utilizar uma Thread para que o envio seja feito em um fluxo paralelo de processamento.

Embora as propriedades no exemplo acima tenham sido atribuídas em tempo de execução, elas também podem, opcionalmente, ser definidas em tempo de projeto, utilizando o Object Inspector. Se o e-mail possui valores fixos (conta de e-mail, servidor, assunto), talvez essa possa ser a melhor opção devido à redução das linhas de código. Do mesmo modo, alguns valores podem ser definidos em tempo de projeto e outros valores informados em tempo de execução, como o destinatário e o corpo da mensagem, digitados pelo usuário em caixas de texto.

Só a título de conhecimento, caso a aplicação não esteja conseguindo se conectar ao servidor, talvez seja necessário alterar algumas configurações na conta do Gmail, conforme as orientações dispostas neste link.

 


Bônus 1: Para enviar um e-mail formatado em HTML, basta utilizar o objeto TIdText no exemplo acima e inserir as tags da linguagem:

IdText := TIdText.Create(IdMessage.MessageParts);
IdText.Body.Add('<html>');
IdText.Body.Add('<body>');
IdText.Body.Add('<h1><font color="red"> Teste Formatação em HTML </font></h1>');
IdText.Body.Add('</body>');
IdText.Body.Add('</html>');
IdText.ContentType := 'text/html; charset=iso-8859-1';

 

Bônus 2: Caso esteja utilizando o servidor do Terra, utilize as configurações a seguir (colaboração do leitor Ricardo Silva):

// Configuração do SMTP
IdSMTP.AuthenticationType := atLogin;
IdSMTP.Port := 587;
IdSMTP.Host := 'smtp.sao.terra.com.br';
IdSMTP.Username := 'usuario@terra.com.br';
IdSMTP.Password := 'senha';

 

Bônus 3: Aproveitando a dica acima, confira também as configurações do servidor do Office365:

// Configuração do SSL
IdSSLIOHandlerSocket.SSLOptions.Method := sslvTLSv1;
IdSSLIOHandlerSocket.PassThrough := True;
IdSSLIOHandlerSocket.SSLOptions.Mode := sslmServer;
 
// Configuração do SMTP
IdSMTP.IOHandler := IdSSLIOHandlerSocket;
IdSMTP.AuthenticationType := atLogin;
IdSMTP.Port := 587;
IdSMTP.Host := 'smtp.office365.com';
IdSMTP.Username := 'usuario';
IdSMTP.Password := 'senha';

 

 

Grande abraço, leitores! Até mais!


 

Compartilhe!
Share on FacebookTweet about this on TwitterShare on LinkedInShare on Google+Pin on PinterestEmail this to someone

157 comentários

  1. Boa tarde amigo, estou programando no Delphi xe7, porem não consigo enxergar os componentes
    TidText e TidAttachmentFile
    Como faço para adicioná-los a palleta Indy? Pois os seus respectivos arquivos dcu e pas existem no meu computador, mas não sei como adicioná-los. No Delphi xe7 e meio complicado.ja fui inclusive no menu componente/install componente, mas me enrrolei e desisti. Vc poderia me enviar um tutorial de como adicionar estes dois componentes? Vc esta de parabéns, pois seu tutorial de como enviar email esta excelente…bem simples e bem explicativo.

    1. Olá, Ney, tudo bem?

      As classes TIdText e TIdAttachmentFile não são visuais, ou melhor, não são componentes que podem ser arrastados para o formulário. Essas classes devem ser instanciadas em tempo de execução (conforme exemplificado no artigo) devido à dependência de configuração que eles possuem com o componente TIdMessage.
      Talvez seja possível criar componentes para essa finalidade, mas não acho viável.

      Caso você esteja se deparando com alguma dificuldade na configuração desses objetos, poste nos comentários!
      Abraço!

  2. Boa noite André.. Valeu pela dica, então era este o motivo pelo qual eu não conseguia visualizar os dois componentes…obrigado amigo. Qualquer dúvida te dou um toque.

  3. Bom dia André…fiz tudo bonitinho no xe7, conforme vc detalhou, porem depois que tento enviar a mensagem com um arquivo em anexo, o programa além de não enviar ainda exibe a seguinte mensagem de erro: Falha na conexão ou Autenticação………Please log in via your web browser and try again. Estou tentando enviar a mensagem e abri-la em meu celular. Onde esta o erro amigo? Como consertar? De imediato agradeço sua atenção.

    1. Fiz a seguinte alteração no código e deu certo

          // Conexão e autenticação
          try
            IdSMTP.ReadTimeout := 100000;
            IdSMTP.ConnectTimeout := 100000;
            IdSMTP.Connect;
            IdSMTP.Authenticate;
          except
            on E:Exception do
            begin
              MessageDlg('Erro na conexão ou autenticação: ' +
                E.Message, mtWarning, [mbOK], 0);
              Exit;
            end;
          end;
      
          // Envio da mensagem
    2. Olá, Edinaldo!

      Obrigado pela colaboração!
      O tempo de timeout deve ser definido conforme o perfil de rede/infraestrutura do cliente. Por exemplo, se o cliente utilizar um sistema robusto de Firewall, talvez o tempo de timeout tenha que ser maior para abrir a conexão. No seu caso, 1,5 minuto foi o suficiente.
      Opcionalmente, o desenvolvedor pode permitir que o próprio usuário define o tempo de timeout para evitar que o tempo fique fixo no código.

      Abraço!

  4. Bom dia, André. Parabéns pelo artigo. Você sabe informar como se faz para enviar e-mail com uma imagem no corpo do e-mail, não é anexar a imagem ao e-mail. É inserir a imagem que esta na pasta “C:\Users\Publico\Pictures” e inserir no corpo do e-mail. Obrigado.

    1. Olá, Otto, tudo bem?

      Desculpe-me pela demora para responder. Estive de mudança e fiquei um tempo sem internet.
      Não é possível anexar um imagem que está no seu computador no corpo do e-mail, afinal, essa mesma imagem não estará no computador do destinatário.
      Para enviar uma imagem no corpo de uma mensagem, é necessário trabalhar com HTML e, além disso, a imagem deve estar armazenada em algum servidor de imagens na Web (Photobucket, ImageShack, FileDen, etc).
      Vou enviar um e-mail para você com um exemplo, ok?

      Qualquer dúvida, estou à disposição!
      Abraço!

  5. André eu vou começar a fazer uma aplicação simples com sql server 2008 usando o Delphi xe5. Queria tirar uma dúvida. Existe alguma função que, por exemplo, quando dois ou mais usuários do sistema tentem gravar no mesmo milésimo de segundo, deixe o sistema em espera aguardando até que o banco de dados consiga armazenar um das informações? Seria como se o sistema deixasse na fila de espera por alguns segundos para não correr risco de duplicidade nos registros quando mais de um usuário estiver gravando ao mesmo tempo um determinado registro?
    Desde já agradeço sua atenção!

    1. Olá, Arlindo, tudo bem?

      Sua pergunta é bastante interessante! Bom, acredito que você está se referindo à chave primária da tabela, na qual não pode se repetir, certo?
      Essa é uma questão que é tratada de diferentes formas. Uma delas é por meio de Triggers no banco de dados. Este é um recurso que funciona como um “gatilho” quando determinado evento acontece em uma tabela, como, por exemplo, a inserção de um novo registro (On Before Insert). Sendo assim, pode-se criar uma Trigger para gerar um novo código antes que o registro seja inserido. Mesmo que dois usuários gravem registros no mesmo milésimo de segundo, o banco de dados irá analisar as transações e disparar essa Trigger para cada um deles em instantes distintos.

      Bom, há também uma forma de controlar essa concorrência pela aplicação. Porém, antes de explicá-la, vale fazer uma observação. Muitos desenvolvedores cometem o erro de gerar o novo valor da chave primária (código do cliente, por exemplo), durante a inserção do novo registro. Logo, se dois usuários iniciarem a inserção de dois registros ao mesmo tempo, o mesmo código será gerado, causando a violação de chave primária.

      A minha recomendação é atribuir o valor da chave primária antes da gravação do registro, ou seja, ao persistir os dados no banco (com o Post e ApplyUpdates). Para isso, consulte o último código da tabela e some mais 1, atribuindo-o imediatamente ao campo do DataSet. Caso dois usuários insiram dois registros simultaneamente, a possibilidade de duplicidade será bastante reduzida.

      Espero que essa explicação lhe ajude, amigo!
      Abraço!

  6. Andre,
    Fazer um executavel “X” com indy para enviar email,..inclusive com arq. anexo é fácil demais….

    Acontece que preciso fazer um servidor de email em delphi,….
    até aí tudo OK ! Usei o demo do indy ( SMTPServer)…e ele recebe na minha mesma maquina os dados
    que mandei o executável “X”…( from, to, subject..body)

    Problemas :
    – Como nesse demo eu obtenho os arquivos que foram anexados e como faço para enviar tudo para um email externo.. usando o meu excutável X e o demo ( server) ?

    1. Olá, Ricardo, tudo certo?

      Infelizmente ainda não tive a oportunidade de explorar o demo SMTPServer que acompanha o Indy, então não sou a melhor pessoa para lhe ajudar.
      A sua necessidade é criar um servidor de e-mail para funcionar em uma rede local?
      Muitos optam por subir um servidor de e-mail já pronto e utilizar as configurações de POP e SMTP no Delphi com o Indy. Em muitos dos casos, essa é a melhor opção.

      Abraço!

  7. Olá. Segui seu codigo a risca no Delphi XE7, porém na hora de enviar da erro.

    Error Connectin With SSL

    Já deixei as 2 dlls no diretorio do Exe e mesmo assim não funcionou. Sabe me dizer o que poderia estar acontecendo?

  8. Olá André,
    Ótimo post!
    Gostaria se possível saber de você se essa função funciona com @hotmail.com.
    Estou tento problemas com outra função que tenho, só consigo mandar para gmail.

    Obrigado

    1. Olá, Eduardo, tudo bem?
      Obrigado pelo feedback!
      Para enviar mensagens com uma conta do Hotmail, basta configurar o TIdSMTP da seguinte forma:

      IdSMTP.UseTLS := utUseExplicitTLS;
      IdSMTP.AuthType := satDefault;
      IdSMTP.Port := 587;
      IdSMTP.Host := 'smtp.live.com';
      IdSMTP.Username := 'usuario@hotmail.com';
      IdSMTP.Password := 'senha';

      E não esqueça também de mudar o endereço de remetente no componente TIdMessage:

      IdMessage.From.Address := 'usuario@hotmail.com';

      Espero ter ajudado, amigo!
      Abraço!

  9. Bom dia, Andre!
    Fiz na minha aplicação conforme o arquivo, porem ele envia o primeiro email se eu fechar a tela e abrir novamente e tentar enviar ele da a seguinte mensagem:
    Project sistema.exe raised exception class EIdOSSLCreatingContextError with message ‘Error creating SSL context’; – Estou usando delphi XE5 e a versao do indy é 10.6.0.504 o estranho que se eu fechar o sistema todo e abrir ele manda o primeiro email ja na segunda fez nao envia percebi tambem que só esta acontecendo com o gmail se eu tentar utilizar outro provedor da certo .

  10. Boa noite, fiz conforme o artigo porem na primeira fez ele envia o e-mail se eu fechar o form ( tela ) e abrir novamente para mandar o e-mail ele da a seguinte mensagem de erro:
    Erro na conexão ou autenticação: Error creating SSL context. estou utilizando o delphi XE5 com o indy na versao 10.6.0.504.

    1. Olá, Emerson!
      Obrigado pelo comentário! Aparentemente, a mensagem “Error creating SSL context” ocorre porque é preciso liberar a DLL após o envio da mensagem.
      Experimente o seguinte procedimento: declare a unit IdSSLOpenSSL na uses do formulário:

      uses
        IdSSLOpenSSL;

      Em seguida, após o envio do e-mail, inclua a seguinte instrução (recomendo colocá-la no Finally):

      UnLoadOpenSSLLibrary;

      Se o erro persistir, deixe novamente um comentário!

      Abraço!

  11. Ola André!
    Deu certo problema resolvido, era só liberar a DLL apos o envio, muito obrigado pela ajuda.

  12. Bom dia Andre, tudo bem?

    Olha só. Seu código é ótimo, obrigado por ter postado. Estou usando ele no Delphi Seattle e roda tranquilo.
    Montei até um form de configuração onde cadastro username, password, remetente entre outros. Gostaria de adicionar 2 configurações extras, mas não consegui.

    A ideia é colocar um checkbox para “Meu servidor requer autenticação” e outro checkbox para “Conexão SSL”

    Poderia me ajudar?

    1. Olá, Renan, tudo certo?
      Bom, vamos lá! Para codificar a opção de autenticação no servidor, controle a propriedade AuthType:

      if CheckBox1.Checked then
        IdSMTP.AuthType := satDefault
      else
        IdSMTP.AuthType := satNone;

      A respeito da conexão SSL, Renan, eu ainda não testei, mas acredito que, se o objeto TIdSSLIOHandlerSocketOpenSSL não for vinculado ao TIdSMTP, a conexão SSL é ignorada. Portanto, provavelmente ficaria dessa forma:

      if CheckBox2.Checked then // usa conexão SSL
        IdSMTP.IOHandler := IdSSLIOHandlerSocket;

      Abraço!

  13. Obrigado pelo retorno Andre. Na segunda-feira vou por em pratica.

    Sobre o SSL via checkbox acho que preciso ignorar essas 3 linhas, pois foi assim que consegui rodar o código.

    // Configuração do protocolo SSL (TIdSSLIOHandlerSocketOpenSSL)
    IdSSLIOHandlerSocket.SSLOptions.Method := sslvSSLv23;
    IdSSLIOHandlerSocket.SSLOptions.Mode := sslmClient;
    
    // Configuração do servidor SMTP (TIdSMTP)
    IdSMTP.UseTLS := utUseImplicitTLS;

    O problema é que não estou encontrando uma forma adequada de configurar, mas assim que conseguir volto aqui pra comentar.

  14. Bom dia André. Testes realizados e tudo funcionando. Modifiquei um pouco a ordem para que rodasse e ficou assim:

    if frmdm.qrServer_EmailSERV_REQ_AUT.AsString = 'S' then
       IdSMTP.AuthType := satDefault
    else
       IdSMTP.AuthType := satNone;
    
    //Configuração do protocolo SSL (TIdSSLIOHandlerSocketOpenSSL)
    if frmdm.qrServer_EmailSERV_REQ_SSL.AsString = 'S' then
      begin
       IdSSLIOHandlerSocket.SSLOptions.Method := sslvSSLv23;
       IdSSLIOHandlerSocket.SSLOptions.Mode := sslmClient;
       IdSMTP.IOHandler := IdSSLIOHandlerSocket;
       IdSMTP.UseTLS := utUseImplicitTLS;
      end
      else
       IdSMTP.IOHandler := nil;
    1. Legal, Renan!
      Obrigado pela contribuição e também por dedicar o seu tempo para retornar e publicar o comentário!
      Certamente irá ajudar outros leitores.
      Grande abraço!

  15. Amigo parabéns pelo código e a forma como você explica, uma pequena observação depois que fui testá lo, vi que estava dando um pequeno erro quando finalizava, debuguei e vi que o objeto IdSMTP não estava sendo destruído porque teria de desconectar antes do FINALLY colocando a instrução ( IdSMTP.Disconnect(); ) antes, ai funcionou beleza. Nome do erro que apresentava “Access de Violation # read 0x00000000” , obrigado e valeu pelo seu excelente trabalho.

    1. Olá, Bifanio, tudo certo?
      Opa, muito obrigado pela dica! Vou editar o artigo e colocar essa instrução, conforme você indicou, para que outros leitores não tenham o mesmo problema.
      Grande abraço!

  16. Boa noite André!

    Excelente código e melhor ainda a didática.

    Meu provedor é o Terra, e estou conseguindo mandar e-mails para os usuarios@terra.com.br, mas quando tento mandar para os @gmail e @hotmail e até os @cliente.com.br, o e-mail não vai. Aparece a mensagem de ‘enviado’ mas não chega lá.

    Eu vi lá em cima as orientações para o provedor Terra, mas por mais que eu tente, só consigo mandar para o próprio Terra.

    Será que estou fazendo algo errado?

    Muito obrigado.

    1. Boa noite, Marco, tudo certo?

      Você deu uma olhada na caixa de spams ou lixo eletrônico dos destinatários @gmail e @hotmail?
      Dependendo do conteúdo da mensagem, estes servidores a encaminham para essas pastas.

      Abraço!

    2. Oi André, obrigado por responder.

      Eu olhei lá, os destinatários gmail e hotmail, são minha próprias caixas postais e não tem spams, mas o mais importante são os @cliente.com.br.

      Ontem, depois de eu ter desistido eu lembrei de um outro programa de envio de e-mails que eu tinha desenvolvido lá em casa usando Delphi 7, e mandei e-mails para meus hotmail e gmail e chegaram bem, inclusive com os anexos.

      Eu estou usando agora o XE7, e tentei o seguinte: Abri o programa com problema de envio, e dentro dele, no ambiente de desenvolvimento, abri a UEmail.Pas do outro em Delphi 7, copiei o idSMTP e colei no XE7, já com as configurações de lá, onde estava funcionando. Só que deu a mesma coisa, mandou para o Terra e não mandou para os hotmail/gmail.

      Agradeço a atenção.

  17. Funcionou!!! O erro era o seguinte:

    Meu provedor sempre foi o Terra, e o e-mail: usuario@terra.com.br. Neste caso o Username: usuario

    Só que ao cadastrar o domínio (hospedado no Terra), o email passou a ser:

    usuario@dominio.com.br e o Username mudou para: usuario@dominio.com.br mas eu estava usando o username antigo, e como eu testava mandando e-mail para mim, achava que estava tudo ok. Mas quando comecei a mandar e-mails para os clientes, descobri que tinha algo errado.

    Acho que este Delphi XE poderia dar mais mensagens de erro.

    Obrigado por tudo, e desculpe-me pelo transtorno!!

    Obs: te enviei um e-mail pelo sistema funcionando.

    1. Boa noite, Marco!
      Recebi o e-mail. Está funcionando mesmo!
      Muito obrigado por dedicar um tempo para retornar ao blog e postar a solução! Talvez poderá ajudar outros usuários do Terra! 🙂

      Grande abraço!

  18. Eu que agradeço André.
    Lá em cima você deu uma boa ideia de colocar um gif animado ou uma Thread, enquanto algum processamento demorado está em execução.
    Muita gente, como eu, está com este problema do gif congelar durante o processamento, e parece que para escrever Threads, tem que ter um pequeno curso Doutorado em Ciência da Computação.

    1. Olá, Marco!
      Opa, curso de Doutorado e Mestre! kkkkkkk
      Brincadeira. A princípio, a utilização de Threads pode parecer um pouco complexa, mas acaba se tornando descomplicada.
      Clique neste link e baixe um exemplo de Threads aqui do blog. Talvez poderá servir como uma orientação inicial. 🙂

      Abraço!

  19. Hola Andrè,
    Gracias a gente como tu, publicando ejemplos y conocimientos, muchas veces solucionamos nuestros problemas. Me ha servido perfectamente.
    Muito obrigado.

    1. Hola, Juan, ¿cómo estás?

      Gracias por el comentario!
      Me alegra saber que el artículo te ha ayudado!
      Mi objetivo es sólo eso: compartir el conocimiento! 🙂
      Abrazo!

  20. Olá Andre tudo bom? bom obrigado por posta o código! estou fazendo um envio smtp em massa! para marketing,
    e gostaria de sabe como configura seu código para usar servido smtp próprio como smtp.empresa.com

    1. Olá, Júnior, tudo bem?
      Toda a configuração de SMTP é feita nas seguintes linhas:

      IdSMTP.AuthenticationType := atLogin;
      IdSMTP.Port := 587;
      IdSMTP.Host := 'smtp.terra.com';
      IdSMTP.Username := 'usuario@empresa.com';
      IdSMTP.Password := 'senha';

      Basta substituir os valores, preenchendo-os com a configuração do seu servidor.
      Abraço!

  21. Olá Bom Dia.

    Estava usando esta rotina de envio e até então não estava tendo problemas com ela utilizando um E-mail de domínio próprio(hospedagem hostgator) e pelo Gmail.

    Porém fui utilizar de um Domínio hospedado no UOL no qual requer autenticação e não importa o que eu coloque nas configurações a mensagem que retorna é

    ‘SSL23_GET_SERVER_HELLO:unknown protocol’

    Teria ideia do que pode estar ocorrendo ?
    Obrigado pela atenção.

    Meu Código

    //Configuração do SSL
    IdSSLIOHandlerSocket.SSLOptions.Method := TIdSSLVersion(1);     //sslvSSLv23;
    IdSSLIOHandlerSocket.SSLOptions.Mode   := TIdSSLMode(1); //sslmClient;
    
    // Configuração do SMTP
    IdSMTP.IOHandler      :=  IdSSLIOHandlerSocket;
    //IdSMTP.AuthType     := satNone;
    //IdSMTP.AuthType     := satSASL;
    //IdSMTP.AuthType     := satDefault;
    IdSMTP.UseTLS           :=  utUseImplicitTLS;
    
    IdSMTP.Port         := StrToInt(EditPortaSMTP.Text);    //Porta
    IdSMTP.Host         := EditServidorSMTP.Text; //servidor smtp
    IdSMTP.Username     := EditUsuario.Text;      //usuario
    IdSMTP.Password     := EditSenha.Text;        //senha
    
    // Tentativa de conexão e autenticação
    try
      IdSMTP.Connect;
      IdSMTP.Authenticate;
    except
      on e:exception do begin
         MessageDlg('Erro na conexão e/ou autenticação: ' +   E.Message, mtWarning, [mbOK], 0);
      end;
    end;
    1. Bom Dia A todos… Referente ao meu problema o André entrou em contato comigo por E-mail e conseguiu sanar o problema.
      Segue abaixo a solução para quem passar pela mesma situação.

      Para os E-mails que utilizam a porta 465
      eu estava utilizando o código da seguinte maneira.

      IdSSLIOHandlerSocket.SSLOptions.Method := sslvSSLv23;
      IdSSLIOHandlerSocket.SSLOptions.Mode := sslmClient;
      IdSMTP.IOHandler := IdSSLIOHandlerSocket;
      IdSMTP.UseTLS := utUseImplicitTLS;
      
      IdSMTP.AuthType := satDefault;
      IdSMTP.Port := 465;
      IdSMTP.Host := 'smtp.dominio.com.br';
      IdSMTP.Username := 'email@dominio.com.br';
      IdSMTP.Password := '12345';

      Código que funcionava perfeitamente, a partir do momento que precisei utilizar a porta 587 a figura mudou e ai que estava o problema, eu fazia as mudanças nos parâmetros e mesmo assim não dava certo pois a solução estava em remove-los, ficando então apenas o código abaixo.

      IdSMTP.AuthType := satDefault;
      IdSMTP.Port := 587;
      IdSMTP.Host := 'smtp.dominio.com.br';
      IdSMTP.Username := 'email@dominio.com.br';
      IdSMTP.Password := '12345';

      Muito Obrigado André pela pronta ajuda, fantástico ver a atenção que da aos usuários do blog sem exigir nada em troca.

      Sucesso pra você.

    2. Que bom que funcionou, Denis!
      Muito obrigado por dedicar um tempo para retornar ao blog e publicar a solução!
      Com certeza poderá ajudar outros desenvolvedores.

      Grande abraço!

  22. Boa noite andré, parabens pela iniciativa e ótima explicação. Não estou conseguindo mostrar alguma mensagem pro cliente de espera, para que ele não tenha a sensação de programa travado. Baixei seu exemplo, mas sinceramente peço desculpas, mas não entendi como aplicá-lo.
    Agradeço a paciencia
    forte abraço

    1. Olá, Rodrigo, tudo bem?
      A implementação de uma tela de espera não consta neste artigo, já que fugiria um pouco do tema.
      Mesmo assim, vou tentar elaborar um exemplo para te apresentar, ok?

      Obrigado! Abraço!

  23. Bom dia André, estou usando o Delphi xe2 para criar esse soft, e estou com um problema na visualização do meu Html enviado, ou invés de de mostrar a mensagem montada, ele mostra o Código Html, tenho no meu sistema uma classe para criar meus Html, mais não consigo visualizar como era pra ser, se alguém poder me ajudar agradeço muito a todos.

    1. Olá, João Rufino, tudo bem?
      Para que o conteúdo HTML seja reconhecido na mensagem, é necessário adicionar a seguinte instrução:

      IdText.ContentType := 'text/html; charset=iso-8859-1';

      Abraço!

  24. Obrigado Andre, tudo certo agora, na verdade já tinha esta linha no meu código só com uma diferença, o meu estava assim:

    IdText.ContentType := 'text/plain; charset=iso-8859-1';

    O seu está assim:

    IdText.ContentType := 'text/html; charset=iso-8859-1';

    Agradeço a todos.

  25. Bom dia, André.

    Muito massa seu post sobre o envio de email, simples e direto. Gostaria que você me ajudasse se possível, tentei exatamente como o exemplo no post (usando gmail, com usuário e senha válido) apresenta: Connection Closed Gracefully, se mudo para porta 587 que requer o protocolo TLS, apresenta erro na versão SSL mesmo testado com todas as versões que o componente dispõe.
    Obrigado.

    1. Olá, Jorge, tudo bem?
      Em primeiro lugar, obrigado pelo comentário no blog!
      Acredito que esse erro esteja relacionado com segurança. A princípio, eu diria para você desabilitar o Firewall/Antivirus e testar novamente.
      Há também uma opção do Gmail chamada “Less secure apps” que, em alguns casos, deve ser habilitada para que o envio funcione, mas, atenção: use essa opção conscientemente.

      Abraço!

  26. Boa Tarde..

    Não estou conseguindo enviar email pelo hotmail. Retorna sempre o erro 140770FC:SSL Routines: ssl23_GET_SERVER_HELLO: Unknown Protocol.

    Estou definindo a seguinte configuração:

      if pos('.live.com', FHost) > 0 then
      Begin
        fIdSSLIOHandlerSocket.SSLOptions.Method    := sslvSSLv23;
        fIdSSLIOHandlerSocket.SSLOptions.Mode      := sslmClient;
        FIdSMTP.IOHandler := fIdSSLIOHandlerSocket;
    
        FIdSMTP.UseTLS    := utUseImplicitTLS;
        FIdSMTP.AuthType  := satDefault;
        FHostPorta        := 587;
      End;
    

    Estou utilizando Delphi Seattle..

    Se possivel, envie um codigo funcional para que eu possa compara-lo.
    Grato

    1. Olá, Daniel!
      Esse erro refere-se ao protocolo SSL. Provavelmente a configuração está incorreta nas seguintes linhas:

      fIdSSLIOHandlerSocket.SSLOptions.Method    := sslvSSLv23;
      fIdSSLIOHandlerSocket.SSLOptions.Mode      := sslmClient;

      Infelizmente não tenho conhecimento da configuração válida do domínio live.com, mas, mesmo assim, experimente trocar o valor da propriedade “Method”.
      Em um dos comentários, um desenvolvedor chamado Denis teve o mesmo problema e conseguiu solucionar removendo as linhas do SSL, mas era um servidor diferente do live. Acho que não será a mesma solução.

      Abraço!

  27. Olá Boa Tarde.

    Segue abaixo a forma funcional para configurar envio a partir de conta Hotmail.

    SSLHandler.MaxLineAction := maException;
    SSLHandler.SSLOptions.Method := sslvTLSv1;
    SSLHandler.SSLOptions.Mode := sslmUnassigned;
    
    SMTP.IOHandler := SSLHandler;
    SMTP.Host := 'smtp.live.com';
    SMTP.Port := 587;
    SMTP.Username := 'seu_email@hotmail.com';
    SMTP.Password := 'sua_senha';
    SMTP.UseTLS := utUseExplicitTLS;

    Ah, um detalhe: para utilizar o maException, deve-se declarar a unit IdGlobal.

  28. André, muito obrigado por pelo tutorial. Fiz o teste com Delphi XE3 e funcionou muito bem, mas tive que alterar a propriedade do gmail (conta que envia) Less secure apps. Não há outra alternativa, não gostaria de sugerir ao cliente que deixe sua conta de email vulnerável.
    Mas que funciona bem funciona. muito obrigado

    1. Olá, Rogério, tudo certo?
      Infelizmente a opção “Less secure apps” deve ser ajustada na conta do Gmail para que o código funcione. Trata-se de uma medida de segurança imposta pelo servidor já há algum tempo para evitar que aplicativos de terceiros façam operações sem autorização do usuário.
      Caso o cliente apresente objeções com a alteração dessa propriedade, uma alternativa é utilizar outro servidor de e-mail, como Yahoo, Hotmail, etc.

      Obrigado pelo comentário! Abraço!

  29. Boa tarde André, usando como base a sua rotina de email, desenvolvi a minha. Consegui enviar email para os provedores gmail, terra, yahoo, email proprio da empresa e todos sairam a imagem no corpo do email. Porém não estou conseguindo receber a imagem no corpo do email nos provedores do outlook e hotmail. Será que tem alguma configuração a mais para inserir para funcionar nesses provedores?

    Abraço

    1. Olá, Marcos, tudo bem?
      Como funciona nos outros provedores, acredito que seja uma restrição de segurança do Hotmail/Outlook. Envie a parte do código da imagem para “contato@andrecelestino.com”. Vou dar uma olhada!

      Abraço!

  30. Bom dia André, montei a seguinte função de envio de email com imagem no corpo do email. Espero que ajude.

    procedure TEmail.EnviarEmail(Msg: string;Anexo:String); 
    var 
      AuthSSL : TIdSSLIOHandlerSocketOpenSSL; 
    begin 
      IdMessage.Recipients.EMailAddresses := FEmailReceber; 
      IdMessage.Subject := FAssunto; 
      IdMessage.From.Address := FEmailEnviou; 
      IdMessage.From.Name := FNomeRemetente; 
      IdMessage.Priority := mpHighest; 
      IdMessage.ContentType := 'multipart/mixed'; 
      IdMessage.Encoding := meMIME; 
    
      with TIdText.Create(IdMessage.MessageParts) do 
      begin 
        ContentType := 'text/html; charset=iso-8859-1'; 
        Body.Add(''); 
    
        if Msg  '' then 
          Body.Add(Msg);
    
        Body.Add('<img style="margin:1px 1px 1px 0px;"'); 
        Body.Add(''); 
        Body.Add(''); 
        ContentDisposition := 'inline'; 
    
        SMTP.Host := FHost; 
        SMTP.Username := FUsername; 
        SMTP.Password := FPassword; 
    
        if FAutentica then 
        begin 
          AuthSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil); 
          SMTP.IOHandler := AuthSSL; 
          SMTP.UseTLS := utUseExplicitTLS; 
          AuthSSL.DefaultPort := FPorta; 
          AuthSSL.SSLOptions.Method := sslvSSLv3; 
          AuthSSL.SSLOptions.Mode := sslmClient; 
          SMTP.AuthType := satDefault; 
        end; 
    
        SMTP.Port := FPorta; 
        if not(SMTP.Connected) then 
          SMTP.Connect; 
    
        SMTP.Send(IdMessage); 
        SMTP.Disconnect; 
        IdMessage.MessageParts.Clear; 
      end;
    end
    1. Olá, Marcos! Muito obrigado pela colaboração.
      Embora eu tenho identificado alguns pontos de inconsistência no código, parece ser funcional.
      Com certeza irá ajudar outros leitores!

      Abraço!

  31. Olá,

    Gostaria de alguma dica se alguém puder me ajudar, possuo uma pequena aplicação em delphi 2010, então estou tentando migrar ela para delphi seattle 10, nessa aplicação tenho 2 formulários para envio de email com o indy, porém na hora de migrar não consigo compilar como se os componentes do indy não estivessem mais instalados, verifiquei esta tudo ok, olho visualmente todos estão, exclui-os e coloquei novamente e o erro persiste. Não sei mais como resolver.

    Msg de erro:
    [dcc32 Fatal Error] EmailC.pas(9): F2063 Could not compile used unit ‘IdMessageClient.pas’

    O problema não da só com o IdMessageClient acontece com todos os uses que o delphi coloca automaticamente quando uso o indy que são esses ( IdMessageClient, IdSMTPBase, IdSMTP, IdBaseComponent, IdMessage, IdComponent, IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase)

    Será que tem alguma dica ?
    Se abro a aplicação no delphi 2010 funciona corretamente. Muito estranho.

    Obrigado

    abraço

    1. Olá, Martins!
      Infelizmente ainda não tive a oportunidade de trabalhar com o Delphi Seattle. Elaborei o exemplo do artigo apenas utilizando a família XE do Delphi.
      Pela descrição do erro, talvez a versão Seattle tenha uma estrutura diferente dos componentes Indy.
      Só uma dúvida, Martins. Antes do “Fatal Error”, tem mais alguma linha na saída do compilador? Normalmente a linha anterior informa qual é o problema.

      Abraço!

  32. Olá, André.
    Então, não tem erro nenhum, só esse é como se o componente não estivesse instalado, sabe? como a biblioteca estivesse indisponível. muito estranho, não é erro de sintaxe de alteração de funcionalidade.
    Por isso estou pedindo opiniões.

    obrigado
    abraço

  33. Fiz o programa para emviar e-mail com anexo. Meu problema é que quando abro o OpenDialog para encontar o arquivo desejado, tudo certo. Consigo enviar o e-mail. Acontece que depois de enviar, o programa no geral, abre fotos, txt, etc… e o programa não volta para a pasta de instalação do executável onde estão as fotos, etc… Como faria para depois de enviar o arquivo, via e-mail, o programa voltar ao diretório inicial.
    Se poder me ajudar, agradeço bastante.
    Forte abraço

    1. Olá, Maurício, tudo bem?
      O OpenDialog possui uma propriedade chamada InitialDir, que controla o diretório inicial que será exibido ao executá-lo.
      Portanto, basta utilizá-lo para voltar para a pasta que você deseja, por exemplo:

      OpenDialog.InitialDir := 'C:\Aplicativo';

      Abraço!

  34. olá André, tentei implementar o envio do e-mail HTML com anexo em pdf porem não obtive sucesso, poderia me ajudar:
    Quando insiro o codigo do anexo ele deixa o html todo bagunçado

    procedure TForm1.Send_Mail(Revenda, Contato, Tabela, email, coemail, Tvalor, TextHtml, DocAnexo : string);
      var i : Integer;
    begin
      with dmPrincipal do
      begin
        { Envio do e-mail }
    
        //Detinatário do e-mail.
        IdMessage.Recipients.EMailAddresses := para; //info dinamica
    
        //Destinatário em cópia.
        //IdMessage.CCList.EMailAddresses := MailCnt;
    
        //Assunto do e-mail.
        IdMessage.Subject := 'Teste Projeto Conscientização';  //info dinamica
    
        //Informa ao IdMessage que o Conteúdo do e-mail é HTML.
        IdMessage.ContentType := 'text/html';
    
        //Carrega HTML com o Corpo do E-mail.
        IdMessage.Body.LoadFromFile(TextHtml);
    
         //Substitui o Valor dos Campos.
        IdMessage.Body.Text := StringReplace(IdMessage.Body.Text, '{:Revenda:}', Revenda, [rfIgnoreCase, rfReplaceAll]);
        IdMessage.Body.Text := StringReplace(IdMessage.Body.Text, '{:Contato:}', Contato, [rfIgnoreCase, rfReplaceAll]);
    
        IdMessage.Body.Text := StringReplace(IdMessage.Body.Text, '{:Tabela:}', Tabela, [rfIgnoreCase, rfReplaceAll]);
        IdMessage.Body.Text := StringReplace(IdMessage.Body.Text, '{:Vtotal:}', Tvalor, [rfIgnoreCase, rfReplaceAll]);
        IdMessage.Body.Text := StringReplace(IdMessage.Body.Text, '{:ContatoCNT:}', Contato, [rfIgnoreCase, rfReplaceAll]);
        IdMessage.Body.Text := StringReplace(IdMessage.Body.Text, '{:RamalCNT:}', ramal, [rfIgnoreCase, rfReplaceAll]);
        IdMessage.Body.Text := StringReplace(IdMessage.Body.Text, '{:MailCNT:}', email, [rfIgnoreCase, rfReplaceAll]);
    
        if DocAnexo  '' then
        begin
          TIdAttachmentFile.Create(IdMessage.MessageParts, DocAnexo);
        end;
    
        //Configurações do SMTP.
        IdSMTP.UseEhlo := True;
        IdSMTP.Username := UserName;
        IdSMTP.Password := Password;
        IdSMTP.Port := 25;
        IdSMTP.Host := Host;
    
         IdSMTP.Connect;
        try
          IdSMTP.Send(IdMessage);
        finally
          IdMessage.Body.Clear;
          IdMessage.MessageParts.Clear;
          IdSMTP.Disconnect;
        end;
      end;
    end;
    1. Olá, Douglas, tudo bem?
      Vou entrar em contato com você por e-mail. Lembro-me de ter resolvido este problema para outro leitor, mas não recordo da solução.
      Abraço!

    2. Qual foi a solução para o problema?
      Estou passando pela mesma situação

  35. André, tentei enviar emails com o SMTP do Gmail que você postou, mas sempre gera uma mensagem de erro. No SMTP do Yahoo funciona bem.

    Você pode dizer onde está a falha no código para o Gmail?

  36. Boa tarde Andre, estou com exemplo aqui que eu consigo enviar para Gmail, Bol, Hotmail, mais para o yahoo não estou conseguindo, da um erro de “connect timed out” já vi alguns exemplo falando que deram certo, mais tive analisando que o SMTP: smpt.mail.yahoo.com.br terminando com o “.br” que esta dando certo, mais agora para os novos email yahoo não tem mais “.br” exemplo@yahoo.com. Alguem tem alguma dicas desse de já agradeço em nome de todos que estam na mesma que eu.

  37. Boa tarde voltei para disponibilizar minha solução Para o envio do Yahoo ficou assim
    SMTP: smtp.mail.yahoo.com
    USUARIO: exemploassim@yahoo.com.br (com “br” no final do email)

    IdSMTP1.UseTLS := utUseExplicitTLS;
    port := 587;
    IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1;
    IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmClient;

    E isso espero ajudar. André muito Obrigado e ate a próxima.

  38. André, parabéns pelo post.
    Me ajudou a implementar o envio de e-mail na aplicação do meu cliente.

    Já adicionei seu site nos favoritos pois já vi que vou encontrar muita coisa interessante aqui.
    Obrigado.

  39. Boa Tarde André,
    Parabéns pelos post, muito bom e esclarecedor, que voce continue nessa bela trajetória que DEUS te honrou.
    Bom eu fiz funcionar no Embarcadero® RAD Studio 10 Seattle.

    Passos que eu fiz para funcionamento pelo GMAIL:

    1 – Habilitar na sua conta do GMAIL, as opções de usar IMAP e POP
    https://support.google.com/mail/troubleshooter/1668960?hl=pt-BR

    2 – baixar as DLL’s que você informou no diretório da sua aplicação.
    http://www.andrecelestino.com/wp-content/files/DLLs-SSL-DelphiXE.rar

    3 – Usei seu código e inclui a chamada do método “LoadOpenSSLLibrary”

    Dai foi só alegria 🙂

    1. Boa noite, Renato!
      Opa, agradeço pelo elogio! 🙂

      Muito obrigado pela colaboração, Renato.
      Em qual linha você incluiu a chamada do “LoadOpenSSLLibrary”? Achei essa informação importante!

      Abraço!

    2. Bom dia,

      Primeira linha do método, logo após o primeiro begin.

      Esqueci de mencionar, eu troquei o protocolo SSL, de “sslvSSLv23” para “sslvSSLv3”

      abrcs

  40. Boa noite André, estou tentando implementar mas está dando o seguinte erro:

    Erro na conexão ou autenticação: Error connectiong witj SSL.
    error:140770fc:ssl
    routines:SSL23_GET_SERVER_HELLO:inknown protocol

  41. André, bom dia, até que enfim achei um cara que conhece, bela orientação, André.
    Tenho o Delphi 2010 e o Indy não aceita no Uses, poderia me orientar como resolvê-lo.
    Obs. O Indy está marcado lá na pasta de packages.

  42. André, bom dia, resolvido o item anterior, obrigado.
    Tem uma dúvida, pode ajudar? como converter o conteúdo do Messageparts. por exemplo: lMsg.MessageParts.Items[j] em string ou texto para manipular ou armazenar?

  43. André tudo bem?

    Muito bom seu artigo.
    Mas como eu faria para enviar o PDF no corpo da mensagem poderia me ajudar?

    1. Boa tarde, Ricardo!
      Para anexar um arquivo, você pode utilizar o TIdAttachmentFile. Por exemplo:

      TIdAttachmentFile.Create(IdMessage.MessageParts, 'C:\Arquivo.pdf');

      Abraço!

  44. Boa tarde
    parabéns pela matéria muito bom.

    Estou tentando usar o Envio de Email com Thread mais a tela continua congelado quanto amando o Email, seria possível vc dar uma explanação sobre este assunto?
    Se o demo do Thread que tem aqui no site mais não esta funcionando.

  45. Boa noite André!

    Ótimo artigo, mas estou muito confuso com a thread. Baixei o exemplo seu, mas não consegui encaixar no meu código… Na verdade não sei o que jogo na thread, se é a função de enviar e-mail ou atualizar a progressbar…

    Poderia me ajudar?

    1. Olá, Gabriel!
      A rotina de envio de e-mail que deve ficar na Thread. Basta mover todo o código apresentando nesse artigo para o método “Execute” da Thread. Na aplicação cliente, instancie a Thread e chame o método Resume (ou Start, nas versões mais recentes do Delphi).

      Abraço!

  46. André, boa noite.
    Primeiramente obrigado pela resposta. Mas no caso estou utilizando um dataset pra pegar os endereços de email do database, ao mover o código pra thread eu não consigo localizar o dataset contido no outro form (já coloquei ele em uses). Alguma sugestão?

    Abraço.

    1. Olá, Gabriel.
      Neste caso, você pode criar uma property do tipo TStringList na classe da Thread para receber os endereços de e-mail da tela. Por exemplo:

      TMinhaThread = class(TThread)
      private
        FEmails: TStringList;
        ...
      public
        ...
        property Emails: TStringList read FEmails write FEmails;
      end;

      A chamada da Thread seria da seguinte forma:

      Thread := TMinhaThread.Create(True);
      ...
      Thread.Emails := {TStringList coms os e-mails do DataSet}

      Uma vez que os e-mails estiverem na classe da Thread, basta adicioná-los na propriedade Recipients do componente TIdMessage.

  47. Olá eu consegui usando o gmail mas, no outlook da este erro

    Erro na conexão ou atenticação: Error connecting
    with SSL.
    erro:140770FC:SSL
    routinesSSL23_GET_SERVER-HELLO:unknown protocol

    veja meu codigo:

    if comboxMail.Text = 'outlook' then
      begin
        IdSMTP.Port := 587 ;
        IdSMTP.Host := 'smtp-mail.outlook.com';
      end else
      begin
        IdSMTP.Port := 465; 
        IdSMTP.Host := 'smtp.gmail.com'; 
      end;
  48. André, Bom Dia.
    Acredito que você esteja bastante familiarizado com esses componentes, por isso da minha pergunta.
    Desenvolvi uma rotina de envio de e-mail, para que possa encaminhar documentos que possuo digitalizados salvos em meu banco de dados SQL Server. Até ai tudo bem, o programa conecta, envia, sem problema algum, entretanto sinto que seria importante deixar o usuário consciente do progresso do envio, por tratarem-se de documentos os arquivos anexados geram grandes mensagens, com 5, 6 ou até mais MB e consequentemente demoram para serem enviados, conhece alguma propriedade ou método que retorne o progresso do envio?? que pudesse ser lido recorrentemente e apresentado ao usuário?

    Grato desde já.

    1. Olá, Eudardo, como vai?
      Em primeiro lugar, obrigado pelo comentário no blog. É uma ótima pergunta!
      O componente TIdSMTP traz um evento chamado OnWork que nos permite trabalhar com os dados que são processados durante o envio do e-mail através do parâmetro AWorkCount. Não tive tempo de testar, mas encontrei um trecho de código de um membro do ActiveDelphi que fez a seguinte codificação neste evento utilizando uma TProgressBar:

      ProgressBar1.Position := Trunc((AWorkCount / ProgressBar1.Max) * 100); 
      Application.ProcessMessages;

      Espero que lhe ajude! Abraço!

  49. Andre,
    Bom Dia.

    Realmente verifiquei esse evento e ele também possui um evento OnWorkBegin que teoricamente deveria me trazer o valor máximo, que seria o tamanho da mensagem, o tal do AWorkCountMax, entretanto o AWorkCountMax vem sempre zerado no TIdSMTP, assim fiz uso de um “expediente técnico” disponibilizado por alguém, não lembro onde, para resolver esse problema do valor dado ao ProgressBar1.Max que segue:

    try
      FILE_Stream := TMemoryStream.Create;
      Mensagem.SaveToStream(FILE_Stream);
      BarraProgressoEnvio.MaxValue := FILE_Stream.Size;
    finally
      FreeAndNil(FILE_Stream);
    end;

    Pelo que entendi ele sava a mensagem propriamente dita em um stream e verifica o tamanho desse stream, pois não é suficiente verificar o tamanho dos anexos, pois difere substancialmente do tamanho da mensagem.

    e no evento OnWork coloquei:

    begin
      lblProgressoEnvio.Caption:='Progresso do Envio ('+IntToStr(Round((AWorkCount/1024)))+'/'+IntToStr(Round((BarraProgressoEnvio.MaxValue/1024)))+' KB)';
      BarraProgressoEnvio.Progress:=AWorkCount;
      Application.ProcessMessages;
    end;

    Assim tenho dois Gauges na tela de envio, uma que traz o progresso: conectando, autenticando, enviando, concluido e outro específico para a hora que chega no enviando, que mostra o progresso do envio propriamente dito.

    Espero ter colaborado.

    Grande abraço.

    1. Perfeito, Eduardo!
      Muito obrigado por ter dedicado um tempo para voltar ao blog e contribuir com este código! 🙂
      Achei bem interessante a ideia de “medir” o tamanho da mensagem por meio de uma TMemoryStream para configurar o MaxValue da barra de progresso.

      Obrigado!

  50. Ola Andre, disculpa meu portugues, e parabem pelo site.
    Seguinte, estou trabalhando com um servidor da hostinger, usei o codigo do Denis para o porto 587 mas esta mandando erro “EIdSMTPReplyError with message ‘Must issue a STARTTLS command first'” ai me lasquei, sou novo no asunto email.
    Abraço a todos.

    1. Olá, Daniel, tudo bem?
      Obrigado pela visita e pelo comentário!
      O erro aparentemente parece estar relacionado com a porta. Você já tentou utilizar a porta 465?
      Se mesmo assim não funcionar, peço que envie o código que você está utilizando para “contato@andrecelestino.com”.

      Abraço!

  51. Obrigado André, mas parece que o problema era com o servidor mesmo, hoje funciona bem. Valeu pela ajuda. So para esclarecer, usei o seu codigo mas troquei a parte que o Denis mandou na mensagem dele.
    Saludos desde Argentina

  52. Boa noite.
    Não consegui enviar o e-mail, aparece a mensagem “Erro na conexão ou autenticação: Socket Error #10060.
    Connection timed out.
    Firewall está desativado, não tenho anti-vírus instalado e estou enviado do gmail.

    1. Qual a solução encontrada nesse caso? Estou com o mesmo problema.

  53. Bom dia… Estou com problemas de conexão e autenticação e também na parte de instância do TIdText e TIdAttachmentFile e por conta disso eu apaguei a parte de TIdAttachmentFile pois realmente não vou precisar e na TIdText eu substitui por IdMessage1…
    Na parte da conexão e autenticação esta dando um erro…
    Erro na conexão ou autenticação: Erro connecting with SSL.
    error:140770FC:SSL
    routines:SSL23_GET_SERVER_HELLO:unknown protocol
    e não sei como posso resolver, já pesquisei bastante mas não achei algo explicável..

    Se possível me ajudar, agradeço de coração.

    1. Olá, Vinícius, tudo bem?
      Não sei se você está utilizando o Gmail, mas este erro parece estar relacionado com a porta de conexão ou modo de autenticação através do SSL.
      Em primeiro momento, sugiro alterar entre as portas 25, 465 e 587. Se ainda não funcionar, experimente trocar as propriedades referente ao SSL:

      fIdSSLIOHandlerSocket.SSLOptions.Method := {trocar valor};
      fIdSSLIOHandlerSocket.SSLOptions.Mode := {trocar valor};

      Os valores acima podem ser obtidos com o suporte do webmail que você está utilizando.

      Abraço!

  54. Gostaria de agradecer.
    Após 5 horas de frustração pesquisando em sites estrangeiros (parei até em um da Indonésia), me deparei com seu site de maneira explicativa de simples.
    Parabéns pela inciativa

  55. Salam!
    Je ne peut pas envoyer l’e-mail, le message “Erreur dans la connexion ou l’ authentification: Socket Error # 10060.
    Connection timed out.
    je ne comprends pas ce qui ne vas pas ! est ce que vous pouvez m’aidé svp? (j’utilise un compte gmail)

  56. Salam!
    Merci beaucoup Monsieur André finalement ça marche !
    sans votre aide je serai perdu … 1000 merci!
    j’ai suivi vos instructions 🙂
    bravo pour le site et pour la rapidité de réponse et surtout les compétences que vous avez !
    continu comme ça on a encore besoin de vous, puis je m’excuse pour le français je ne maîtrise pas l’espagnole
    muchas gracias ! 🙂

    1. Salut, Beddiar!
      Bon! Heureux de savoir que je pourrais vous aider!
      Pas besoin de présenter des excuses! communauté Delphi est l’un dans le monde! 🙂

      Je vous remercie!

  57. Olá André, sempre que posso dou uma passadinha aqui no seu site pra aprender um pouco mais.

    A sua dica de como enviar e-mail é excelente, aliás, me foi muito útil, obrigado, no entanto, não encontro na internet, nenhuma dica de como receber os e-mail na mesma aplicação….

    Tem como você nos mostrar como faz?

    Obrigado e sem mais.

    Atenciosamente.
    Adriano.

  58. Wow…
    Excelente, vou testar em minha aplicação e retorno para tirar dúvidas sobre possíveis melhorias no códigos…rs.

    Obrigado André.

    1. Haaaa, outra coisa que eu já ia me esquecendo. Estou precisando de uma forcinha com Socket, para enviar e receber arquivos …

      Se não for muito abuso, evidentemente…

      Obrigado mais uma vez.
      Adriano.

  59. Olá, primeiramente obrigado pelo artigo que me ajudou muito.
    Estou tendo um probleminha para saber como enviar um anexo. Estou utilizando este exemplo em um projeto de APP mobile(Android primeiro). Porém este anexo seria uma foto. Gostaria de saber como enviar como anexo uma imagem, tirando de um TImage.

    É o seguinte: Eu tenho um botão para escolher o arquivo da galeria e outro para tirar uma foto. Após executado eu jogo para meu TImage da seguinte forma pra aparecer o preview da seguinte forma:

    procedure THeaderFooterForm.TakePhotoFromCameraAction1DidFinishTaking(Image: TBitmap);
    begin
      Image9.Bitmap.Assign(Image);
    end;
    
    procedure THeaderFooterForm.TakePhotoFromLibraryAction1DidFinishTaking(
      Image: TBitmap);
    begin
      Image9.Bitmap.Assign(Image);
    end;

    Então, gostaria de enviar está imagem. Poderia me ajudar? É a única coisa que está faltando para eu terminar meu APP.
    Obrigado.

    1. Olá, Leandro, tudo bem?

      Ainda não tive a oportunidade de testar o código apresentado no artigo em um aplicativo mobile. Mesmo assim, acredito que será necessário referenciar a imagem pelo caminho em que ela está armazenada, ou seja, através do comando GetPicturesPath. Dessa forma o TIdAttachmentFile conseguirá localizar a carregar a imagem como anexo.

      Abraço!

    2. Ótimo Post Andre..
      Porém como colega Leandro Lanini, gostaria de utilizar o envio de e-mail direto de um APP android. Porém, este exemplo exige as DLL’s.. então Leandro, como vc conseguiu utilizar este exemplo em sua aplicação mobile??

      Agradeço desde já!

    3. Obrigado pelo Retorno André.
      Eu ja vi este artigo do Landerson, porém, não serve..Tem até outras pessoas questionando essa mesma necessidade que estou precisando.
      O app precisa efetuar um disparo de e-mail diretamente, sem a intervenção do usuário selecionando um gerenciador de e-mail de seu app.

      Situação: Usuário efetua cadastro no App e ao salvar os dados, é disparado um e-mail para a conta cadastrada.. seja uma boas vindas ou confirmação dos dados cadastrados.

      Estou pesquisando em vários lugares e não consigo encontrar nada como o Delphi faria isto!!

      Utilizo um app(carrorama) que envia e-mail de relatório com o excel em anexo, bastando preencher o e-mail, assunto e texto e pronto.

      Deu pra entender o que seria?

      Agradeço desde já!

    4. olá. também preciso usar esse processo todo de enviar email em um app para android e ios pelo delphi firemonkey. Mas tem essas dll’s necessárias. Alguém pode me ajudar ou solucionou esse problema? ficaria extremamente grato.

  60. Boa tarde Andre, na minha maquina funcionou tranquilo mais ao tentar mandar de outra maquina deu erro
    “Erro na conexão ou autenticação.Could not load SSL Lybrary estou usando o xe10

    1. Olá, Renato, tudo certo?
      Junto com o executável, você deve levar também as DLLs do Indy para conexão (ssleay32.dll e libeay32.dll), lembrando que estes arquivos devem ficar na mesma pasta do executável.

      Abraço!

  61. Ja fiz isso inclusive coloquei tambem no sytem32 e nao deu certoinstalei ate o xe10 na maquina e nao vai.
    Project EnviaEmail.exe raised exception class EIdOSSLCouldNotLoadSSLLibrary whith message Çould not load SSL Library’, copiei o projeto da minha maquina para a docliente rodei la e nada o mesmo erro

  62. Hola Andre
    Mucho gusto en escribirle. tengo un problema con el correo que estoy utilizando es de mail.office365.com, en sus opciones de correo me pide esto:
    Nombre de servidor: smtp.office365.com
    Puerto: 587
    Método de cifrado: STARTTL

    entonces, yo lo codifico así:

    IdSSLIOHandlerSocket.MaxLineAction := maException;
    IdSSLIOHandlerSocket.SSLOptions.Method := sslvTLSv1;
    IdSSLIOHandlerSocket.PassThrough := True;
    IdSSLIOHandlerSocket.SSLOptions.Mode := sslmClient;

    IdSMTP.IOHandler := IdSSLIOHandlerSocket;
    IdSMTP.UseTLS := utUseImplicitTLS;
    IdSMTP.AuthType := satDefault;
    IdSMTP.Port := 587;
    IdSMTP.Host := ‘pod51004.outlook.com’;
    IdSMTP.Username := ‘myuser’;
    IdSMTP.Password := ‘mypass’;

    Pero cuando intento enviar el email me sale el error: Error connecting with SSL, Error 1408F10B: SSL Routines:SSL3_GET_RECORD: wrong version number

    Que puedo estar haciendo mal? alguna idea?

  63. Andre, boa noite.

    Estou usando Delphi Berlin e estou com o mesmo problema que o Renato Aquino.
    Retorna sempre “Could not Load SSL Library’

    Poderia me ajudar.

  64. André, boa tarde.

    Gostei muito do seu blog. Tenho pouco tempo no delphi, estou usando o berlin update2, fiz um aplicativo seguindo o seu modelo para usar no android, mas quanto tento enviar ele retorna a seguinte mensagem depois de passar por IdSMTP.Send(IdMessage): “Erro na conexão ou autenticação”, um showmessage que eu coloque, pois não consegui usar o messagedlg. E mesmo assim a momento que ele envia e outros não.
    Como faço pra ele ficar 100%, estou precisando muito dele.
    Obrigado!!

    1. Olá, Jorge, tudo bem?
      Este código para envio de e-mails não está otimizado para aplicativos Android. Acredito que algumas alterações devem ser aplicadas.
      Em breve pretendo estender esse assunto de envio de e-mails, envolvendo o Firemonkey.

      Abraço!

  65. Boa noite!

    Eu também estou recebendo a mensagem de erro “Could not Load SSL Library”. Já adicionei as referidas DLL(s) à pasta da aplicação. Você conseguiu ajudar os demais colegas que estavam passando pelo mesmo problema?

    Obrigado.

    1. Boa noite, Lincoln!
      Geralmente o problema está relacionado com a versão correta das DLLs.
      Vou entrar em contato com você para verificar a versão do Delphi que você está utilizando.
      Abraço!

  66. Boa tarde André,

    Could not load SSL library, usso Delphi XE7, tentei seguir alguns procedimento que o pessoal colocou aqui e nada, está dando esse erro. Preciso de uma força sua. Muito obrigado

  67. Ola Andre, você já é mestre em enviar email, estou sofrendo para enviar um PDF em anexo, não vai de forma alguma, o email é enviado, mas chega sem anexo, Uso Delphi Xe7, Indy 10.6.0.5169

    Agradeço sua ajuda

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha o campo abaixo * Time limit is exhausted. Please reload CAPTCHA.