1
votes

Some Outlook VBA code that saves email attachments according to their file names failed on an embedded bitmap image when it tried to access the FileName property of that "attachment."

How can I detect this? The FileName property is supposed to be a String but neither of these tests catches it:

If objAtt.FileName = "" Then ....
If objAtt.FileName = vbNullString Then ....

But every attempt to access this property throws a run-time error:

Outlook cannot perform this action on this type of attachment.

I would prefer not to use the DisplayName property if possible.

Also, it seems that I could filter the attachments according to the value of their FileType properties but I have not been able to find a list associating these Integer values with file types.

Advice is appreciated.

1

1 Answers

2
votes

FileName property is only applicable to the regular olByValue type attachments. In your case you are most likely dealing with an olOLE type attachment, which is really a serialized embedded OLE object - the stream stores the bitmap (or metafile) that Outlook uses to represent the image as well as the actual data that the original application that created the data (MSPaint?) can use to edit it.

OLE attachment data is stored in the IStorage interface format. The actual format of the data depends on the application used to create it (MSPaint, Excel, etc.). Outlook Object Model does not let you save such attachments using Attachment.SaveAsFile.

Depending on the language you are using (C++ or Delphi would be best), you will need to open the PR_ATTACH_DATA_OBJ property as IStorage and then extract the data (IAttach::OpenProperty(PR_ATTACH_DATA_OBJ, IID_IStorage, ...)) . Take a look at the message with OutlookSpy - click IMessage button, go to the GetAttachmentTable tab, double click on the OLE attachment, select the PR_ATTACH_DATA_OBJ, right click, IMAPIProp::OpenProperty.

If using Redemption is an option, it extracts the the attachment data for a dozen or so most popular formats (MSPaint, Excel, Word, PDF, etc.):

set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
set OutlookMsg = Application.ActiveExplorer.Selection.Item(1)
set Msg = Session.GetRDOObjectFromOUtlookObject(OutlookMsg)
for each attach in Msg.Attachments
  attach.SaveAsFile "c:\temp\" & attach.FileName
next