I am new to using EWS managed APIs.
Following is the issue I am facing with EWS APIs: EWS API - Impersonating to update a calendar item created by any other user than a service account, raise an error "Access is denied. Check credentials and try again."
Details: 1. I am using a service account e.g. abc@xyz.onmicrosoft.com. This user is a global administrator and also has ApplicationImpersonation role assigned. (Sign into Online Office 365 account -> Admin -> select "Exchange" tab- > select Permissions on the left panel -> create an impersonation role -> assign ApplicationImpersonation in Roles: and abc@xyz.onmicrosoft.com in Members: -> Click on save)
Create a calendar item by other user for e.g. pqr@xyz.onmicrosoft.com, and invite an attendee - abc@xyz.onmicrosoft.com.
In a c# program, I connect to EWS service using a service account - abc@xyz.onmicrosoft.com, fetch its calendar events. If organizer of an event is some other user - pqr@xyz.onmicrosoft.com then I use impersonation in the following way to update the calendar event/item properties- subject, body text etc.
private static void Impersonate(string organizer)
{
string impersonatedUserSMTPAddress = organizer;
ImpersonatedUserId impersonatedUserId =
new ImpersonatedUserId(ConnectingIdType.SmtpAddress, impersonatedUserSMTPAddress);
service.ImpersonatedUserId = impersonatedUserId;
}
It was working fine till yesterday afternoon. Suddenly, it started throwing an exception "Access is denied. Check credentials and try again." Whenever I try to update that event.
private static void FindAndUpdate(ExchangeService service) { CalendarView cv = new CalendarView(DateTime.Now, DateTime.Now.AddDays(30)); cv.MaxItemsReturned = 25; try { FindItemsResults masterResults = service.FindItems(WellKnownFolderName.Calendar, cv);
foreach (Appointment item in masterResults.Items)
{
if (item is Appointment)
{
Appointment masterItem = item as Appointment;
if (!masterRecurEventIDs.Contains(masterItem.ICalUid.ToString()))
{
masterItem.Load();
if (!masterItem.Subject.Contains(" (Updated content)"))
{
//impersonate organizer to update and save for further use
Impersonate(masterItem.Organizer.Address.ToString());
// Update the subject and body
masterItem.Subject = masterItem.Subject + " (Updated content)";
string currentBodyType = masterItem.Body.BodyType.ToString();
masterItem.Body = masterItem.Body.Text + "\nUpdated Body Info: xxxxxxxxxxxx";
// This results in an UpdateItem operation call to EWS.
masterItem.Update(ConflictResolutionMode.AutoResolve);
// Send updated notification to organizer of an appointment
CreateAndSendEmail(masterItem.Organizer.Address.ToString(), masterItem.Subject);
masterRecurEventIDs.Add(masterItem.ICalUid.ToString());
}
else
{
Console.WriteLine("Event is already updated. No need to update again.:\r\n");
Console.WriteLine("Subject: " + masterItem.Subject);
Console.WriteLine("Description: " + masterItem.Body.Text);
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
What could be an issue here? Initially I thought may be its a throttling policy which is stopping same user after making certain API call limits for the day, but I am still seeing this issue today.
Any help is appreciated.
Thanks
Found the solution:
Only adding impersonated ID to the existing service instance doesn't work. You also need to re-validate the auto-discover url.