EWS: Why does not FindItem return all the fields you expected?
FindItem is one of the very useful & powerful functions available in EWS. You can use it on any folder to find any type of item with as complex restrictions as you can think of.
But wait… before you assume you can get everything that you would get from GetItem, It is not truth!
FindItem only returns summary information & following fields are returned ONLY by GetItem and never by FindItem.
Attachments, Body, Categories, CcRecipients, InternetMessageHeaders, ReplyTo, ResponseObjects, ToRecipients, BccRecipients
I have also discovered that although Sender is returned by FindItem, but you only get display name for sender and EmailAddressType & RoutingType are set to null. I asked myself why not… and following is the response I got from people who decided to design it that way.
"Returning the e-mail address to clients would not add much network traffic from the client to the CAS server, it would be a tremendous performance problem for the server itself. FindItem's whole point is to be an extremely efficient operation for the server – because it's potentially returning very large tables of data. The data returned by a FindItem call is often used to display a view (such as a list of items, like in Outlook). Returning the e-mail address as part of FindItem would require one Active Directory (AD) lookup per recipient, which would result in insufficient performance for FindItem. Beyond that, applications that display a table of information would typically only show the display name of a recipient (as Outlook does in the item listing). So, all that put together is why we require clients to call GetItem to find full recipient information. "
References:
https://msdn2.microsoft.com/en-us/library/bb508824.aspx
Comments
Anonymous
August 04, 2009
In this post it indicated that - "I have also discovered that although Sender is returned by FindItem ..." I could not find the sender info though in my code below // Send the request and get the response by using the binding object. FindItemResponseType response = binding.FindItem(request); ..... // now the message body is here BodyType messageBody = inboxItem.Body; // now we have the mailbox item's body property, get the email text string content = messageBody.Value; // This is the emaill body in html string cleanContent = CleanUpHtml(content); emailMessage = new EmailMessage(); emailMessage.Subject = inboxItem.Subject; emailMessage.ReceivedDate = inboxItem.DateTimeReceived.ToString(); // TODO: emailMessage.MessageBody = cleanContent; emailMessage.From = inboxItem.LastModifiedName; // TODO: Is this "from"? emailMessage.ItemID = inboxItem.ItemId.Id; emailMessage.ChangeKey = inboxItem.ItemId.ChangeKey; emailMessages.Add(emailMessage);Anonymous
August 05, 2009
From is a property of EmailAddress Type and you cannot assign a string name to it.. change your code to something similar to this. EmailAddress emailFrom = new EmailAddress(); emailFrom.Address = "abc@xyz.com"; emailFrom.Name = "ABC XYZ"; emailMessage.From = emailFrom; Disclaimer: I have not written or compiled this code in Visual Studio so cannot verify if it will compile or not, ideally it should.Anonymous
August 05, 2009
Thanks for your reply. I think I did not make myself clear about my question. I got a hold of a message through the following code using FindItem and GetItem. I got the message body, subject, and other properties; but the email "from" property is no where to be found. I need to know how to get the "From" (sender) property of a mail. I really appreciate you help! // Send the request and get the response by using the binding object. FindItemResponseType response = binding.FindItem(request); foreach (FindItemResponseMessageType responseMessage in response.ResponseMessages.Items) { if (responseMessage.ResponseClass == ResponseClassType.Success) { ArrayOfRealItemsType mailboxItems = (ArrayOfRealItemsType)responseMessage.RootFolder.Item; for (int itemCount = 0; itemCount < mailboxItems.Items.Length; itemCount++) { ItemType inboxItem = mailboxItems.Items[itemCount]; // call GetItem on each ItemId to retrieve the item's body property and any attachmentIds // Form the GetItem request GetItemType getItemRequest = new GetItemType(); getItemRequest.ItemShape = new ItemResponseShapeType(); // All properties on a GetItem request will return the message body getItemRequest.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties; getItemRequest.ItemIds = new BaseItemIdType[1]; getItemRequest.ItemIds[0] = (BaseItemIdType)inboxItem.ItemId; GetItemResponseType getItemResponse = binding.GetItem(getItemRequest); // We only passed in one ItemId to the GetItem request. Therefore, we can assume that // we got at most one Item back. ItemInfoResponseMessageType getItemResponseMessage = getItemResponse.ResponseMessages.Items[0] as ItemInfoResponseMessageType; if (getItemResponseMessage != null) { if (getItemResponseMessage.ResponseClass == ResponseClassType.Success && getItemResponseMessage.Items.Items != null && getItemResponseMessage.Items.Items.Length > 0) { inboxItem = getItemResponseMessage.Items.Items[0]; } } else { return inboxResponse; } // now the message body is here BodyType messageBody = inboxItem.Body; // now we have the mailbox item's body property, get the email text string content = messageBody.Value; // This is the emaill body in html string cleanContent = CleanUpHtml(content); emailMessage = new EmailMessage(); emailMessage.Subject = inboxItem.Subject; emailMessage.ReceivedDate = inboxItem.DateTimeReceived.ToString(); // TODO: emailMessage.MessageBody = cleanContent; emailMessage.From = inboxItem.LastModifiedName; // TODO: Is this "from"? emailMessage.ItemID = inboxItem.ItemId.Id; emailMessage.ChangeKey = inboxItem.ItemId.ChangeKey; emailMessages.Add(emailMessage);Anonymous
August 05, 2009
Change the type of inboxItem to either MessageType or CalendarType depending upon its actual type. ItemType is a base object and does not include From field as a ContactType can also be typecast into ItemType. You need to use either MessageType or CalendarType which has From fieldAnonymous
August 05, 2009
Thank you very much Vikas! This works!!!Anonymous
August 05, 2009
By the way, may I ask how to limit the number of email items returned from FindItem?Anonymous
August 05, 2009
You can do that by turning paging on the FindItem operation See the sample code here.. http://msdn.microsoft.com/en-us/library/exchangewebservices.finditemtype.aspx // Define the paging scheme for the result set. IndexedPageViewType ipvt = new IndexedPageViewType(); ipvt.BasePoint = IndexBasePointType.Beginning; ipvt.MaxEntriesReturned = 10; ipvt.MaxEntriesReturnedSpecified = true; ipvt.Offset = 0; // Add the paging scheme to the request. findItemRequest.Item = ipvt;Anonymous
August 11, 2009
Thanks again! How do I return 10 most recent "unread" mails? The requirements are -
- based on email received date, return the most recent 10 emails. AND
- returned only the "unread" emails. Thank you for your help!