How to get latest SyncState from Exchange Server 2007 SP1 - c#

I am using EWS api for email operations.
When initially user sets up his account, i just need to collect latest syncstate of his account. My CRON job checks for latest changes from then onwards at regular intervals.
Here is the code
var service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Url = new Uri("https://" + data.ServerAddress + "/ews/Exchange.asmx");
service.Credentials = new NetworkCredential(data.EMail, data.Password);
ServicePointManager.ServerCertificateValidationCallback = (xyzxyz, certificate, chain, sslPolicyErrors) => true;
ChangeCollection<ItemChange> icc = service.SyncFolderItems(new FolderId(WellKnownFolderName.Inbox),
PropertySet.FirstClassProperties,
null,
512,
SyncFolderItemsScope.NormalItems,
null );
return icc.SyncState;
Issue lies in collecting SyncState when user initially sets up his account.
Assume user has 600 email in Inbox. When I request for syncstate with above code, I get syncstate which is valid for first 512 emails. I will have to make one more call to get next syncstate which is valid and final. This will increase waiting time for the user to setup his account. If user has 10000 mails in Inbox, it would be required to make 20 calls to EWS to get final SyncState.
How to get final or latest SyncState with a single call to EWS?

You can't get the latest sync state in a single call, see EWS. How to get latest SyncState without initial synchronization?. Note that starting with Exchange 2010 SP2, EWS returns items from newest to oldest, so the user will get their newest items first - they won't have to wait all 20 calls.

Related

EWS Managed API, Why Item.DateTimeSent.Millisecond is always zero?

I am trying to calculate the time taken to send email message and time taken to receive email message. i am using EWS in my program , I set streaming notification to receive call back when a new mail reaches reciptent mailbox .
once received notification i bind the Itemevent with ews service , i checked the item properties DateTimeCreated, DateTimeSent, DateTimeReceived.All these properties are of DateTime object.
I checked DateTimeSent milisecond is always 0, whereas DateTimeCreated, DateTimeReceived has millisecond value.
I couldnot figure out why DateTimeSent millisecond is always 0 everytime. if i want to claulate time taken from send to receive what should i do.
DateTimeReceived - Datetimesent is the actual time taken to send and receive the message?
or what is the correct way to calculate time taken to send and receive the message?
set DateTimePrecision as Milliseconds
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials(username, password);
service.Url = new Uri(ConfigSettings.EmailConnectionUrl);
service.DateTimePrecision = DateTimePrecision.Milliseconds;
how about actually measuring the Timespan? so for example showing total milliseconds but you could change that to suit
var result=((TimeSpan)(DateTimeReceived - DateTimeSent )).TotalMilliseconds.ToString("#,##0.00") + "ms";
In the EWS Managed API the ExchangeService class has a precision property that you need to set before you make any calls see https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeservice.datetimeprecision(v=exchg.80).aspx

EWS Appointment server change timestamp

I'm working on buffer solution for MS Exchange server.
The buffer should store events and keep them in sync with Exchange server.
I code in C# and use Managed EWS.
The buffer queries Exchange for appointments changed in sequential intervals:
(t[1], t[2]), (t[2], t[3]), (t[3], t[4])
...
I use Appointment.LastModifiedTime field to filter out appointments changed in interval (t[x], t[x+1]). However I discovered, that this field takes it value from time of modification on client. What I need is some timestamp of modification on server.
Imagine the case: user X goes offline and adds appointment on t[Y] in his Outlook client. On t[Z] = t[Y] + 24h user X goes online. His Outlook client will sync with Exchange server and this new appoinment appears on it with LastModifiedDate = t[Y]. Is there some field to get t[Z] ?
For now I see full sync as a 100% working alternative to this, but it is a 'hammer solution' with obvious drawbacks. I will have to use it in case nobody can give an alternative :)

EWS Exchange Impersonate 2 or more users using one ExchangeService connection

In order to avoid the Exchange Server limit RCAMaxConcurrency (0-100), I want to code a listener service (streamlistener) that can handle up to 5000 users using just one connection. I already have 200 test accounts and another account having impersonate rights over those 200 test accounts.
If possible it would be nice to avoid switching around all accounts.
We already have the code and it works fine doing impersonation just to 1 user.
public void SuscribeToCalendar()
{
// Set the email address of the account to get the appointment.
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, "xxxxxxxxx");
// Subscribe to streaming notifications in the Inbox.
StreamingSubscription streamingSubscription = service.SubscribeToStreamingNotifications(
new FolderId[] { WellKnownFolderName.Calendar }, EventType.Created, EventType.Modified, EventType.Moved);
// Create a streaming connection to the service object, over which events are returned to the client.
// Keep the streaming connection open for 30 minutes.
StreamingSubscriptionConnection connection = new StreamingSubscriptionConnection(service, 30);
connection.AddSubscription(streamingSubscription);
connection.OnNotificationEvent += OnNotificationEvent;
connection.OnDisconnect += OnDisconnect;
connection.Open();
}
RCAMaxConcurrency doesn't affect EWS it affect Outlook connections which use RPC to connect. What will affect EWS is EWSMaxConcurrency which has a much a lower value to 10 by default. (you would also get affected by EWSMaxSubscriptions which is 20).
The impersonation setting affect the header of the EWS request so you can't impersonate any more the one user per call so when creating a subscription you need one call per user you subscribing. You can group the Subscripting together into one connection with impersonation using the following https://msdn.microsoft.com/en-us/library/office/dn458789(v=exchg.150).aspx .
The limitations with group is 200 users per group, given the amount of churn you have with subscriptions you don't really want any more the this. When your using impersonation the number of connections isn't an issue as long as you don't anchor ever group with the same mailbox.
Cheers
Glen

ExchangeService: connecting without credentials, how to retrieve user information?

I am analyzing a users Exchange mailbox with calls to the ExchangeService. This tool needs to run on the client environment periodically and by ommiting the credentials to the service I am connecting to the Exchange Service as the logged in Windows User. I can succesfully loop thrue the folders and items.
Now I want tot retrieve the information about the mailbox being used. Username and (main) E-mail should suffice. But I cannot find anything about how to retrieve this information. Every example provides credentails for the user, or auto-discovering the Exchange service from the e-mail adres. I do not want the user to configure anything :-).
Any suggestions?
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Url = new Uri("https://FQDN/EWS/Exchange.asmx");
???
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.SentItems, new ItemView(100)); // this works
I've tried using service.ResolveName, but that can give multiple answers, even using Environment.UserName
The easiest method to do this is to use ConvertId operation and use unresolvable address (blah#blah.com always works for me) in the Mailbox element. Exchange should convert this to the actual Mailbox in the response. eg
Folder chk = Folder.Bind(service, WellKnownFolderName.Inbox);
AlternateId aiItem = new AlternateId();
aiItem.Mailbox = "Blah#Blah.com";
aiItem.UniqueId = chk.Id.UniqueId;
aiItem.Format = IdFormat.EwsId;
String CasServer = service.Url.Host.ToString();
AlternateIdBase caid = service.ConvertId(aiItem, IdFormat.HexEntryId);
Console.WriteLine(((AlternateId)caid).Mailbox);
Cheers
Glen

EWS - Possible timeout?

I'm new to EWS so forgive me if this is obvious. I searched and could not find a solution.
I have a command line C# utility that filters emails and organizes them into folders. The app seems to work fine logically, but appears to be timing out after 15 minutes without error.
The utility connects using autodiscover:
private ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
...
// Connect using credentials and autodiscover
service.Credentials = new WebCredentials(userName, password, domain);
service.AutodiscoverUrl(emailServer);
Then after filtering, it loops through the results and moves the emails into the appropriate folders. Something like this:
...
// Create a filter to only return unread messages
SearchFilter emailFilter = new SearchFilter.IsLessThan(EmailMessageSchema.DateTimeReceived, DateTime.Now.AddDays(-2));
// Retrieve the results
FindItemsResults<Item> findResults = service.FindItems(folder, emailFilter, view);
Logger.Write("Total emails to be archived: " + findResults.TotalCount);
...
try
{
...
foreach (Item email in findResults)
{
EmailMessage emailMessage = EmailMessage.Bind(service, email.Id);
emailMessage.Load();
emailMessage.Move(folder5.Folders[0].Id);
}
}
catch (Exception ex)
{
Logger.Write("Exception caught while moving emails: " + ex.Message);
throw ex;
}
...
Logger.Write("=== End Email Move Logic...");
My first logging output indicates that 5,000 emails should be moved, and in fact, the process begins nicely, but after 15 minutes, I see the final logging output. Indicating that everything completed. Yet, only a portion of the total 5000 get moved. Oddly, I do not see an exception or anything in the event logs.
EDIT: 7/9/2014
Ok, my initial problem was due to the fact that I did not notice that the FindItemsResults class uses paging! Doh! So even though it correctly reported the TotalCount (5000), when I iterated through the results, only 1000 were being processed. Not terribly intuitive to a EWS noob like me, but there you have it.
Unfortunately, I have a follow-up frustration. Based on Brad's comments below, I'm now using the ExchangeService.MoveItems method. After dealing with the paging issue, I now have a proper list of itemIds (count = 5000) that I pass to the MoveItems method. Like this:
service.MoveItems(itemIds, folder5.Folders[0].Id);
To my surprise, only 730 emails were moved. Leaving 4270 emails unmoved. So, hoping to find a pattern, I ran it again, this time 671 emails were moved. No pattern.
Any input would be greatly appreciated.
I appreciate this is an old thread but it was the first I found on Google so thought I would add my findings.
I coded a WPF app to help in migrating legacy Exchange public folders to Office 365 hosted Exchange and have been experiencing timeouts when searching using the FindItems method. Specifically I was searching over a date range for date sent in a public folder and then copying the items found to the Office 365 public folder. If we used a large date range then the FindItems call would timeout.
What has fixed it for us is to set the Timeout value for the ExchangeService, the default is 100000 milliseconds, so we just added another 0 to test the possible solution. Hey presto we were able to use much larger date ranges.
ExchangeService service = new ExchangeService();
ExchangeService o365 = new ExchangeService();
switch (strArgs[6])
{
case "0":
service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
break;
case "1":
service = new ExchangeService(ExchangeVersion.Exchange2010);
break;
case "2":
service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
break;
case "3":
service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
break;
case "4":
service = new ExchangeService(ExchangeVersion.Exchange2013);
break;
case "5":
service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
break;
}
int nCount = 0;
// Connect to on-premises Exchange Server
callback(nCount, "Connecting to on-premises Exchange Server, please wait....", 0, true, mailItem);
service.Credentials = new WebCredentials(strArgs[0], strArgs[1]);
if (!useUrl)
service.AutodiscoverUrl(strArgs[2], RedirectionUrlValidationCallback);
else
service.Url = new Uri(strArgs[10] + "/EWS/Exchange.asmx");
service.Timeout = 1000000;
callback(nCount, "Connected to on-premises Exchange Server, please wait....", 0, true, mailItem);
// Connect to Office 365 Exchange Server
callback(nCount, "Connecting to Office 365 Exchange Server, please wait....", 0, true, mailItem);
o365.Credentials = new WebCredentials(strArgs[7], strArgs[8]);
o365.AutodiscoverUrl(strArgs[9], RedirectionUrlValidationCallback);
callback(nCount, "Connected to Office 365 Exchange Server, please wait....", 0, true, mailItem);
We are using a paging value of 500.
The source Exchange version is Exchange 2007 SP1.
Hope it helps someone.
Timeouts are normal for search queries, especially for large folders.
What happens is Exchange does not keep live indexes to respond to just any search query you can build, so it times out the response and keeps indexing.
If you try to issue the same query later it will succeed. Unfortunately Exchange does not provide information on when, just keep trying. After first page is returned further page queries will return almost immediately.
BTW this is not a throttling issue, you will get a clear error back when throttling limit is reached. Exchange 2007 just says that, 2010 and higher provides you a value of how much to wait until throttling quota will be recharged.

Categories

Resources