Edit Exchange appointment of other user - c#

I'm coding a service which should synchronize Outlook appointments with another system. After appointment created I need to add some info to the body. The service is running under some tech account, it's also added as an owner to the organizer's calendar in Outlook. However, the following code doesn't do any changes:
var _exchangeService = new ExchangeService(ExchangeVersion.Exchange2010_SP2, TimeZoneInfo.Local)
{
Url = new Uri(someUrl),
Credentials = new NetworkCredential(someUser, somePwd, someDomain)
};
Appointment appointment = Appointment.Bind(_exchangeService, someId, new PropertySet(AppointmentSchema.Subject, AppointmentSchema.Start, AppointmentSchema.End));
string oldSubject = appointment.Subject;
appointment.Subject = appointment.Subject + " moved one hour later and to the day after " + appointment.Start.DayOfWeek + "!";
appointment.Start.AddHours(25);
appointment.End.AddHours(25);
appointment.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendOnlyToAll);
The sample code is taken from MSDN. The code works when Organizer and tech Account is the same user.
Do you have any idea of what could be wrong? Thank you!

The sample code is taken from MSDN. The code works when Organizer and tech Account is the same user.
That's correct because you can only make changes to appointments that the user making the modifications is the owner off (in some case this will require that you use EWS Impersonation https://msdn.microsoft.com/en-us/library/office/dd633680(v=exchg.80).aspx ). For a Meeting object where you have multiple attendees once you make changes in the Organizer mailbox updates then need to be sent out to the attendees who then need to acknowledge those updates for the updates to be applied to the version of the Appointment in the attendee's calendars.
Cheers
Glen

Related

Outlook 2016 showing appointment Icon even for meetings created with EWS API

I'm creating appointments and meeting with EWS managed API but however, I found the Icon's appearing wrongly in Outlook 2016.
Creating meetings with msdn example ` ExchangeService service = GetExchangeService();
Appointment meeting = new Appointment(service);
// Set the properties on the meeting object to create the meeting.
meeting.Subject = "EWS : Meeting";
meeting.Body = "Let's learn to really work as a team and then have lunch!";
meeting.Start = DateTime.Now.AddDays(2);
meeting.End = meeting.Start.AddHours(4);
meeting.Location = "Conference Room 12";
meeting.RequiredAttendees.Add("attendee1");
meeting.RequiredAttendees.Add("attendee2");
meeting.ReminderMinutesBeforeStart = 60;
//// Save the meeting to the Calendar folder and send the meeting request.
meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy);
// Verify that the meeting was created.
Item item = Item.Bind(service, meeting.Id, new PropertySet(BasePropertySet.FirstClassProperties));
Console.WriteLine("\nMeeting created: " + item.Subject + "\n");`
But the Icons are like this .
Here , Subject starting with "EWS" created using API and subject with "Outlook" are manually created in outlook. Outlook meeting has different Icon.
Any workaround for this problem?
You could try setting the PR_Icon_Index property https://msdn.microsoft.com/en-us/library/office/cc815472.aspx which you should be able to set using a Extended property to 0x00000402 for a single instance meeting.

Using Microsoft's EWS to create online Lync/Skype meeting

Anybody knows how to create meeting request with online conference(Lync/Skype) using EWS?
So my approach is first getting an online and regular meeting created via Outlook and then simulate the creation of event with the same property.
Here is my code snippet for getting the meeting (calendarView is already initialized with start date, end date etc.):
ExtendedPropertyDefinition extendedOnlineMeetingProperty =
new ExtendedPropertyDefinition(new Guid("{00062008-0000-0000-c000-000000000046}"), 34112,
MapiPropertyType.Integer);
var properties = new PropertySet(
ItemSchema.Id,
AppointmentSchema.ICalUid,
ItemSchema.Subject,
AppointmentSchema.Start,
AppointmentSchema.End,
AppointmentSchema.Organizer,
AppointmentSchema.Location,
AppointmentSchema.LegacyFreeBusyStatus,
AppointmentSchema.IsCancelled,
AppointmentSchema.ICalRecurrenceId,
AppointmentSchema.MyResponseType, // Mandatory Meeting.MyResponseType can be retrieved without a search in the participant list
ItemSchema.LastModifiedTime,
AppointmentSchema.IsOnlineMeeting,
AppointmentSchema.IsMeeting,
ItemSchema.DisplayTo) { };
properties.Add(extendedOnlineMeetingProperty);
var activeResults = service.FindAppointments(WellKnownFolderName.Calendar, calendarView).ToList();
if (activeResults.Count > 0)
{
service.LoadPropertiesForItems(activeResults, properties);
}
I got the property IsOnlineMeeting with the correct bool value (tested -
created online and regular meeting with Outlook) in variable activeResults but I do not understand where to get conference link and other Lync/Skype properties needed for joining a conference.
Also I am not sure where and how to assign the values of Lync/Skype conference URL and other properties.
Sometimes I ask myself if it's worth it to developed some app based on MS products since their documentation suck.
After one week of cursing MS I have found a solution. Using the tool MFCMAPI you can check what property and their values your item in mailbox have.
download the program link
build and run it
Session - Logon - choose your mail profile - pick the mailbox and double click
actions - open special folder - calendar - double click on calendar
open the item with online S4B/Lync conference
the UC* properties are the one I was looking for.
If you open the property you can see something like this on the top:
ag: 0x8096001E
Type: PT_STRING8
DASL: http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/UCMeetingSetting
Named Prop Name: UCMeetingSetting
Named Prop Guid: {00020329-0000-0000-C000-000000000046} = PS_PUBLIC_STRINGS
So my definition of the extended property was wrong. It is not only one property but actually you need all 7 of them.
So the definition should be:
private static ExtendedPropertyDefinition CreateOnlineMeetingProperty()
{
ExtendedPropertyDefinition extendedUCMeetingSetting =
new ExtendedPropertyDefinition(new Guid("{00020329-0000-0000-C000-000000000046}"), "UCMeetingSetting",
MapiPropertyType.String);
return extendedUCMeetingSetting;
}
With the correct extended definition you can get the values from the item easily.
accessing the Value of ExtendedProperties
Calling TryGetProperty
var activeResults = service.FindAppointments(new
FolderId(WellKnownFolderName.Calendar, resource.Email),calendarView).ToList();
service.LoadPropertiesForItems(activeResults, properties);
foreach (Appointment result in activeResults)
{
// 1.
var b = result.ExtendedProperties[1].Value;
// 2.
string UCMeetingSetting;
result.TryGetProperty(extendedUCMeetingSetting, out UCMeetingSetting);
}
using steps above you can get whatever extended property you want, not only Unified Communications (UC) properties.
Ok, I managed to have this working (almost!) by setting just one of the extended properties:
appointment.SetExtendedProperty(
new ExtendedPropertyDefinition(
new Guid("00020329-0000-0000-C000-000000000046"),
"OnlineMeetingExternalLink",
MapiPropertyType.String
),
skypeMeeting.JoinUrl
);
I say almost because the appointment doesn't look exactly like a Skype meeting when you open it in Outlook: doesn't have the footer will the Join link and phone number etc.
Maybe there are other differences, but for now we see it in Skype for business with the Join button and also we see the it in the Outlook reminder with the Join button.
As a workaround, we have to hard-code the body content of the appointment.
Also conference ID, can be taken using UCWA 2.0 (https://learn.microsoft.com/en-us/skype-sdk/ucwa/myonlinemeetings_ref)
We used UCWA 2.0 to create the Skype conference call and attached it to the EWS appointment object.

Get calendars of office365 email without authentication

I want to get list of events of particular users lets say user#company1.com , user#company2.com which uses office365 accounts.
I need to retrive user#company2.com calendar with out login. My application will be like listing my available timings for my clients , so that they can select my free time and will schedule meeting with me. I need to filter the already scheduled events from my list... Is there any example code for getting calendar events without login??
I tried office365 multi-tenant application which will gives sample code for getting calendar events only after login. I need it with out authentication. Please help me on this.
Trying to access the O365 information without authentication is impossible , either user authentication or app authentication will be required . In your scenario ,you may need app authentication . You could try to build Daemon or Service Apps using client credential grant flow as described in this blog, the service app that requires admin consent, but is authorized to access any mailbox/calendar information in your Office 365 tenant.
Another choice is to use EWS Managed API, you could get free/busy information of a user and suggested meeting times by using the EWS Managed API :
https://msdn.microsoft.com/en-us/library/office/dn643673(v=exchg.150).aspx
And an existing Office add-in support on Outlook:
https://findtime.microsoft.com/
Finally I tried to use the free/busy code. My code is as follows... I am following this procedure but I don't know if it is correct or not. I have a Microsoft Office 365 account, and by passing credentials silently, I am creating Exchange Server service. After that i am passing different domain attendee information as ORGANIZER and REQUIRED as follows. But it is returning all values not skipping any scheduled meetings for those users.
Lets assume user1#domain.com is ORGANIZER and user2#anotherdomain.com is REQUIRED for meeting . User1 have meeting scheduled at 7:00-7:30pm on daily basis but when I executed the following script it shows me 7:00-7:30pm as available for meeting. It supposed to block that time.
Can you suggest some changes to code and am I proceeding in the correct way?
private static void GetSuggestedMeetingTimes(ExchangeService service)
{
List<AttendeeInfo> attendees = new List<AttendeeInfo>();
attendees.Add(new AttendeeInfo()
{
SmtpAddress = "user1#mydomain.com",
AttendeeType = MeetingAttendeeType.Organizer
});
attendees.Add(new AttendeeInfo()
{
SmtpAddress = "user2#anotherdomain.com",
AttendeeType = MeetingAttendeeType.Required
});
// Specify options to request free/busy information and suggested meeting times.
AvailabilityOptions availabilityOptions = new AvailabilityOptions();
availabilityOptions.GoodSuggestionThreshold = 49;
availabilityOptions.MaximumNonWorkHoursSuggestionsPerDay = 0;
availabilityOptions.MaximumSuggestionsPerDay = 40;
// Note that 60 minutes is the default value for MeetingDuration, but setting it explicitly for demonstration purposes.
availabilityOptions.MeetingDuration = 30;
availabilityOptions.MinimumSuggestionQuality = SuggestionQuality.Good;
availabilityOptions.DetailedSuggestionsWindow = new TimeWindow(DateTime.Now.AddDays(1), DateTime.Now.AddDays(2));
availabilityOptions.RequestedFreeBusyView = FreeBusyViewType.FreeBusy;
// Return free/busy information and a set of suggested meeting times.
// This method results in a GetUserAvailabilityRequest call to EWS.
GetUserAvailabilityResults results = service.GetUserAvailability(attendees,
availabilityOptions.DetailedSuggestionsWindow,
AvailabilityData.FreeBusyAndSuggestions,
availabilityOptions);
// Display suggested meeting times.
Console.WriteLine("Availability for {0} and {1}", attendees[0].SmtpAddress, attendees[1].SmtpAddress);
Console.WriteLine();
foreach (Suggestion suggestion in results.Suggestions)
{
Console.WriteLine("Suggested date: {0}\n", suggestion.Date.ToShortDateString());
Console.WriteLine("Suggested meeting times:\n");
foreach (TimeSuggestion timeSuggestion in suggestion.TimeSuggestions)
{
Console.WriteLine("\t{0} - {1}\n",
timeSuggestion.MeetingTime.ToShortTimeString(),
timeSuggestion.MeetingTime.Add(TimeSpan.FromMinutes(availabilityOptions.MeetingDuration)).ToShortTimeString());
}
}
int i = 0;
// Display free/busy times.
foreach (AttendeeAvailability availability in results.AttendeesAvailability)
{
Console.WriteLine("Availability information for {0}:\n", attendees[i].SmtpAddress);
foreach (CalendarEvent calEvent in availability.CalendarEvents)
{
Console.WriteLine("\tBusy from {0} to {1} \n", calEvent.StartTime.ToString(), calEvent.EndTime.ToString());
}
i++;
}

Exchange API incorrect Subject

When ever I create a meeting in Outlook, Subject field for an appointment is going through incorrectly. Instead of something like "Test" I get the name of the user who created an appointment.
-> bold = title, admin = creator name
-> admin = creator name even though it suppose to be subject.
foreach (Appointment a in room.appointments)
m.Subject = a.Subject
Is this a known issue; Is there another field that is responsible for subject?
This is actually not an "issue" but a "feature" of Exchange's workflow for meeting invites. The default on a room resource is to replace the subject with the orgranizer. This can be changed for a room with a PowerShell command:
Set-Calendarprocessing -Identity:roommb -AddOrganizerToSubject:$false -DeleteSubject:$false
Of course you need proper permissions to do this, or else bribe your Exchange admin!

How to use Microsoft Exchange Web Services to retrieve meeting form other contacts in the same domain?

I would like to retrieve calender items from Outlook 2010. Currently I could only retrieve items from my own calender by following this tutorial. But I want to get meeting from my colleagues calender. I have tried many option so far but nothing is working. Could you please show me how to use these api to get all calender meeting from the same exchange server? Thanks in advance!
Well, there is no answer within 2 days. Meanwhile I found a way to access others calender. I want to share my solution so that other can get a helsp:-
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
service.Credentials = new WebCredentials();
Mailbox principle = new Mailbox("usedr#domain.com");
CalendarFolder calendar2 = CalendarFolder.Bind(service, new FolderId(WellKnownFolderName.Calendar, principle), new PropertySet());
// Retrieve a collection of appointments by using the calendar view.
FindItemsResults<Appointment> appointments2 = calendar2.FindAppointments(cView2);
appointments2 should have all the calender meeting.

Categories