Sunday, June 07, 2009

Downloading Attachments and Exporting Email as eml files in the EWS Managed API using Powershell

A common and useful thing you may want to do in Powershell when working with Exchange Email automation is to download an attachment. When working with Exchange Web Services you first need to use a GetItem operation to work out what attachments are on a message then use a GetAttachment operation which returns a Byte Array of each attachments content. So all you need to do with this Byte array is write it out to a file using the System.IO.FileStream Class.

To do this you first need a message object that you would normally get doing a GetItem operation in EWS in the managed API its just one line once you know the MessageID. Eg

$msMessage = [Microsoft.Exchange.WebServices.Data.EmailMessage]::Bind($service,$MessageID)


Once you have the message object you will have a list of attachments and the attachmentID you need to make a GetAttachment operations. Again this is pretty easy to do using the Managed API which extrapolates the GetAttachment operation as the load method on an attachment object.

$fileName = “C:\temp”
foreach($attach in $msMessage.Attachments){
$attach.Load()
$fiFile = new-object System.IO.FileStream(($fppath + “\” + $attach.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($attach.Content, 0, $attach.Content.Length)
$fiFile.Close()
write-host "Downloaded Attachment : " + (($fppath + “\” + $attach.Name.ToString())
}


In Exchange Web Services you have the ability to export the whole message in a serialized EML format (this is different from a Compound message format msg file which contains all the Mapi properties related to the rich types of the Exchange store). To do this when you do the original Get-Item operation request for the message you need to make sure you also request the MIME content of the message. This MIME content will contain the RFC serialized copy of the message which you can write out to a file. Eg

$psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ItemSchema]::MimeContent)
$msMessage = [Microsoft.Exchange.WebServices.Data.EmailMessage]::Bind($service,$MessageID,$psPropset)
Then similar to the above attachment example you can write that MIME content out to filestream. Eg
$fileName = “C:\temp\exportedmail.eml”
$fiFile = new-object System.IO.FileStream($fileName, [System.IO.FileMode]::Create) $fiFile.Write($msMessage.MimeContent.Content, 0,$msMessage.MimeContent.Content.Length)
$fiFile.Close()