16
votes

I want to fetch all mails in the Inbox folder using EWS Managed API and store them as .eml. The problem is in fetching (1) all mails with (2) all headers (like from, to, subject) (I am keeping information of those values of from, to and other properties somewhere else, so I need them too) and (3)byte[] EmailMessage.MimeContent.Content. Actually I am lacking understanding of

  • Microsoft.Exchange.WebServices.Data.ItemView,
  • Microsoft.Exchange.WebServices.Data.BasePropertySet and
  • Microsoft.Exchange.WebServices.Data.ItemSchema

thats why I am finding it difficult.

My primary code is:

When I create PropertySet as follows:

PropertySet properties = new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.MimeContent);

I get following exception:

The property MimeContent can't be used in FindItem requests.

I dont understand

(1) What these ItemSchema and BasePropertySet are

(2) And how we are supposed to use them

So I removed ItemSchema.MimeContent:

PropertySet properties = new PropertySet(BasePropertySet.FirstClassProperties);

I wrote simple following code to get all mails in inbox:

ItemView view = new ItemView(50);
view.PropertySet = properties;
FindItemsResults<Item> findResults; 
List<EmailMessage> emails = new List<EmailMessage>();

do
{    
    findResults = service.FindItems(WellKnownFolderName.Inbox, view);
    foreach (var item in findResults.Items)
    {
        emails.Add((EmailMessage)item);
    }
    Console.WriteLine("Loop");
    view.Offset = 50;
}
while (findResults.MoreAvailable);

Above I kept page size of ItemView to 50, to retrieve no more than 50 mails at a time, and then offsetting it by 50 to get next 50 mails if there are any. However it goes in infinite loop and continuously prints Loop on console. So I must be understanding pagesize and offset wrong. I want to understand

(3) what pagesize, offset and offsetbasepoint in ItemView constructor means

(4) how they behave and

(5) how to use them to retrieve all mails in the inbox

I didnt found any article online nicely explaining these but just giving code samples. Will appreciate question-wise explanation despite it may turn long.

1
Worked on it long back. If I remember it correct, we can save it only as eml. I guess you want to know if we can save it as msg. Am I right? If yes, we can obtain msg only when working from inside outlook. I did not find work around to get back msg with EWS. But there is nothing wrong with eml, its the standard.Mahesha999
How do you save it only as eml ? source code fragment about it?. Right, anyways, you say that I can get msg ONLY inside Outlook (using Outlook.Application automation).Kiquenet
didnt get you fully. Excerpts to save as eml can be found here:1, 2Mahesha999
there were people talking about eml to msg conversion too: 1. This looks promising but is not free...And I never tried any such thing.Mahesha999

1 Answers

30
votes

EWS is a bit inconsistent with the properties returned from various operations. An Item.Bind will not return the exact same properties as a FindItem. You're using PropertySets properly as far as defining what you want from the server, but you have to use them in the right place. What you need to do is find the items, then load the properties into them. It's not ideal, but that's the way EWS works. With your loop, you're constantly assigning 50 to your offset when you need to increment it by 50. Off the top of my head, something like this would do:

int offset = 0;
int pageSize = 50;
bool more = true;
ItemView view = new ItemView(pageSize, offset, OffsetBasePoint.Beginning);

view.PropertySet = PropertySet.IdOnly;
FindItemsResults<Item> findResults;
List<EmailMessage> emails = new List<EmailMessage>();

while(more){
    findResults = service.FindItems(WellKnownFolderName.Inbox, view);
    foreach (var item in findResults.Items){
        emails.Add((EmailMessage)item);
    }
    more = findResults.MoreAvailable;
    if (more){
        view.Offset += pageSize;
    }
}
PropertySet properties = (BasePropertySet.FirstClassProperties); //A PropertySet with the explicit properties you want goes here
service.LoadPropertiesForItems(emails, properties);

Now you have all of the items with all of the properties that you requested. FindItems often doesn't return all of the properties you want even if you ask for them, so loading only the Id initially and then loading up the properties you want is generally the way to go. You may also want to batch the loading of properties in some way depending on how many emails you're retrieving, perhaps in the loop prior to adding them to the List of EmailMessages. You could also consider other methods of getting items, such as a service.SyncFolder action.