Share via


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 = "https://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

  • Anonymous
    November 04, 2007
    thanks for your article..... That's what i want

  • Anonymous
    January 22, 2008
    The comment has been removed

  • Anonymous
    January 29, 2008
    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>

  • Anonymous
    June 04, 2008
    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.

  • Anonymous
    June 09, 2008
    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

  • Anonymous
    December 11, 2008
    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.

  • Anonymous
    March 17, 2009
    This was EXACTLY what I needed! Thank You A Million!! You are a genius!

  • Anonymous
    April 20, 2009
    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?

  • Anonymous
    June 10, 2009
    Just had to say thank you. Wish I found this page 4 hours ago!!

  • Anonymous
    June 11, 2009
    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

  • Anonymous
    June 16, 2009
    The comment has been removed

  • Anonymous
    August 19, 2009
    Great! Had the information I was after. Thanks!

  • Anonymous
    November 28, 2012
    Download Attachment link is not working..

  • Anonymous
    April 13, 2014
    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?

  • Anonymous
    April 14, 2014
    The comment has been removed

  • Anonymous
    July 31, 2014
    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?

  • Anonymous
    December 10, 2015
    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&quot; + 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."