Working With Exchange Web service (EWS)

Introduction

Remotely working with Exchange Server /Outlook using Exchange Web Service (EWS)- There are many article how to process using EWS managed API but there are very less article of how we can actually do it remotely  using exchange web service.

EWS Managed API works only on exchange server. If you are looking for remote processing here is solution. 

Following are steps involved -

  1. Creating An Instance Of Exchange Web Service (EWS)

  2. Process Unread Email Attachment

  3. Iterate Through Attachments

  4. Process Email Attachments

  5. Change Status of Emails From ‘Unread’ to ‘Read’

How It Works/Using Code :
  1. Creating An Instance Of Exchange Web Service (EWS)

First you will need to add web service to project then you will get instance of ExchangeServiceBinding() . You can initiate/invoke an instance of EWS using following code :

/// 
/// Set all required configuration parameters
/// 
public void Initialize()
{
 try
 {
 // you can also get if from configuration file

 EmailAddress = "MyEmail@MyDomain.Com"; //AppConfig.EmailAddress;

 UserName = "MyUserName"; //AppConfig.UserName;

 Password = "MyPassword"; //AppConfig.Password;

 Domain = "myDomain"; //AppConfig.Domain; 

 Authenticate = "basic"; //AppConfig.Authenticate;

 EWS_URL = "https://MyExchangeWebServiceDomain/ews/Exchange.asmx"; //AppConfig.EWS_URL;

 RequestOperation = "ServiceRequestOperation"; //AppConfig.RequestOperation;

 ResponseOperation = "ServiceResponseOperation"; //AppConfig.ResponseOperation;

 NetworkCredential nc = null;

 if (Authenticate == "Windows")

 {

 nc = System.Net.CredentialCache.DefaultNetworkCredentials;

 } else
 {

 nc = new NetworkCredential(UserName, Password, Domain);

 }

 esb.Url = EWS_URL;

 esb.Credentials = nc;

 } catch (Exception x) {
 //Write Exeption Handiling Code Here

 string exceptonMessage = x.Message;
 }
}
  1. Process Unread Email Attachment

Now that we have instantiated Exchange Web Service and then apply filter to process through folder and other filter criteria.

Here is sample code you can use :

 
public void ProcessUnReadEmailAttachments() {
 try {
 //Set all requred configuration parameters 
 this.Initialize(); //Click here for - how to create/initiate an instance of Exchange web service (EWS) in ASP.NET? 
 FindItemType findItemRequest = new FindItemType();
 // Setup the mailbox using the smtp address of the account wanted 
 var mailbox = new EmailAddressType {
 EmailAddress = EmailAddress
 };
 findItemRequest.Traversal = ItemQueryTraversalType.Shallow;
 // Define which item properties are returned in the response 
 ItemResponseShapeType itemProperties = new ItemResponseShapeType();
 itemProperties.BaseShape = DefaultShapeNamesType.AllProperties;
 findItemRequest.ItemShape = itemProperties; // Add properties shape to request 
 // Identify which folders to search to find items 
 //DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1]; 
 DistinguishedFolderIdType[] folderIDArray = new[] {
 new DistinguishedFolderIdType {
 Mailbox = mailbox
 }
 };
 folderIDArray[0] = new DistinguishedFolderIdType();
 folderIDArray[0].Id = DistinguishedFolderIdNameType.inbox;
 folderIDArray[0].Mailbox = mailbox;
 // Add folders to request 
 findItemRequest.ParentFolderIds = folderIDArray;
 //Create unread only restriction -------------------------- 
 RestrictionType restriction = new RestrictionType();
 IsEqualToType isEqualTo = new IsEqualToType();
 PathToUnindexedFieldType pathToFieldType = new PathToUnindexedFieldType();
 pathToFieldType.FieldURI = UnindexedFieldURIType.messageIsRead;
 FieldURIOrConstantType constantType = new FieldURIOrConstantType();
 ConstantValueType constantValueType = new ConstantValueType();
 constantValueType.Value = "0";
 constantType.Item = constantValueType;
 isEqualTo.Item = pathToFieldType;
 isEqualTo.FieldURIOrConstant = constantType;
 restriction.Item = isEqualTo;
 findItemRequest.Restriction = restriction;
 this.HttpStatus(RequestOperation, findItemRequest, typeof (FindItemType));
 // ------------- Send the request and get the response 
 FindItemResponseType findItemResponse = esb.FindItem(findItemRequest);
 this.HttpStatus(ResponseOperation, findItemResponse, typeof (FindItemResponseType));
 // ------------- read returned 
 FindItemResponseMessageType folder = (FindItemResponseMessageType) findItemResponse.ResponseMessages.Items[0];
 ArrayOfRealItemsType folderContents = new ArrayOfRealItemsType();
 folderContents = (ArrayOfRealItemsType) folder.RootFolder.Item;
 ItemType[] items = folderContents.Items;
 //string sText = ""; 
 if (items != null) {
 foreach(ItemType curItem in items) {
 //You can access email content here 
 //sText += "Subject: " + (curItem.Subject.Trim()) + " "; 
 //sText += "DisplayTo: " + (curItem.DisplayTo.Trim()) + " "; 
 //sText += "DateTimeReceived: " + (curItem.DateTimeReceived.TimeOfDay.ToString()) + " "; 
 //sText += "DateTimeReceived: " + (curItem.ItemClass.Trim()) + " "; 
 //sText += "\r\n"; 
 }
 }
 } catch (Exception x) {
 //Write Exeption Handiling Code Here 
 string exceptonMessage = x.Message;
 }
}
/// 
/// execte operation 
/// 
/// ServiceRequestOperation/ServiceResponceOperation 
/// executior object 
/// executior object type 
private void HttpStatus(string Operation, Object serviceObject, Type type) {
 //// ------------- GetAccessibilityObjectById the stream 
 using(StreamWriter myreqWriter = new StreamWriter(Logger.LOG_PATH + Operation + ".xml")) {
 XmlSerializer myReqSerializer = new XmlSerializer(type);
 myReqSerializer.Serialize(myreqWriter, serviceObject);
 }
}
  1. Iterate Through Attachments

We are going to see how to iterate through the attachments of  email.

for that we are going to use following code block where we are going to
pass instance of Exchange Service binding and item ID of email.



/// 
/// Get all items associated with email 
/// 
/// 
/// 
public void GetAttachmentsByItemID(ExchangeServiceBinding binding, string itemID)

{

 try

 {

 GetItemType getItemRequest = new GetItemType();

 ItemIdType[] items = new ItemIdType[1];

 items[0] = new ItemIdType();

 items[0].Id = itemID;

 getItemRequest.ItemIds = items;

 getItemRequest.ItemShape = new ItemResponseShapeType();

 getItemRequest.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;

 PathToUnindexedFieldType hasAttachPath = new PathToUnindexedFieldType();

 hasAttachPath.FieldURI = UnindexedFieldURIType.itemHasAttachments;

 PathToUnindexedFieldType attachmentsPath = new PathToUnindexedFieldType();

 attachmentsPath.FieldURI = UnindexedFieldURIType.itemAttachments;

 // Add additional properties? 

 getItemRequest.ItemShape.AdditionalProperties = new BasePathToElementType[] {

 hasAttachPath, attachmentsPath
 };

 GetItemResponseType getItemResponse = binding.GetItem(getItemRequest);

 ItemInfoResponseMessageType getItemResponseMessage = getItemResponse.ResponseMessages.Items[0] as ItemInfoResponseMessageType;

 if (getItemResponseMessage.ResponseCode == ResponseCodeType.NoError)

 {

 ItemType item = getItemResponseMessage.Items.Items[0];

 MessageType messageType = item as MessageType;

 SingleRecipientType singleRecipientType = messageType.From;

 // Don't rely on HasAttachments - It does not mean what you thing it would. 

 if ((item.Attachments != null) && (item.Attachments.Length > 0))

 {

 FileAttachmentType almostAnAttachment;

 for (int attachmentIndex = 0; attachmentIndex < item.Attachments.Length; attachmentIndex++)

 {

 almostAnAttachment = item.Attachments[attachmentIndex] as FileAttachmentType;

 //You can add filter if you are looking for specific type of attachement. In this example I am filtering only .xml files. 

 if (almostAnAttachment != null && string.Equals(almostAnAttachment.Name.ToLower().Substring(almostAnAttachment.Name.ToLower().Length - 4, 4), ".xml"))

 {

 //ProcessAttachmentByAttachmentItemID(binding, ((RequestAttachmentIdType)(almostAnAttachment.AttachmentId)).Id); 

 //SetReadFlagForMessage(item.ItemId); 

 }

 }

 }

 }

 } catch (Exception x)

 {

 //Write Exception Handling Code Here 

 string exceptonMessage = x.Message;

 }

}
  1. Process Email Attachment

Now we know how to filter attachments based on type, Here will see how we can process xml file in outlook email.


/// 
/// Here is code to process attachmentre 
/// 
/// 
/// 
private static void ProcessAttachmentByAttachmentItemID(ExchangeServiceBinding esb, string itemID)

{

 // Create the request. 

 GetAttachmentType request = new GetAttachmentType();

 // Create the response shape. 

 AttachmentResponseShapeType responseShape = new AttachmentResponseShapeType();

 responseShape.BodyType = BodyTypeResponseType.Text;

 responseShape.BodyTypeSpecified = true;

 // Add the response shape to the request. 

 request.AttachmentShape = responseShape;

 // Identify the attachment IDs to get. 

 RequestAttachmentIdType[] ids = new RequestAttachmentIdType[1];

 ids[0] = new RequestAttachmentIdType();

 ids[0].Id = itemID;

 // Add the attachment IDs to the request. 

 request.AttachmentIds = ids;

 GetAttachmentResponseType response = esb.GetAttachment(request);

 ResponseMessageType[] rmta = response.ResponseMessages.Items;

 foreach(ResponseMessageType responseMessage in rmta)

 {

 AttachmentInfoResponseMessageType airmt = (responseMessage as AttachmentInfoResponseMessageType);

 AttachmentType[] attachments = airmt.Attachments;

 // Type check for item or file attachment. 

 foreach(AttachmentType attachment in attachments)

 {

 if (attachment is FileAttachmentType)

 {

 FileAttachmentType fat = (attachment as FileAttachmentType);

 // Assumes ASCII encoding. 

 //string myContent = ASCIIEncoding.ASCII.GetString(fat.Content); 

 string myContent = ASCIIEncoding.UTF8.GetString(fat.Content);

 //my Content is attachment content - you can download/write code here to save it into database 

 //SaveAttachmentContentInDatabase(myContent); 

 }

 // Attachment is item attachment. 
 else

 {

 ItemAttachmentType iat = (attachment as ItemAttachmentType);

 // TODO: Handle the item attachment. 

 }

 }

 }

}
  1. Change Status of Emails From ‘Unread’ to ‘Read’

Once email/attachment is processed you would like to mark as read (change status from ‘unread’ to ‘read’ )

Here will see how we can do that.


/// 
/// EWS code to update the IsRead flag, *ONLY* for MessageType 
/// 
/// email message/item id 
/// boolean value true- if it marked as read else false 
private static bool SetReadFlagForMessage(ItemIdType messageId)

{

 SetItemFieldType setField = new SetItemFieldType();

 MessageType message = new MessageType();

 // message.IsRead = false; 

 message.IsRead = true;

 message.IsReadSpecified = true;

 setField.Item1 = message;

 PathToUnindexedFieldType path = new PathToUnindexedFieldType();

 path.FieldURI = UnindexedFieldURIType.messageIsRead;

 setField.Item = path;

 ItemChangeType[] updatedItems = new ItemChangeType[1];

 updatedItems[0] = new ItemChangeType();

 updatedItems[0].Updates = new ItemChangeDescriptionType[1];

 updatedItems[0].Updates[0] = setField;

 ItemChangeDescriptionType[] updates = new ItemChangeDescriptionType[1];

 updates[0] = new ItemChangeDescriptionType();

 updates[0].Item = path;

 updatedItems[0].Item = new ItemIdType();

 ((ItemIdType) updatedItems[0].Item).Id = messageId.Id;

 ((ItemIdType) updatedItems[0].Item).ChangeKey = messageId.ChangeKey;

 UpdateItemType request = new UpdateItemType();

 request.ItemChanges = updatedItems;

 request.ConflictResolution = ConflictResolutionType.AutoResolve;

 request.MessageDisposition = MessageDispositionType.SaveOnly;

 request.MessageDispositionSpecified = true;

 request.SendMeetingInvitationsOrCancellations = CalendarItemUpdateOperationType.SendToChangedAndSaveCopy;

 request.SendMeetingInvitationsOrCancellationsSpecified = true;

 UpdateItemResponseType response = esb.UpdateItem(request);

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

 {

 return false;

 } else

 {

 return true;

 }

}

}

}


Thank you …Please like this article on social site if this worked for you… Coding is fun !!! Isn't it...