I recently had an opportunity to work with Exchange server having created an ExtJs/Ext.Net based email client for Exchange. And I used the Exchange Web Services Managed API for .NET to interface with the Exchange server itself.
One of the aspects of the email client was downloading email attachments. I could not find anything on web that explained downloading attachments through the EWS Managed API (though there are examples for other interfaces used to interact with Exchange). And the MSDN documentation for the API is still not as mature as other MSDN documentation (without a surprise as the API itself is under development).
So, after having played around a little, I found my way out for downloading the attachments.
You need to know the EmailMessage UniqueId as well as the desired Attachment’s Id to open a System.IO.Stream containing the contents of the attachment. And then you can do anything with this Stream, like saving it as a file on the server, or sending its contents to the client.
Here’s the interesting part of the code for the same. The code opens (loads) an attachment whose Email UniqueId and Attachment Id are known (through a previous call to the Exchange probably), and then sends the Attachment content to a http client for downloading:
{syntaxhighlighter brush: csharp;fontsize: 100; first-line: 1; }//Instantize a new ExchangeService instance with the desired parameters here.
ExchangeService service=context.getExchangeService();
//Bind to the email message with known id.
EmailMessage m=EmailMessage.Bind(service, new ItemId(mailId), new PropertySet(EmailMessageSchema.Attachments));
//Figure out the desired attachment.
FileAttachment a=null;
foreach (Attachment at in m.Attachments)
{
if (at.Id.Equals(attachmentId))
{
a = (FileAttachment) at;
break;
}
}
//Load the attachment in memory from Exchange.
MemoryStream stream=new MemoryStream();
a.Load(stream);
StreamReader reader=new StreamReader(stream);
stream.Seek(0, SeekOrigin.Begin);
//Send the attachment to client.
HttpResponse response=context.Response;
response.Clear();
response.Charset = “”;
response.ContentType = type;
response.AddHeader(“Content-Disposition”, “attachment; filename=” + name);
response.CacheControl = “private”;
response.AddHeader(“Pragma”, “no-cache”);
response.Cache.SetExpires(DateTime.Now.AddDays(-100));
byte[]bytes=stream.GetBuffer();
response.BinaryWrite(bytes);
try
{
response.Flush();
response.End();
response.Close();
}
catch (Exception) { }{/syntaxhighlighter}
This is mostly boilerplate code that you can easily move to a generic .ashx handler to be able to download attachments.
One such handler is attached with this post that expects the EmailMessage UniqueId, Attachment Id, Attachment Mime Type and Name as request parameters and send the desired attachment to the client for downloading.
Hi. You’ll run into a HUGE memory overhead on server side using this code. The thing is EWS transfers attachment via bytearray parameter, which, in turn, in plain web services, which exchange uses, will be base64-encoded, and require LOTS of RAM to decode. You’ll have to write you own custom HttpWebRequest-based wrapper to call attachment download method (EWS->your server).
Hi Rahul,
This is great, but how can you get the images (jpg, gif) which are in the body of a Message?
Thanks,
MASSIMO
your code helped me figure out how to download the attachments!
But, I’m non clear where the “context.getExchangeService(); ” is comming from and specifically what’s needed on line 25 “HttpResponse response=context.Response; “
Can you provide the code for the Context Class you are using?
Chuck
Hi Rahul
I have used your code to download attachment. But I am getting Casting issue.
{System.InvalidCastException: Unable to cast object of type ‘Microsoft.Exchange.WebServices.Data.ItemAttachment’ to type ‘Microsoft.Exchange.WebServices.Data.FileAttachment’.
}
can you please help me how you have cast the ItemAttachment to FileAttachment.
I will really appreciate your help.
Hi,
The above code to download file attachment works good for all the file type , except for zip file..
Can you suggest what to change in the above code for downloading the zip file
Hi great post quick question, have you try to export the email itself as text or pdf (including address from, address to, cc, bcc, email body) ?
I need to achive this but the only thing that I have found is to export it as eml but that does not help me.
Thank you very very much, correct me if I am wrong body will have all the info that I asked earlier correct?
From:
To:
CC:
BCC:
Subject:
Body
correct? So if I am correct I just need to get that string and pase to ItextSharp for example correct?