0

I need to create an OutLook add-in that catches emails with large attachments and replaces the attachment with a URL that can be used to download the attachment.

I found this which shows how to modify an attachment before sending it that looked like a good starting point but the problem is that the call:

const string PR_ATTACH_DATA_BIN = "http://schemas.microsoft.com/mapi/proptag/0x37010102";

var attachmentData = attachment.PropertyAccessor.GetProperty( PR_ATTACH_DATA_BIN);

fails with an error saying the property is unknown or cannot be found.

I can call attachment.PropertyAccessor.GetProperty() to get the attachment type which is 1 (ATTACH_BY_VALUE) so I should be able to get the data with attachment.PropertyAccessor.GetProperty(PR_ATTACH_DATA_BIN)

I am wondering if there is a privilege problem here. I see here: dev.office.com/docs/add-ins/outlook/understanding-outlook-add-in-permissions that there are Outlook add-in permissions and that if I did not ReadWriteItem access then this could fail. I do not know how or where this is set though. They mention about it being set in the manifest but I do not see where I can do that.

I am using Visual Studio Community 2015.

B. Leslie
  • 165
  • 10

1 Answers1

3

Outlook Object Model cannot retrieve large binary or string MAPI properties using PropertyAccessor.GetProperty. On the low level (Extended MAPI, C++ or Delphi only), IMAPIProp::GetProps() does not work for the large PT_STING8 / PT_UNICODE / PT_BINARY properties. They must be opened as IStream (IMAPIProp::OpenProperty(PR_ATTACH_DATA_BIN, IIS_IStream, ...)). If using Redemption (I am its author) is an option, its attachment objects expose AsText, AsArray, AsStream, etc properties.

set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
set item = Session.GetMessageFromID(Application.ActiveExplorer.Selection(1).EntryID)
for each attach in item.Attachments
    MsgBox attach.AsText
next
Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
  • Thanks for the answer but at this point I think my problem is more basic. In my test the attachment was a small text file so I think I should be able to get it PropertyAccessor.GetProperty() although in the end I will need to use something else because of the size limitation. If I sue attachment.SaveAsFile() I also get an exception telling me I do not have appropriate permission to perform this operation. MSVS and C# is not my native development environment and so I suspect there is something very basic I am missing. – B. Leslie Oct 21 '16 at 14:16
  • What is the value of the Attachment.Type property? Take a look at the message with OutlookSpy (http://www.dimastr.com/outspy/)? Select the message, click IMessage button, go to the GetAttachmentTable tab, double click on the attachment entry. Do you see the PR_ATTACH_DATA_BIN property? – Dmitry Streblechenko Oct 21 '16 at 15:06
  • The PR_ATTACH_TYPE = 7 and there is a PR_ATTACH_DATA_BIN property. – B. Leslie Oct 21 '16 at 16:44
  • PR_ATTACH_TYPE = 7 is the new ATTACH_BY_WEB_REF, which is for the new OneDrive web attachments. Are you sure PR_ATTACH_DATA_BIN is present and you can see its value? When you save an attachment like that in Outlook 2016, it creates a *.url file pointing to a location from PR_ATTACH_LONG_PATHNAME_W. – Dmitry Streblechenko Oct 21 '16 at 17:47
  • PR_ATTACH_DATA_BIN is there and it contains the content of the attached file. There is no PR_ATTACH_LONG_PATHNAME_W though. – B. Leslie Oct 21 '16 at 18:14
  • Does the script above work if you install Redemption? – Dmitry Streblechenko Oct 21 '16 at 19:18
  • From inside the 'send' event handler where should I get the EntryID, ActiveExplorer seems to be not valid from this context. The EntryID in Outlook.MailItem is nil. – B. Leslie Oct 21 '16 at 22:07
  • Why do you need the entry id? Did you call MailItem.Save? – Dmitry Streblechenko Oct 21 '16 at 22:09
  • I am trying to get the example shown here: https://msdn.microsoft.com/en-us/library/office/hh290849.aspx to work. The code is called when the mail is sent. I do not call 'save' any where. I wanted the entry id because that appears to be what you were getting in this statement: item = Session.GetMessageFromID(Application.ActiveExplorer.Selection(1).EntryID). – B. Leslie Oct 21 '16 at 22:49
  • If I add a mailItem.save() then it works! Well that only took me a few days. :( – B. Leslie Oct 21 '16 at 23:00
  • The example used the currently selected item as a test. If you already have an Outlook item, you can replace Application.ActiveExplorer.Selection(1).EntryID with YouMailItem.Entry. Or you can use GetRDOObjectFromOutlookObject and pass your mail item. You will still need to call MailItem.Save if the item is unsaved. – Dmitry Streblechenko Oct 21 '16 at 23:07