Coletando e-mails da caixa de entrada do Outlook com Delphi
Eu escrevi alguns códigos para ler e-mails da caixa de entrada do Outlook e coletar anexos.
Isso está funcionando muito bem. Estou usando o Outlook 2019 / Office 365.
Posso usar os dois Mail.SenderEmailAddressou Mail.Sender.Addresspara obter o endereço de e-mail do remetente.
Ao implantar meu aplicativo em outro computador com Outlook 2016, recebo este erro:
EOleError: Método 'Sender' não suportado pelo objeto de automação
Mesmo para Mail.SenderEmailAddress
Outlook 2016 ou 2019 têm o mesmo fluxo de código. Veja as versões do Outlook, números de compilação e outras curiosidades .
Você poderia ajudar a entender por que recebo esse erro no computador do meu cliente e como posso corrigir esse problema?
Você está ciente de uma biblioteca gratuita / comercial ou componentes que podem fazer isso sem problemas?
Isso está de alguma forma relacionado com a minha outra pergunta sobre como enviar e-mail do Outlook com Delphi .
try
Outlook:=GetActiveOleObject('Outlook.Application') ;
except
Outlook:=CreateOleObject('Outlook.Application') ;
end;
try
oNameSpace := Outlook.GetNamespace('MAPI');
oNameSpace.Logon;
Inbox:= oNameSpace.GetDefaultFolder(6);
iNbMail:= Inbox.Items.Count;
for i:= iNbMail downto 1 do
begin
if VarIsNull(Inbox.Items[i]) or VarIsEmpty(Inbox.Items[i]) then
Continue;
Mail:= Inbox.Items[i];
EmailAddress:= Mail.Sender.Address;
// EmailAddress:= Mail.SenderEmailAddress;
UnReadFlag:= Mail.UnRead;
iNbAttach := Mail.Attachments.Count;
for j := iNbAttach downto 1 do
begin
Attachment:= Mail.Attachments[j];
if ExtractFileExt(Attachment.FileName) = '.pdf' then
begin
SaveName:= TPath.Combine(InboxFolder, Attachment.FileName);
Attachment.SaveAsFile(SaveName);
end;
end;
Mail.UnRead:= False;
end;
finally
Outlook:= Unassigned;
oNameSpace:= Unassigned;
Inbox:= Unassigned;
Mail:= Unassigned;
end;
Respostas
A pasta da caixa de entrada no Outlook não se restringe a conter apenas mensagens de correio. Quando a iteração através de seus itens que você pode encontrar várias classes de itens como MailItem, PostItem, MeetingItem, TaskRequestIteme muitos outros. Todos esses itens oferecem suporte a diferentes conjuntos de propriedades e nem todos têm Sender, SenderEmailAddressou Attachmentspropriedade. Se você estiver interessado apenas em itens de correio, será necessário verificar as Classpropriedades do item :
const
olMail = $0000002B;
{ ... }
for i := iNbMail downto 1 do
begin
Mail := Inbox.Items[i];
if Mail.Class <> olMail then
Continue;
{ here we can assume we're working with MailItem instance }
end;
Duvido que o Outlook retorne um item nulo ou vazio, então a verificação que você faz em seu código é inútil. Se você estiver interessado em outras classes de itens, verifique a OlObjectClassenumeração.
Não sei por que você prefere usar a ligação tardia , porque o Delphi já vem com uma biblioteca de tipos importada Outlook2010.paspara automatizar o Outlook de maneira fortemente tipada. A biblioteca está localizada na OCX\Serverssubpasta da pasta de instalação. Caso seja necessário oferecer suporte a versões pré-2010 do Outlook, você pode usar a unidade OutlookXPou até mesmo em seu Outlook2000lugar. O código antes de iterar itens de email usando a biblioteca de tipos poderia ser assim:
uses
System.SysUtils, System.Variants, Winapi.ActiveX, Outlook2010;
function GetOutlookApplication: OutlookApplication;
var
ActiveObject: IUnknown;
begin
if Succeeded(GetActiveObject(OutlookApplication, nil, ActiveObject)) then
Result := ActiveObject as OutlookApplication
else
Result := CoOutlookApplication.Create;
end;
procedure ProcessInboxItems;
var
Outlook: OutlookApplication;
Inbox: Folder;
Index: Integer;
LItems: Items;
LMailItem: MailItem;
begin
Outlook := GetOutlookApplication;
Outlook.Session.Logon(EmptyParam, EmptyParam, EmptyParam, EmptyParam);
Inbox := Outlook.Session.GetDefaultFolder(olFolderInbox);
LItems := Inbox.Items;
for Index := LItems.Count downto 1 do
begin
if Supports(LItems.Item(Index), MailItem, LMailItem) then
begin
{ do whatever you wish with LMailItem }
end;
end;
end;