4 de agosto de 2011

Recuperando emails de uma caixa postal com Delphi

Até pouco tempo atrás, o ERP da ABC71 possuia um recurso que permitia aos usuários enviarem sugestões de melhorias do software por email. Uma aplicação em nossos servidores monitorava a caixa postal específica, interpretava algumas informações incluídas em cada email, vinculava a solicitação a um responsável e respondia automaticamente o email do usuário com uma mensagem pré-formatada preparada pelo atendimento a Clientes.

Hoje esse esquema não existe mais - foi substituído por outros canais com papel similar - mas a ideia da aplicação capaz de monitorar uma caixa postal ainda é válida e pode ser reaproveitada em outros cenários.

A solução adotada por nós é baseada no protocolo chamado POP3 (Post Office Protocol). Com ele é possível recuperar todas as mensagens existentes na caixa de entrada de uma conta de email. A implementação dele que usamos é a do Projeto Indy distribuida junto com o IDE do Delphi;

Da mesma forma que outros protocolos baseados no IP, usar o POP3 exige que se faça a conexão com o servidor antes de realizar qualquer operação. Temos, então, que informar o nome (ou endereço) desse servidor, a porta onde se conectar e um nome de usuário e sua senha, válidos para a operação desejada.
var _IdPOP3 : TIdPOP3;
begin
_IdPOP3 := TIdPOP3.Create (Nil);

_IdPOP3.Host := _ServidorPOP;
_IdPOP3.Port := _PortaPOP;
_IdPOP3.Username := _Username;
_IdPOP3.Password := _Userpwd;
_IdPOP3.AutoLogin := True;

_IdPOP3.Connect ();

A propriedade AutoLogin ajustada com o valor true indica que o componente tentará automaticamente fazer o login no servidor sempre que isso for necessário, evitando que tenhamos que comandar o login manualmente.

Uma vez que temos a conexão estabelecida, podemos iniciar a recuperação das mensagens da caixa de entrada. Há basicamente dois níveis de informação que conseguimos recuperar sobre uma mensagem. Em ambos os casos, as informações são armazenadas numa variável do tipo TIdMessage. No primeiro nível, são obtidos somente os dados de cabeçalho da mensagem - como o assunto, o remetente e os destinatários -, o que reduz o tráfego na rede. O trecho abaixo recupera o cabeçalho da primeira mensagem da caixa de entrada:
var msg : TidMessage;
begin
msg := TidMessage.Create(self);

_IdPOP3.RetrieveHeader (1, msg);
{ ... }
msg.Free;

O segundo nível permite recuperar a mensagem completa, incluindo todas as informações do nível anterior, bem como o corpo da mensagem e todos os anexos dela. Ao utilizar esse método, a caixa postal marca automaticamente a mensagem como lida:
var msg : TidMessage;
begin msg := TidMessage.Create(self);

_IdPOP3.Retrieve (1, msg);
{ ... }
msg.Free;

Com as informações obtidas nesse nível, temos maior flexibilidade para customizar tratamentos para as mensagens. Por exemplo, podemos redirecionar a mensagem para outra pessoa de acordo com o conteúdo ou processar os anexos, salvando-os numa pasta do computador ou num banco de dados.

Não podemos esquecer que o conteúdo de um email pode ser composto de diversas partes distintas, conforme mostrei no post sobre envio de email com Delphi. Então, dependendo de como o email foi composto, recuperar o corpo da mensagem pode ser um simples acesso à propriedade msg.Body.Text ou significará termos que percorrer a lista de partes para determinar qual é o texto contido. Se o texto no corpo está em branco, basta percorrer a lista de partes procurando por uma que seja do tipo texto (TIdText):
var { ... }
parte : TIdMessagePart;
texto : TIdText;
corpo : string;
begin
{ ... }
_IdPOP3.Retrieve(1, msg);

for j := 0 to msg.MessageParts.Count - 1 do begin
parte := msg.MessageParts.Items[j];
{ Verifica se a parte é um texto }
if (parte is TIdText) then begin
texto := parte as TIdText;
corpo := texto.Body.Text;
break;
end;
{ ... }

O tipo do texto contido numa parte fica informado na propriedade ContentType. Como é permitido ter mais que uma parte com texto, pode-se testar esse tipo para recuperar o texto que interessa. É comum enviar uma parte com texto HTML e outra com texto TEXT/PLAIN para que o programa leitor de email decida qual exibir, de acordo com a opção feita pelo usuário.

Da mesma forma que recuperamos o texto lendo as partes, podemos salvar os anexos. Para isso, a parte deve ser do tipo TIdAttachment. Também podemos determinar o tipo do conteúdo do anexo lendo a propriedade ContentType da parte em questão. Salvar o arquivo fica fácil :
{ ... }
for j := 0 to msg.MessageParts.Count - 1 do begin
parte := msg.MessageParts.Items[j];
{ Verifica se a parte é um anexo }
if (parte is TIdAttachment) then begin
anexo := parte as TIdAttachment;
anexo.SaveToFile('c:\temp\' + anexo.FileName);
end;
{ ... }

Mas, como saber quais mensagens podem ser recuperadas ? A quantidade de mensagens existentes é conseguida através da função CheckMessages; podemos recuperar qualquer uma delas usando um número inteiro entre 1 e essa quantidade. A lista é trazida em ordem cronológica, com as mensagens mais antigas da caixa de entrada possuindo os menores números de identificação.
for i := 1 to _IdPOP3.CheckMessages do
begin
msg := TidMessage.Create(self);
_IdPOP3.RetrieveHeader (i, msg);

if DeveRecuperarMsg (msg.MsgId) then
TrataMsg (Msg);
msg.Free;
end;

As mensagens lidas permanecem na caixa até que sejam removidas. O POP3 permite fazer essa remoção mas nem sempre isso é uma opção. Para esses casos, uma sugestão é controlar manualmente as mensagens. Elas possuem uma string de identificação chamada MsgID que é única, como mostra o código acima. A ideia é recuperar apenas o cabeçalho da mensagem, testar se o MsgID atual já foi tratado antes e só então trazer a mensagem completa, se for necessário.

Quando concluir as operações na caixa postal, finalize a conexão com o POP3 usando a função Disconnect.

Como se pode ver pelo exemplo retratado neste post, o protocolo POP3 é bastante simples, limitando-se a poucas funcionalidades básicas. Se for preciso usar recursos mais avançados, tais como restringir as mensagens recuperadas usando filtros ou realizar operações envolvendo "pastas" na caixa postal, teremos que apelar a um protocolo mais completo, como o IMAP4. No post Trabalhando com emails em uma caixa postal usando IMAP4 em Delphi eu mostro como usá-lo.

Mais Informações
Post Office Protocol

61 comentários :

Anônimo disse...

Show de bola! Muito obrigado por compartilhar esta informação!

Anônimo disse...

cara muito bom , porem to tentando de usar o chekmenssages , mas ele s'o me retorna "0" (zero) mesmo com menssagens na cx de email !

tem alguma sugestao ?

Luís Gustavo Fabbro disse...

Marcelo

Uma possibilidade é que você tenha feito a conexão com um "servidor / conta de email" diferente daquele que vc imaginou. Revise suas configurações para ver se é esse o caso.

Veja também se as mensagens que você tem estão na caixa postal ou em subpastas. Não tenho certeza mas acredito que o CheckMessages só é capaz de enxergar o que está diretamente na caixa de entrada.

Se você precisa trabalhar com pastas ou quer mais flexibilidade no acesso aos emails, use o IMAP4.

Anônimo disse...

Marcelo :
muito obrigdo pelo retorno ! fiquei surpreso !
bom vamos la !
que esta ocorrendo e que , ao bx a menssagem
ele nao baixa mais , queria saber se tem como mudar o status da menssagem , para que possa baixa quantas vezez quizer ! sera q tem como ?

Luís Gustavo Fabbro disse...

Marcelo

O que vc quer dizer com "a mensagem não baixa mais" ?. Após serem recuperadas com os métodos mostrados no post, as mensagens continuam disponíveis no servidor - a não ser que sejam removidas.

O que pode acontecer é ela ser marcada como "já lida". Se quer marcá-la novamente como "não lida", terá que usar o IMAP4 pois o POP3 não prevê essa alternativa.

Anônimo disse...

Marcelo :
ok , parti entao para o imap ,
show de bola!!
no seu blog imap4 , tem uma procedure ou funcao de nome
SelecionaCaixaPostal que nao tem seu conteudo no codigo
teria como vc me fornecer esta ? ou me explicar como funciona !
muito obrigado !

Luís Gustavo Fabbro disse...

Marcelo

Como diz o comentário incluído no fonte, a função SelecionaCaixaPostal pega os nomes das caixas postais levantadas pelo ListMailBoxes e os mostra num form separado para que o usuário possa escolher qual deve ser aberta.

A seleção feita pelo usuário é retornada na variável lCaixaSel, que por sua vez é usada em SelectMailBox para efetivamente abrir a caixa escolhida.

[]s

Souza disse...

Ola Luis, Gostaria de mandar para lixeira ou até mesmo apagar as mensagens já recebidas, de uma só vez, isso é possivel usando o POP3, desde já agradeço.

Luís Gustavo Fabbro disse...

Souza

Até onde eu conheço, você terá que usar a função Delete para remover as mensagens. Só que o jeito que ela trabalha exigirá uma chamada para cada mensagem que queira remover, já que ela aceita como parâmetro a identificação de uma única mensagem.

[]s

Marcello Avella disse...

Muito bom, Luís, estou usando as dicas para construir um mecanismo parecido com o que você descreve no ERP. Abraços!

Marco A. Oselame disse...

Muito bom... vlw...

Hélio Galvão disse...

eu não ia achar ruim se tivesse ai um "projetinho" pronto pra baixar ^^ rsrs

se algm tiver um, por favor disponibiliza ae o link, plis!!! =]

Hélio Galvão disse...

Você tem um "mini-projeto" pronto? deixe-o pra download porque assim fica mais fácil testar do que pegar fragmentos. ^^

mas quem já está adiantado no Delphi, o POST foi muito bom! Parabéns!

Anônimo disse...

Muito bom o post!

voce poderia postar o codigo de "DeveRecuperarMsg" e "TrataMsg"???

Luís Gustavo Fabbro disse...

A DeveRecuperarMsg apenas verifica num banco de dados se já foi processada a mensagem com o ID passsado como parâmetro.

A TrataMsg usa as técnicas descritas no post para recuperar a mensagem e grava no banco de dados.

[]s

Guihgo disse...

Cara valeu , mas meu Count do Message part é sempre 0 (ZERO)!

como faço para resolver esse problema??

Luís Gustavo Fabbro disse...

Guihgo

Se você chamou o RetrieveHeader, apenas informações de cabeçalho são retornadas (assunto, por exemplo). Se está usando o Retrieve, o MessageParts sejá preenchido automaticamente apenas se a mensagem possuir anexos.

[]s

Anônimo disse...

seria legal se vc fizesse um programa no source forge tipo o outlook feito pelo delphi o q acha? poderiamos aprender muito com ele e ate mesmo contribuir com o mesmo!!!!
pelas modificaçoes q o indy vem sofrendo acho q seria legal fazer o projeto no xe2 ou quem sabe no q vai ser lançado o xe3 topa?

Marcos disse...

Seria bom mesmo!

Luís Gustavo Fabbro disse...

Infelizmente, não vou ter tempo de me dedicar a um projeto desses ... Mas, se quiser mesmo, monte-o e submeta as eventuais dúvidas ao blog. Tentarei respondê-las na medida do possível.

[]s

Unknown disse...

Show de bola! Fiz exatamente como você sugeriu inclusive com a function DeveRecMsg e com a procedure TrataMsg. Perfeito!
Valeu!

Marcos Martins disse...

Primeiro queria parabenizar pelo artigo!!! Fiz todo o procedimento, consegui adequar ao meu sisteminha que estou fazendo, só no remetente quando tem acentos fica tudo zuado, como posso resolver isso?

Luís Gustavo Fabbro disse...

Marcos

Seu servidor de email pode estar retornando as mensagens com codificação UTF-7. A grosso modo, essa codificação mantem intactos os caracteres ASCII de um texto enquanto "expande" os outros para que possam ser representados como uma sequência de caracteres ASCII.

Por exemplo, no texto "Notificação" os caracteres ç e ã não são ASCII e, por isso, são expandidos respectivamente como &AOc- e &AOM-. O texto final (Notifica&AOc-&AOM-o) é representado apenas por caracteres ASCII.

Neste caso, vc pode reverter manualmente a codificação. Neste link do Wikipedia há uma descrição dos algorítmos para codificar e decodificar textos com UTF-7.

[]s

Luciano G. disse...

Bom dia,
Cara, dei uma procurada e não achei, como eu faço para Arquivar uma mensagem com o IdPOP3?

Abraço.

Luís Gustavo Fabbro disse...

Luciano

O POP3 é um protocolo bastante limitado - basicamente, você pode recuperar uma mensagem e apagá-la do servidor. Para operações mais complexas - como copiar o email para outra pasta (arquivar) - use o IMAP4. Há um post sobre ele neste link.

[]

Luciano G. disse...

Boa tarde,
Pois é, é que neste link sobre IMAP esta postado assim:

"O POP3 é um protocolo amplamente adotado para permitir o acesso remoto aos emails de uma caixa postal mas ele é bastante limitado. Seus recursos estão restritos basicamente à manipulação das mensagens existentes na caixa postal, permitindo lê-las, apagá-las ou ARQUIVÁ-LAS."

Rss, por isso perguntei!

Abraço.

Luís Gustavo Fabbro disse...

Achei que vc estivesse se referindo a função Arquivar do Outlook, onde você pode lançar mensagens para um arquivo morto.

Quando disse que você pode "arquivar" uma mensagem eu me referia a "guardar uma cópia fora do servidor de email". Assim, uma vez que o TidMessage está carregado com a mensagem desejada, vc pode salvá-la em arquivo ou enviá-la para um stream, disponibilizando-a, por exemplo, para um sistema de Base de Conhecimento ou de Gestão de Documentos.

Obviamente, isso pode ser conseguido tb com o IMAP4. Com esse protocolo, no entanto, vc pode reorganizar os emails em pastas no próprio servidor, sem precisar manter cópias locais.

[]s

Luciano G. disse...

Rss, pois é, fiz confusão então.

Muito obrigado por Responder..

Fiz um programinha básico, mas vou deixar o link aqui nos comentários, pode ser útil para alguém!

http://www.4shared.com/rar/OiCMkYt1/IdPOP3.html?
Está com Senha: idpop3 (minúsculo).

Abraços

Luís Gustavo Fabbro disse...

Luciano

Obrigado por compartilhar sua solução.

[]s

Eduardo Flaeschen disse...

Boa noite,
Parabéns pelo artigo, muito bom !!!
Tenho uma pergunta: preciso salvar a mensagem recebida em um arquivo html, tem como fazer ?
Obrigado.
Eduardo Flaeschen

Luís Gustavo Fabbro disse...

Eduardo

Se o ContentType do texto do email (TIdText) já indicar que o conteúdo é html, basta salvar esse conteúdo num arquivo HTML.

Entretanto, se for um texto comum (plain text), você terá que prepará-lo antes de salvar como HTML, montando as tags manualmente.

[]s

Perfil Sistemas disse...

Tentei usar no delphi 2009 o demo não funcionou

Anônimo disse...

Você tem um exemplo igual este com delphi 2009?

Luís Gustavo Fabbro disse...

Que tipo de problema você enfrentou ? Tenho o Delphi 2005 e o XE, respectivamente com Indy 9 e 10; em ambos a recuperação descrita no post funcionaram normalmente.

[]s

Luís Gustavo Fabbro disse...

Eu não tenho essa versão do Delphi mas não creio que o Indy tenha mudado a ponto de impedir o código do post de funcionar. Houve algum problema para usar o conteúdo do post com Delphi 2009 ?

[]s

Anônimo disse...

Bom dia, estou utilizando pop3 para baixar email que contem anexo ( XML da NF-e ) porem quando baixo o XML este arquivo vem com falhas dentro do arquivo. Ex: TAG valor NF : 12..90 o correto seria 12,90

Teria como resolver isso de alguma forma ?

Obrigado

Luís Gustavo Fabbro disse...

Você está fazendo algum outro processamento com o XML? Experimente salvar o conteúdo dele num arquivo para ver se aí já está corrompido.

Ao extrair anexos, são comuns problemas com acentuação e caracteres especiais. Mas o tipo de problema que vc está descrevendo parece ser de interpretação do conteúdo e o algoritmo para extrair os anexos não faz inferências sobre as tags nesse conteúdo.

[]s

rogerio disse...

Boa tarde!
Estou com um problema para implementar, ao incluir somente os campos descritos no artigo, no conectar o programa fica processando e não sai do lugar, usei as mesmas configurações que fiz para o Outlook manualmente(para Hotmail e deu certo), fique com uma dúvida quanto ao "servidor requer ... ssl" no componente Indy não sei como seria o correto configurar isso, tentei meio que adaptar algumas configurações para o pop3 o mesmo que vc usou no outro artigo para SMTP gmail, mas não foi da o seguinte erro "...exception class EidOsslCouldNotLoadSSLLibray whith message 'Could not load SSL library.". Bom é só isso

Luís Gustavo Fabbro disse...

Rogério

Essa mensagem que você está recebendo está relacionada às bibliotecas do projeto OpenSSL utilizadas pelos componentes do Indy para tratar conexões com segurança SSL ou TLS. Você precisa distribuir as duas DLLs desse projeto junto com sua aplicação - libeay32.dll e libssl32.dll.

Há versões específicas das DLLs para cada versão do Delphi. Então, tem que garantir também que as versões utilizadas são mesmo compatíveis com seu Delphi.

[]s

Felix Winter vier disse...

Opa Ótimo o Post, gostaria de saber se tem como pegar as mensagens por status,como lida ou não, neste método.?

Grato!

Luís Gustavo Fabbro disse...

Felix

O protocolo POP3 tratado neste post é bastante limitado; o controle de qual mensagem já foi lida tem que ser feito manualmente, como mostrado.

Se precisar realizar operações mais complexas, use o protocolo IMAP4. Há um post no blog a respeito dele também : Trabalhando com emails em uma caixa postal usando IMAP4 em Delphi.

[]s

Unknown disse...

Boa tarde. Luís Gustavo, estou com um problema para baixar emails de uma conta, o erro é Socket Error # 10060
Connection timed out. Tentei resolver aumentando o ConnectTimeout mas não importa o tempo sempre diz a mesma coisa. O que pode ser?

Luís Gustavo Fabbro disse...

Cezar

Esta mensagem está associada à infraestrutura de rede. Pode ser, por exemplo, um bloqueio no firewall; pode ser tb que o servidor de email não esteja acessível a partir do computador onde seu programa está executando. Tente acessar o servidor por outros meios (Ping, hyperterminal, etc) pra certificar que ele esteja disponível.

[]s

Anônimo disse...

Bom dia. Luís Gustavo, configurei o Outlook com os mesmos parâmetros do meu aplicativo e ele consegue baixar sem problema. Já eu consigo apenas enviar. O email que tento acessar é o SquirrelMail. Estou começando a pensar que o problema é ali, pois fiz uma conta gratuita no Bol e então funcionou. Será que tem como resolver isso?

Luís Gustavo Fabbro disse...

Veja com quem instalou o SquirrelMail se os parâmetros lançados em sua aplicação estão mesmo completos e corretos - o Outlook pode estar usando valores padrão para alguns deles (portas e camadas de segurança, por exemplo). O pessoal de suporte à sua rede tb pode ajudar a determinar a razão para sua conexão remota estar falhando.

[]s

Unknown disse...

Bom dia. Luís Gustavo, estou receoso com relação à questão da rede. Imagine que eu fiz emails do bol para garantir que funcionasse. E funcionou, mas só aqui comigo. Quando instalei no note do cliente que está em outra cidade, pronto, já não recuperou mais as mensagens, isso pelo mesmo email que aqui comigo funciona perfeitamente. Fico pensando: será que terei de ficar à mercê da rede que o cliente utilizar sempre? Ainda, por favor, você pode me dar alguma luz sobre a questão das camadas de segurança das quais você tratou na resposta anterior? Obrigado.

Luís Gustavo Fabbro disse...

Cezar

Cada cliente seu terá infraestrutura de rede com suas configurações próprias diferentes, como firewalls, sites e IPs bloqueados, regras individualizadas de acesso externo, mapeamentos internos de servidores para evitar invasões de hackers, etc. Neste sentido, seu programa está sim à mercê da rede dos clientes.

O melhor a fazer é abrir a configuração do programa pra permitir a cada cliente adaptá-lo ao seu próprio cenário. Pode até mesmo incluir logs para facilitar a detecção de problemas na configuração.

Com relação à segurança, eu me refiro ao uso de SSL ou TLS no acesso à caixa postal pois esses recursos normalmente exigem passos extras na comunicação, além de portas especiais na conexão.

[]s

Unknown disse...

Bom dia.

Luís Gustavo, entendi. Vou repensar a forma de configuração.
Mais uma vez obrigado pelos esclarecimentos.

Anônimo disse...

Bom dia, Luis Gustavo.

Parabéns pelo artigo, estou com uma dificuldade que é excluir as mensagens depois de lida da caixa postal, o comando delete não está fazendo isso, tem alguma sugestão ?
Abaixo o meu código
qtd := _IdPOP3.CheckMessages;
msg := TidMessage.Create(self);
_IdPOP3.RetrieveHeader (1, msg);
msg.Free;

for i := 1 to qtd do
begin
msg := TidMessage.Create(self);
_IdPOP3.Retrieve(qtd - i + 1, msg);
for j := 0 to msg.MessageParts.Count - 1 do
begin
parte := msg.MessageParts.Items[j];
{ Verifica se a parte é um anexo }
if (parte is TIdAttachment) then
begin
anexo := parte as TIdAttachment;
if Pos('CTE', UpperCase(anexo.FileName)) > 0 then
begin
if Pos('xml', anexo.FileName) > 0 then
begin
if not(FileExists(caminho + anexo.FileName)) then
anexo.SaveToFile(caminho + anexo.FileName);
end;
end;
end;
end;
_IdPOP3.Delete(qtd - i + 1);
msg.Free;
end;

Luís Gustavo Fabbro disse...

O Delete envia ao servidor uma instrução para marcar a mensagem; a remoção de fato só ocorre quando você encerra a conexão, ao chamar a função Disconnect. Veja a documentação em http://kumanov.com/docs/prog/indy/007617.html#0004.

Há alguma mensagem de erro na execução? O Delete está retornando TRUE? Como vc está verificando se foi mesmo removido?

[]s

Perfil Sistemas disse...

Quando eu tento conectar da erro de closed gracefully alguém sabe o que pode ser?

Luís Gustavo Fabbro disse...

Essa mensagem indica que ocorreu um erro mas o que o Indy conseguiu tratá-lo e encerrar a conexão. Você pode obter detalhes do erro adicionando um dos componentes de log para interceptar a comunicação do Indy com o servidor (TIdLogEvent ou TIdLogFile, por exemplo).

[]s

Mau Andrade disse...

primeiramente muito obrigado pelo artigo! estou usando o indy 10 para recuperar arquivos usando a comparação abaixo, mas no meu caso esta vindo todos os arquivos ligados ao email sendo eles os anexos e também as imagens que por ventura esteja do corpo da mensagem como um logo. Voce saberia me dizer como pegar somente os anexos?

for j := 0 to msg.MessageParts.Count-1 do
begin
if msg.MessageParts[j] is TIdAttachmentFile then

Luís Gustavo Fabbro disse...

Mau


Imagens (e outros recursos) no texto HTML de um email são anexadas à mensagem, junto com os arquivos anexados manualmente pelo usuário. O que dá pra fazer é inspecionar a propriedade ContentType do anexo pra determinar se é um tipo que seu programa deve tratar - um XML ou um ZIP, por exemplo.

[]s

Infoco Soluções Visuais disse...

Ola muito bom artigo
uma duvida a propriedade 'Anexo' que recebe

if (parte is TIdAttachment) then begin
anexo := parte as TIdAttachment;

é de que tipo? porque estou tendo problemas em salvar os anexos, ja tentei usar metodos da propria classe do TidAttachment, como savetofile, stream e não consigo.

Luís Gustavo Fabbro disse...

A variável anexo é do tipo TIdAttachment mesmo. Ocorre algum erro de compilação ou de execução? Que sintomas acontecem?

[]s

Infoco Soluções Visuais disse...

ele simplismente fala que não consegue abrir o arquivo.
Ja tentei com stream, filestream, com encode do tidattachement, em uma das tentativas a função copyfile da unit idglobal não recebe o source.

function CopyFileTo(const Source, Destination: string): Boolean;
begin
Result := CopyFile(PChar(Source), PChar(Destination), true);
end;

Luís Gustavo Fabbro disse...

A função CopyFile apenas faz a cópia de um arquivo pré existente no sistema de arquivos de seu computador; isto é, ela é incapaz de extrair o anexo de um email. É preciso ver o que foi feito antes pra tentar salvar o anexo e, se foi salvo com sucesso, saber onde ele foi efetivamente salvo e com que nome.

[]s

Perfil Sistemas disse...

Comigo também ocorre isso como resolver? Só retorna zero mesmo colocando RetrieveHeader

Perfil Sistemas disse...

Eu estou usando RetrieveHeader a mensagem tem anexo, mas só retorna zero IDmessage1.MessageParts.Count, mas tem anexo no e-mail

Luís Gustavo Fabbro disse...

Além da questão do RetrieveHeader citada acima, verifique se a recuperação está sendo feita num loop. Neste caso, prefira recriar a instância do TIdMessage, dando um new. Leituras consecutivas na mesma instância podem deixar sujeira e atrapalhar a leitura seguinte.

[]s

Postar um comentário

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.

Observação: somente um membro deste blog pode postar um comentário.