HOWTO: EWS: Use GetAttachment to download attachments off Mail/Appointment


I have fallen for exchange web services. There are endless possibilities with exchange web services, and product group is still working to make it even better.


Today I have created a neat sample to download attachments off Exchange Server


Sample: DownloadAttachments


Input Params: itemID , folder


public void DownloadAttachments(string itemID,string folder)


{


ExchangeServiceBinding esb = new ExchangeServiceBinding();


esb.AllowAutoRedirect = true;


esb.Credentials = new System.Net.NetworkCredential(“USERNAME”, “PASSWORD”, “DOMAIN”);


esb.Url = “http://your-cas-server/ews/exchange.asmx”;


//first we need to get the attachment IDs for the item so we will need to make a GetItem call first


//specify the conetent that we want to retrieve


PathToUnindexedFieldType[] ptufta = new PathToUnindexedFieldType[2];


ptufta[0] = new PathToUnindexedFieldType();


ptufta[0].FieldURI = UnindexedFieldURIType.itemAttachments;


ptufta[1] = new PathToUnindexedFieldType();


ptufta[1].FieldURI = UnindexedFieldURIType.itemHasAttachments;


ItemResponseShapeType irst = new ItemResponseShapeType();


irst.BaseShape = DefaultShapeNamesType.IdOnly;


irst.AdditionalProperties = ptufta;


ItemIdType[] biita = new ItemIdType[1];


biita[0] = new ItemIdType();


biita[0].Id = itemID;


//get the items


GetItemType git = new GetItemType();


git.ItemShape = irst;


git.ItemIds = biita;


GetItemResponseType girt = esb.GetItem(git);


if (girt.ResponseMessages.Items[0].ResponseClass != ResponseClassType.Success)


return;


//now that we have the attachment IDs let’s request the atthacments and save them to disk


ItemType MsgItem = ((ItemInfoResponseMessageType)girt.ResponseMessages.Items[0]).Items.Items[0];


AttachmentResponseShapeType arst = null;


AttachmentIdType[] aita = null;


if (true == MsgItem.HasAttachments)


{


//create the attachment shape; we want the mime contnet just in case this is an message item so that we can save to disk


arst = new AttachmentResponseShapeType();


arst.IncludeMimeContent = true;


arst.IncludeMimeContentSpecified = true;


//create an array of attachment ids that we want to request


aita = new AttachmentIdType[MsgItem.Attachments.Length];


for (int i = 0; i < MsgItem.Attachments.Length; i++)


{


aita[i] = new AttachmentIdType();


aita[i].Id = MsgItem.Attachments[i].AttachmentId.Id;


}


}


//create a GetAttachment object for the GetAttachment operation


GetAttachmentType gat = new GetAttachmentType();


gat.AttachmentIds = aita;


gat.AttachmentShape = arst;


GetAttachmentResponseType gart = esb.GetAttachment(gat);


//save each attachment to disk


foreach (AttachmentInfoResponseMessageType Attachment in gart.ResponseMessages.Items)


{


switch (Attachment.Attachments[0].GetType().Name)


{


//attachments can be of type FileAttachmentType or ItemAttachmentType


//so we need to figure out which type we have before we manipulate it


case “FileAttachmentType”:


//save to disk


FileAttachmentType TheFileAttachment = (FileAttachmentType)Attachment.Attachments[0];


using (Stream FileToDisk = new FileStream(folder + @”\” + Attachment.Attachments[0].Name, FileMode.Create))


{


FileToDisk.Write(TheFileAttachment.Content, 0,


TheFileAttachment.Content.Length);


FileToDisk.Flush();


FileToDisk.Close();


}


break;


case “ItemAttachmentType”:


//save to disk


ItemType TheItemAttachment = ((ItemAttachmentType)Attachment.Attachments[0]).Item;


using (Stream FileToDisk = new FileStream(folder + @”.\” + Attachment.Attachments[0].Name + “.eml”, FileMode.Create))


{


byte[] ContentBytes = System.Convert.FromBase64String(TheItemAttachment.MimeContent.Value);


FileToDisk.Write(ContentBytes, 0,


ContentBytes.Length);


FileToDisk.Flush();


FileToDisk.Close();


}


break;


default:


break;


}


}


}


 


Keywords: GetAttachment, download attachments, exchange web services, exchange 2007

Comments (17)

  1. Bob says:

    thanks for your article…..

    That’s what i want

  2. sanghoon Kim says:

    How to get in-line Image in message body?

    this is in-line attachment (below attid0):

    ABXJDUMwrUFS6nSbLzbeiwhAAAOWa8RAAAJ&attcnt=1&attid0=EACcF5TnxIIgT4qPQ2X5OYSL

    this is attachmentID

    AAMkADU4ZjI3NThjLTg0NGItNGQ5Yy1hMTUwLTdiMDdiZGRiNGNjZgBGAAAAAADSY2dC6xL/Qoj/1NydCzNpBwAYqlXZi4eoQJgtpMlhUahKAAACsSUlAABXJDUMwrUFS6nSbLzbeiwhAAAOWa8RAAABEgAQAJwXlOfEgiBPio9DZfk5hIs

    please teach me how get in-line image in messagebody using Exchange Web Service

  3. hweber says:

    How can I get the from-email-address?

    The GetItemResponse include following tags,

    but I can’t find getter methods for that:

             <Sender>

               <Mailbox>

                 <Name>Name</Name>

                 <EmailAddress>name@test.com</EmailAddress>

                 <RoutingType>SMTP</RoutingType>

               </Mailbox>

             </Sender>

             <From>

               <Mailbox>

                 <Name>Name</Name>

                 <EmailAddress>Name@test.com</EmailAddress>

                 <RoutingType>SMTP</RoutingType>

               </Mailbox>

  4. JD says:

    Great article… How are you obtaining the itemID that you are passing in.  I’ve tried numerous ID’s that I’m getting from the message which all return a malformedID response code.

  5. Vikas Verma says:

    The itemId is unique Base64 encoded string value, which represents a unique item in store. You can use FindItem to find a particular item in store and then call GetItem on the ItemID returned by that FindItem call.

    Refer to the following post which has sample code for GetFolder, FindItem, GetItem and how to use restrictions with FindItem

    http://blogs.msdn.com/vikas/archive/2007/07/27/howto-getfolder-finditem-restriction-getitem.aspx

  6. Rambabu says:

    Friends, I am new to the world of exchange server 2007, can anyone suggest me that how can I proceede  to fetch mailbox details (Subject / has attachments, if yes attachment details..) Thanks.

  7. This was EXACTLY what I needed!

    Thank You A Million!!

    You are a genius!

  8. John Granade says:

    This code works great unless there’s a inline image (i.e. signature logo).  But how can I detect if it’s an inline image or not.  The book inside Microsoft Exchange Server 2007 Web Services says that Exchange Web Services doesn’t provide a way to determine the visibility of an attachment.  What’s the right way to handle this so we can get all attachments?

  9. Jeff says:

    Just had to say thank you. Wish I found this page 4 hours ago!!

  10. Kobe says:

    I always get following error when i try to use this method: "The request failed with HTTP status 403: Forbidden"

    Do you know if I’m doing something wrong or passing through the wrong ID? I tried with

    *DownloadAttachments(mt.Attachments[0].AttachmentId.Id, @"c:temp");

    *DownloadAttachments(it.ItemId.Id, @"c:temp");

    But always the same error

  11. Ralf Purr says:

    @Kobe: Did you use https://… to connect to your Exchange server ?

    @Vikas: Nice article, works great! But the code indeed fails if inline attachments are detected, because the MsgItem.HasAttachments is FALSE. So the attachment id is not defined and esb.GetAttachment(gat) fails.

    I’ll try to fix this but I am not sure wether I understand EWS good enough to achieve this.

    KR,

    Ralf

  12. Jeremy says:

    Great! Had the information I was after. Thanks!

  13. Download Attachment link is not working..

  14. Philip says:

    Hi,

    I am using EWS with SearchFilterCollection, and the Inbox I am checking should have 4 emails that are in scope, 3 with 0, 1, or multiple file attachments, and 1 with an item attachment.

    My trouble is that when I apply my searchfilter (> searchFilterCollection.Add(new SearchFilter.IsEqualTo(EmailMessageSchema.HasAttachments, true)); <) I don't get the one with the email <Item> attachment

    Is there a special searchFilter for this?

  15. Philip says:

    I am trying to use your code with Exchange 2010/EWS, on c#, and the ItemType is not recognized:

    This line won't compile:

    ItemType TheItemAttachment = ((ItemAttachmentType)Attachment.Attachments[0]).Item;

    what could I do to fix this?

  16. Ger83 says:

    Hi Vikas, This was a great help. Unfotunetaly the item I am testing with is a valid .msg attachment which you can open and read the email, but the TheItemAttachment.MimeContent is null. All the other properties are populated (body, subject, from etc). Any ideas how I can get this ItemType to be saved to disc then, since its MimeContent is null?

  17. chandrasekhar ravuri says:

    unable to save attachments exchange server 2007 sp1 using c#.

    // logged on to the domain.

                   service.Credentials = new WebCredentials(AppConfigSettings.EmailAccountName, AppConfigSettings.Password, AppConfigSettings.ExchangeDomain);

                   service.Url = new Uri(AppConfigSettings.ExchangeWebServiceLink);

                   ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

                  // FindItems();

                   FindItemsResults<Item> findResults = service.FindItems(

                   WellKnownFolderName.Inbox,

                   new ItemView(30000));

                   foreach (Item item in findResults.Items)

                   {

                       item.Load();

                       if (item.HasAttachments)

                       {

                           foreach (var i in item.Attachments)

                           {

                               FileAttachment fileAttachment = (FileAttachment)item.Attachments[0];                          

                               fileAttachment.Load("C:\temp\" + fileAttachment.Name);

                           }

                       }

    getting exception as "The request failed. Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."