Click here to Skip to main content
15,861,168 members
Articles / Web Development / ASP.NET
Article

Programming with Exchange Server 2007 (EWS) - Part 3

Rate me:
Please Sign up or sign in to vote.
4.81/5 (22 votes)
1 Dec 2008CPOL3 min read 200.2K   50   51
This article is the third in a series on EWS, which explores Exchange Web Services.

Background

In my last article, I discussed how to read different folders like inbox, sent items etc., and also do a search on the basis of some criteria.

My previous articles on this series include:

  1. Programming with Exchange Server 2007 (EWS) - Part 1
  2. Programming with Exchange Server 2007 (EWS) - Part 2

In this part, first, I'll discuss reading the details of a mail from the inbox, and also cover the mystery behind extended properties. The key points are:

Introduction

Every mail is of type MessageType or is inherited from MessageType, so we can access all the items from the inbox as MessageType even mails related to Calendaring.

Reading Mails

To read the details of a mail, we need to use the GetItem API provided by EWS, as:

C#
public void GetSignalDetails(ItemIdType p_strItemId)
{
    GetItemType MailId = new GetItemType();
    GetItemResponseType mailResponse;
    string strMsg = string.Empty;

    MailId.ItemIds = new BaseItemIdType[] { idType };
    MailId.ItemShape = new ItemResponseShapeType();
    MailId.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;
    mailResponse = _esb.GetItem(MailId);
    ArrayOfResponseMessagesType arrMail = p_mailResponse.ResponseMessages;
    ResponseMessageType[] responseMessages = arrMail.Items;
    foreach (ResponseMessageType respmsg in responseMessages)
    {
        if (respmsg.ResponseClass == ResponseClassType.Error)
        {
            throw new Exception("Error: " + respmsg.MessageText);
        }
        else if (respmsg.ResponseClass == ResponseClassType.Warning)
        {
            throw new Exception("Error: " + respmsg.MessageText);
        }
        //check to determine whether the response message is correct type 
        if (respmsg is ItemInfoResponseMessageType)
        {
            ItemInfoResponseMessageType createItemResp = 
                     (respmsg as ItemInfoResponseMessageType);
            ArrayOfRealItemsType aorit = createItemResp.Items;
            foreach (MessageType myitem in aorit.Items)
            {
                string  strSubject = myMessage.Subject;
                if (myMessage.From != null)
                {
                       string strFrom = myMessage.From.Item.Name;
                }
                StringBuilder objTo = new StringBuilder();

                if (myMessage.ToRecipients != null)
                {
                    //To be checked only for single recipient
                    foreach (EmailAddressType email in myMessage.ToRecipients)
                    {
                        objTo.Append(email.Name + "[" + email.EmailAddress + "];");


                    }
                }
                StringBuilder objCC = new StringBuilder();

                if (myMessage.CcRecipients != null)
                {
                    //To be checked only for single recipient
                    foreach (EmailAddressType email in myMessage.CcRecipients)
                    {
                        objCC.Append(email.Name + "[" + email.EmailAddress + "];");
                    }
                }
                objSignalDetailsRow.MailBody = myMessage.Body.Value;
            }
            //Similarly we can read other properties
        }

In the same way, we can read mails related to Calendaring, which will be explored in subsequent articles.

Setting Read Mails as Read

There is a property of type bool for MessageType called isRead. The first time a mail comes to the inbox, we show it in bold because it is not read yet, but when the mail is read, we need to set the property isRead to true so that the next time we show it as normal. After successfully reading a mail, we need to update this property to true. We have an API UpdateItem to update any existing item. The code to accomplish this is as shown:

C#
public bool SetReadStatus(ItemIdType item)
{
    SetItemFieldType setField = new SetItemFieldType();
    PathToUnindexedFieldType path = new PathToUnindexedFieldType();

    MessageType message = new MessageType();
    message.IsRead = true;
    message.IsReadSpecified = true;
    setField.Item1 = message;
    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 = item.Id;
    ((ItemIdType)updatedItems[0].Item).ChangeKey = item.ChangeKey;
    UpdateItemType request = new UpdateItemType();
    request.ItemChanges = updatedItems;
    request.ConflictResolution = ConflictResolutionType.AutoResolve;
    request.MessageDisposition = MessageDispositionType.SaveOnly;
    request.MessageDispositionSpecified = true;

    UpdateItemResponseType response = _esb.UpdateItem(request);

    if (response.ResponseMessages.Items[0].ResponseClass != 
                         ResponseClassType.Success)
        return false;
    else
        return true;
}

Extended Properties - Intro

Extended properties are very important for us when we make custom mail applications because, let's say, in a mail, we have default properties in the MessageType item, and if we want a new property, let's say, Classification, for our custom application, then we need to use an extended property.

Extended Properties - How to set them

We can create and set a new property as an extended property at the time of making an instance of the class (i.e., when setting the properties of that class).

C#
MessageType p_objMessage=new p_objMessage();
p_objMessage.ExtendedProperty = new ExtendedPropertyType[1];

PathToExtendedFieldType pathClassification = new PathToExtendedFieldType();
pathClassification.DistinguishedPropertySetId =

DistinguishedPropertySetType.PublicStrings;
pathClassification.DistinguishedPropertySetIdSpecified = true;
pathClassification.PropertyName = "Classification";
pathClassification.PropertyType = MapiPropertyTypeType.String;
p_objMessage.ExtendedProperty[0] = new ExtendedPropertyType();
p_objMessage.ExtendedProperty[0].ExtendedFieldURI = pathClassification;
p_objMessage.ExtendedProperty[0].Item = msgRow.Classification;

Here, I am creating an extended property "Classification" for the MessageType object .This should be done at the time of setting the other properties of that object, after creating the object.

Extended Properties - How to read them

We have two scenarios here:

  • Reading it at the time of searching\reading all the items for folders.
  • Reading at the time of detailed reading.

For the first case: We first need to specify which property we want to read:

C#
PathToExtendedFieldType pathClassification = new PathToExtendedFieldType();
pathClassification.DistinguishedPropertySetId = 
          DistinguishedPropertySetType.PublicStrings;
pathClassification.DistinguishedPropertySetIdSpecified = true;
pathClassification.PropertyName = "Clasification";
pathClassification.PropertyType = MapiPropertyTypeType.String;

But for using this, we first need to create an object of type ItemResponseShapeType as shown below and set the BaseShape property:

C#
ItemResponseShapeType itemProperties = new ItemResponseShapeType();
// Use the Default shape for the response. 
itemProperties.BaseShape = DefaultShapeNamesType.Default;
itemProperties.AdditionalProperties = new BasePathToElementType[]
{ pathClassification };

And finally, we need to set this to the findRequest object, as:

C#
findRequest.ItemShape = itemProperties;

For the second case: we first need to read the details by using GetItem; then again, we need to call the EWS API for all the extended properties because we can't do it in one go. The code is as shown:

C#
public ExtendedPropertyType[] GetExtendedProperties(ItemIdType itemid)
{
    PathToExtendedFieldType pathClassification = new PathToExtendedFieldType();
    pathClassification.DistinguishedPropertySetId = 
       DistinguishedPropertySetType.PublicStrings;
    pathClassification.DistinguishedPropertySetIdSpecified = true;
    pathClassification.PropertyName = "Classification";
    pathClassification.PropertyType = MapiPropertyTypeType.String;


    GetItemType getExPropertiesRequest = new GetItemType();
    ItemIdType iiItemId = new ItemIdType();
    iiItemId = itemid;

    ItemResponseShapeType getResponseShape = new ItemResponseShapeType();
    getResponseShape.BaseShape = DefaultShapeNamesType.AllProperties;
    getResponseShape.IncludeMimeContent = true;
    getExPropertiesRequest.ItemShape = getResponseShape;

    getExPropertiesRequest.ItemShape.AdditionalProperties = 
                                     new BasePathToElementType[1];
    getExPropertiesRequest.ItemShape.AdditionalProperties[0] = pathClassification;


    getExPropertiesRequest.ItemIds = new ItemIdType[1];
    getExPropertiesRequest.ItemIds[0] = iiItemId;
    getExPropertiesRequest.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;

    GetItemResponseType giResponse = _esb.GetItem(getExPropertiesRequest);
    if (giResponse.ResponseMessages.Items[0].ResponseClass == ResponseClassType.Error)
    {
        throw new Exception("Error: " +
        giResponse.ResponseMessages.Items[0].MessageText);
    }
    else
    {
        ItemInfoResponseMessageType rmResponseMessage = 
             giResponse.ResponseMessages.Items[0] as ItemInfoResponseMessageType;

        if (rmResponseMessage.Items.Items[0].ExtendedProperty != null)
        {
            MessageType message = rmResponseMessage.Items.Items[0] as MessageType;
            return (message.ExtendedProperty);
        }
        else
        {
            return null;
        }
    }
}

Note: In this article, _esb is the object of ExchangeService is as in my earlier articles of the series.

I hope this series is useful for all those who are working on EWS. Suggestions are highly appreciated. In the next article, I'll start exploring the Calendaring provided by EWS.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
Brij is a 3-times Microsoft MVP in ASP.NET/IIS Category and a passionate .NET developer. More than 6 years of experience in IT field, currently serving a MNC as a Tech Lead/Architect.

He is a very passionate .NET developer and have expertise over Web technologies like ASP.NET 2.0/3.5/4.0, jQuery, JSON, Javascript, IIS and related technologies. He is also a Exchange Server (EWS) Specialist. He has great experience in design patterns and N-Tier Architecture.

He is also certified as Microsoft Certified Technologies Specialist-ASP.NET and Microsoft Certified Technologies Specialist-WCF in .NET 4.0. He has also received several awards at various forums and his various articles got listed as "Article of the day" at ASP.NET Microsoft Official Website www.asp.net.

He has done MCA from NIT Durgapur and completed his graduation from Lucknow University.

Learning new technologies and sharing knowledge excites him most. Blogging, solving problems at various forums, helping people, keeps him busy entire day.


Visit his Blog: Code Wala

Area of Expertise :
C#, ASP.NET 2.0,3.5,4.0, AJAX, JQuery, JSON, XML, XSLT, ADO.Net, WCF, Active Directory, Exchange Server 2007 (EWS), Java script, Web Services ,Win services, DotnetNuke, WSS 3.0,Sharepoint Designer, SQL Server 2000/2005/2008

Comments and Discussions

 
Questionhow to get attchment with message [modified] Pin
HedgehogDworkin12-Feb-09 6:43
HedgehogDworkin12-Feb-09 6:43 
Generalarticle is nice but... Pin
HedgehogDworkin12-Feb-09 3:33
HedgehogDworkin12-Feb-09 3:33 
GeneralRe: article is nice but... Pin
Brij15-Feb-09 3:49
mentorBrij15-Feb-09 3:49 
GeneralRe: article is nice but... Pin
darkfoxy24-Sep-09 2:40
darkfoxy24-Sep-09 2:40 
GeneralRe: article is nice but... Pin
Brij26-Sep-09 19:53
mentorBrij26-Sep-09 19:53 
GeneralAll Extended Properties Pin
Daxel12330-Jan-09 6:12
Daxel12330-Jan-09 6:12 
GeneralRe: All Extended Properties Pin
Brij15-Feb-09 3:52
mentorBrij15-Feb-09 3:52 
GeneralNeed help regarding "Extraction of MessageType from Drafts folder (with itemId string as input)" Pin
Member 54474312-Dec-08 6:20
Member 54474312-Dec-08 6:20 
Hi Brij,
I've gone through your Exchange Server Article and I really appreciate your effort as it is very new domain to cover and there is not much help available over internet.

I am also working in EWS 2007 and I am struck with one issue that is retrieval of MessageType
from Drafts folder with itemId as input string.

a) Right now I've working code to get MessageType from inbox.
b) I pass a string ID as input string and my code works fine, but when I pass a string of an
"item" from Drafts folder it doesn't work. (Looks that the below code only deals with Inbox
folder items, but not from Drafts folder)

Below is my code for Inbox items.

///////////////////////////////////////////////////////////////////////////////////
mailId = "AAANAHRlc3RAZXgubG9jYWwARgAAAAAARDWn3wZYfkW2CByA4LXDOQcA1Ua+wk0wDEqNVd+xZtq3wQAAG3JxxwAA1Ua+wk0wDEqNVd+xZtq3wQAc4vuBNwAA";

public String openEmailById(String mailId)
{
mailId = mailId.Replace(' ', '+');
ExchangeServiceBinding esb = new ExchangeServiceBinding();
esb.Credentials = new NetworkCredential("Test", "12345", "Ex.Local");
esb.Url = @Commons.getExchangeServerURL();

// Create the request.
GetItemType request = new GetItemType();
// Create the response shape.
ItemResponseShapeType responseShape = new ItemResponseShapeType();
responseShape.BodyType = BodyTypeResponseType.HTML;
responseShape.BaseShape = DefaultShapeNamesType.Default;
// Add the response shape to the request.
request.ItemShape = responseShape;

// Identify the items to get.
ItemIdType[] items = new ItemIdType[1];
items[0] = new ItemIdType();
items[0].Id = mailId;
request.ItemIds = items;

try
{
// Send the request and get the response.
GetItemResponseType resp = esb.GetItem(request);
ArrayOfResponseMessagesType aormt = resp.ResponseMessages;
ResponseMessageType[] rmta = aormt.Items;

Mail myMail = new Mail();

foreach (ResponseMessageType rmt in rmta)
{
ItemInfoResponseMessageType iirmt = (rmt as ItemInfoResponseMessageType);
ArrayOfRealItemsType aorit = iirmt.Items;
ItemType[] myItems = aorit.Items;
//Intialize the thread List of my Items
if (myItems.Length > 0)
myMail.threads = new List<mailthread>();
foreach (ItemType it in myItems)
{
// Check whether it is an e-mail.
if (it is MessageType)
{
MessageType inboxMessage = (MessageType)it;

MailThread myMailThread = new MailThread();
return inboxMessage.ItemId.ChangeKey.ToString();
myMailThread.id = inboxMessage.ItemId.Id;
//if last Item then send the body contents in HTML
myMailThread.to = Commons.getCommaSeperatedEmails(inboxMessage.ToRecipients);
myMailThread.cc = Commons.getCommaSeperatedEmails(inboxMessage.CcRecipients);
myMailThread.bcc = Commons.getCommaSeperatedEmails(inboxMessage.BccRecipients);

myMailThread.subject = Commons.getDisplayString(inboxMessage.Subject);

return myMailThread.subject + " ---- " + myMailThread.bcc + " st "+ inboxMessage.Sensitivity;

myMailThread.attachments.count = (inboxMessage.HasAttachments) ? inboxMessage.Attachments.Length : 0;
myMailThread.date = inboxMessage.DateTimeCreated.ToLocalTime().ToString("F");
myMailThread.from = inboxMessage.From.Item.EmailAddress;
myMailThread.fromName = inboxMessage.From.Item.Name;
if (inboxMessage.Body != null && inboxMessage.Body.Value != null)
myMailThread.body = inboxMessage.Body.Value.ToString();

myMail.threads.Add(myMailThread);

}

}
}

return "{\"mail\":" + JsonMapper.ToJson(myMail) + "}";
}
catch (Exception e)
{
//throw new Exception("GetItem failed");
return e.ToString();
}
}
/////////////////////////////////////////////////////////////////////////////

Kindly help me with this, I'll really appreciate that.

Regards,
san
GeneralRe: Need help regarding "Extraction of MessageType from Drafts folder (with itemId string as input)" Pin
Brij12-Dec-08 20:21
mentorBrij12-Dec-08 20:21 
Generalhooking into exchange events Pin
Yang Yu4-Dec-08 1:29
Yang Yu4-Dec-08 1:29 
AnswerRe: hooking into exchange events Pin
Brij4-Dec-08 17:51
mentorBrij4-Dec-08 17:51 
GeneralGreat Series Pin
Ricky072-Dec-08 3:37
Ricky072-Dec-08 3:37 
GeneralMy vote of 1 Pin
terragenegeystur1-Dec-08 20:35
terragenegeystur1-Dec-08 20:35 
GeneralRe: My vote of 1 Pin
Brij1-Dec-08 20:55
mentorBrij1-Dec-08 20:55 
GeneralExcellent Series Pin
bbm2k31-Dec-08 19:07
bbm2k31-Dec-08 19:07 
GeneralWaiting for Next article. Pin
Abhijit Jana1-Dec-08 19:02
professionalAbhijit Jana1-Dec-08 19:02 
GeneralRe: Waiting for Next article. Pin
Kotte_SDS19-Mar-11 18:29
Kotte_SDS19-Mar-11 18:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.