We're using EWS to integrate our CRM with Exchange Online 2010SP2. One of the tasks: provide one calendar for Sales persons with the next rule: every Sales can see all appointments in Scheduler, but can open and see details (body) only his/her own appointment. Appointment are being placed by CRM in response of certain business events. We tried to use impersonate and Sensitivity.Private property. Appointment is being placed with impersonated user name, but it can't be opened by that user neither through OWA nor via Outlook. So it's placed as private appointment of 'master' user (user who created shared calendar and his credentials is used for service connection), he can open it in Outlook or OWA. EWSEditor shows appointment's LastModifiedUser - correct impersonated username (not master's). In Fiddler we can see 'success' Response on appointment placement request (under impersonated user). In OutlookSpy, we can see that appointments PR_SENDER_NAME_W, PR_SENT_REPRESENTING_NAME_W properties shows 'master's' username. We stuck.
Impersonated user has 'owner' rights upon that shared calendar.
If Impersonating doesn't resolve this issue, can Delegate technique do that?
Thanks in advance for any help.
static void Main(string[] args)
{
ExchangeService services = new
ExchangeService(ExchangeVersion.Exchange2010_SP2);
services.Credentials = new WebCredentials("master#exchserver.com",
"MasterPwd");
services.Url = new Uri("https://someserver.com/ews/exchange.asmx");
FolderId rfRootFolderid = new FolderId(WellKnownFolderName.Calendar);
FolderView fvFolderView = new FolderView(100);
DateTime startDate = DateTime.Now.AddDays(1);
DateTime endDate;
string SalesCalendarId = "AAMkADVlMGVjZWVkLT....AADo8XAAA=";
CalendarFolder folder = CalendarFolder.Bind(services, new
FolderId(SalesCalendarId));
TimeSpan ts = new TimeSpan(10, 00, 0);
startDate = startDate.Date + ts;
endDate = startDate.AddMinutes(60);
services.HttpHeaders.Add("X-AnchorMailbox","impersonateduser#exchserver.com");
appointment.Subject = "from Test";
appointment.Body = "Test";
appointment.Start = startDate;
appointment.End = appointment.Start.AddMinutes(30);
appointment.ReminderDueBy = appointment.Start.AddHours(1);
appointment.Sensitivity = Sensitivity.Private;
ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "impersonateduser#exchserver.com");
appointment.Save(SalesCalendarId, SendInvitationsMode.SendToNone);
}
You could use impersonated user to obtain ‘owner’ permissions.
Please include the code below before services.Credentials = new WebCredentials("master#exchserver.com", "MasterPwd")
services.PreAuthenticate = true;
you need to make sure that we have required permissions for EWS Impersonation as per the article mentioned below:
Configuring Exchange Impersonation in Exchange 2010
Using Exchange Impersonation in Exchange 2010
You could reference the following link:
Get all calendar events for a specific user
Related
I am working on a web application in which one of the functionality is to set events/appointment from web application to outlook calendar of the user logged in the application.
I am using EWS Managed API to cover this functionality. This is working fine on localhost but when I deployed application on IIS then the appointments/events are not being created in outlook calendar.
I have searched regarding this and it might be happening due to some permissions.
Is EWS the right API to achieve above functionality or I am going in wrong way?
Kindly suggest any solution.
EWS Code
private static ExchangeService Service
{
get
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
//service.Credentials = new WebCredentials("example#abc.com", password);
service.AutodiscoverUrl("example#abc.com");
return service;
}
}
private void SaveAppointment()
{
IAppointmentFactory iappointment = new AppointmentFactory();
List<string> lstEmail = new List<string>() {"other#abc.com"};
CreateAppointments(Service, lstEmail, iappointment);
}
private static void CreateAppointments(ExchangeService service, List<string> emailAddresses, IAppointmentFactory factory)
{
// Loop through the list of email addresses to add the appointment.
foreach (var emailAddress in emailAddresses)
{
Console.WriteLine(string.Format(" Placing appointment in calendar for {0}.", emailAddress));
// Set the email address of the account to get the appointment.
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, emailAddress);
// Get the appointment to add.
Microsoft.Exchange.WebServices.Data.Appointment appointment = factory.GetAppointment(service);
// Save the appointment.
try
{
Mailbox primary = new Mailbox(emailAddress);
Microsoft.Exchange.WebServices.Data.Folder primaryCalendar = Microsoft.Exchange.WebServices.Data.Folder.Bind(service, new FolderId(WellKnownFolderName.Calendar, primary));
appointment.Save(primaryCalendar.Id, SendInvitationsMode.SendToAllAndSaveCopy);
}
catch (ServiceResponseException ex)
{
Console.WriteLine(string.Format("Could not create appointment for {0}", emailAddress));
Console.WriteLine(ex.Message);
}
}
}
Your application and IIS need to be specifically configured to allow delegation of the credentials to work see https://blogs.msdn.microsoft.com/emeamsgdev/2012/11/05/ews-from-a-web-application-using-windows-authentication-and-impersonation/
I'm having trouble finding out how to get the master occurrence for a series of private appointments using the Exchange Web Service Managed API for C#.
When I retrieve the list of appointments using FindAppointments on the ExchangeService, I manage to get the occurrences within the search criteria. However, when I then try to get the recurring master appointment using Appointment.BindToRecurringMaster where the id is the id of the private occurrence, I get the error "The specified object was not found in the store., Item not found."
Is there any other way for me to retrieve the master occurrence for a private occurrence?
In my example below, I'm authenticating using a service account which as the Reviewer permissions on the target mailbox calendar.
var exchangeService = new ExchangeService();
exchangeService.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
exchangeService.Credentials = new WebCredentials("service.user#organization.com", "password", "domain");
const string email = "other.user#organization.com";
// The following successfully retrieve all appointments including the private occurrence.
var appointments = exchangeService.FindAppointments(
new FolderId(WellKnownFolderName.Calendar, new Mailbox(email)),
new CalendarView(DateTime.UtcNow, DateTime.UtcNow.AddDays(1)));
const string id = "AAMkA..."; // Id of the private occurrence.
// The following fails saying "The specified object was not found in the store., Item not found."
var appointment = Appointment.BindToRecurringMaster(exchangeService, id);
Any help is appreciated.
What your describing is the expected behaviour for private Items if you haven't been delegated access to view private Items via the Delegate Operation. So you would need to either give the Service Account Delegate rights on the Mailbox using the Delegate operations https://msdn.microsoft.com/en-us/library/office/dn641959(v=exchg.150).aspx and set ViewPrivateItems to true. Or give the Service Account FullAccess to the Mailbox or use EWS Impersonation.
I am creating simple app for appointments scheduling and I want to implement ability for me to create appointments for my users.
I managed to create,update and delete my calendar on Exchange Server, and I somewhat managed to create appointments adding my colleagues as RequiredAttendees like so:
//service variable is being created using my credidentals
Appointment meeting = new Appointment(service);
meeting.Subject = "Some subject ";
meeting.Body = "Some body.";
meeting.Start = DateTime.Now;
meeting.End = meeting.Start.AddHours(4);
meeting.Location = "Some Location";
meeting.RequiredAttendees.Add("myCollegue#mail.com");
meeting.ReminderMinutesBeforeStart = 60;
meeting.Save(new FolderId(WellKnownFolderName.Calendar,
"myCollegue#mail.com"),
SendInvitationsMode.SendToAllAndSaveCopy);
But it is just setting him as required attendee. Next thing is I tried using impersonation, but I can't access hosting server to set myself as master and others to have to share calendar with me (due to permissions and stuff) so I had to scrape that as well. Also, he set me up to be his publishing author on his calendar.
Is there something I am missing, or can't seem to find on MSDN sites?
EDIT: I am able to create appointment in his calendar in outlok.
If anyone comes across same issues as I did in here please follow these steps:
Make sure that person for which you are creating appointment sets you up (on exchange server or in outlok as "Editing author" with all permissions.
After that you can create appointments for him (verify this by going to your outlok and creating some test appointments).
This code works for me:
Folder inboxFolder = Folder.Bind(service, new FolderId(WellKnownFolderName.Calendar, "your.colleague#company.com"));
Appointment appointmentOther = new Appointment(service);
appointmentOther.Subject = "Test 2";
appointmentOther.Body = "Body text";
appointmentOther.Start = DateTime.Now;
appointmentOther.End = DateTime.Today.AddHours(16);
appointmentOther.Location = "My Office";
appointmentOther.IsReminderSet = true;
appointmentOther.ReminderMinutesBeforeStart = 30;
appointmentOther.Save(inboxFolder.Id,SendInvitationsMode.SendToNone);
Good luck :)
I have created Following function to set Outlook appointment. It's work fine while running in localhost with visual Studio Editor.
But when I upload publish files on server its not working.
Do I need to set anything in server for Outlook or need to include any additional dll/files?
Any help will be appreciated. Pls let me know, if need more information.
public void OutLookReminder(string DateTimeVal)
{
Outlook.Application outlookApp = new Outlook.Application(); // creates new outlook app
Outlook.AppointmentItem oAppointment = (Outlook.AppointmentItem)outlookApp.CreateItem(Outlook.OlItemType.olAppointmentItem); // creates a new appointment
oAppointment.Subject = "........Subject"; // set the subject
oAppointment.Body = "--------Body"; // set the body
oAppointment.Location = "-------Location"; // set the location
oAppointment.Start = DateTime.ParseExact(DateTimeVal, "dd/MM/yyyy H:mm",null); // Set the start date
oAppointment.End = DateTime.ParseExact(DateTimeVal, "dd/MM/yyyy H:mm", null); // End date
oAppointment.ReminderSet = true; // Set the reminder
oAppointment.ReminderMinutesBeforeStart = 15; // reminder time
oAppointment.Importance = Outlook.OlImportance.olImportanceHigh; // appointment importance
oAppointment.BusyStatus = Outlook.OlBusyStatus.olBusy;
// save the appointment
oAppointment.Save();
}
Do you mean you are running this under a service (such as IIS)? You cannot do that.
Where is the appointment supposed to be created? Current user who is using your code in a browser (then your code needs to run locally in JavaScript)?
I am trying to get a list of all the appointments for the day on a shared calendar. I have successfully done it for my own calendar tied to my user account. I tried getting the folderId of the shared calendar, but I haven't been able to find it.
I used this to access my calendar using its folderId and it worked:
Console.WriteLine("Listing appointments...");
//open the calendar
CalendarFolder calendar = CalendarFolder.Bind(service, WellKnownFolderName.Calendar);
//query for appointments in next 10 days
//FindItemsResults<Appointment> appointments = calendar.FindAppointments(new CalendarView(DateTime.Now, DateTime.Now.AddDays(10)));
//find appointments and write out subject
foreach (Appointment appointment in service.FindItems(new FolderId("FOLDERIDHERE"), new ItemView(int.MaxValue)))
Console.WriteLine(appointment.Subject);
I don't know if this will work to access a shared folder, and I can't figure out the folderID of the shared folder.
You could try something like this :
CalendarModule calModule = (CalendarModule)this.Application.ActiveExplorer().NavigationPane.Modules.GetNavigationModule(OlNavigationModuleType.olModuleCalendar);
foreach (NavigationGroup group in calModule.NavigationGroups)
{
NavigationFolders folders = group.NavigationFolders;
MAPIFolder OtherFolder = null;
Items OtherFolderItems = null;
for (int i = 1; i <= group.NavigationFolders.Count; i++)
{
OtherFolder = folders[i].Folder; //This does not work for me
OtherFolderItems = OtherFolder.Items;
}
Unfortunately, this code did not work for me, as trying to access the .Folder launch an exception. I found this on this link : http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/4891d3a5-f578-495c-83aa-f5a914474c78/