Create an appointment in someone else's outlook calendar with C# - c#

I want to create a program which makes it possible to create an appointment in someone else's outlook calendar. For example : If someone asks their boss for five days free, their boss needs to be able to approve it and immediately make it visible in the person's outlook calendar. I already made some code in which allows you to set your own appointments. here is my code:
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
AddAppointment("ConferenceRoom #2345", "We will discuss progression the group project.", "Group Project", new DateTime(2016, 02, 23, 15, 30, 52), new DateTime(2016, 02, 23, 20, 30, 52));
}
private void AddAppointment(string location, string body, string subject, DateTime startdatum, DateTime einddatum)
{
try
{
var AppOutlook = new Outlook.Application();
Outlook.AppointmentItem newAppointment =
(Outlook.AppointmentItem)
AppOutlook.CreateItem(Outlook.OlItemType.olAppointmentItem);
newAppointment.Start = startdatum;
newAppointment.End = einddatum;
newAppointment.Location = location;
newAppointment.Body = body;
newAppointment.BusyStatus=Outlook.OlBusyStatus.olTentative;
newAppointment.AllDayEvent = true;
newAppointment.Subject = subject;
newAppointment.Save();
newAppointment.Display(true);
}
catch (Exception ex)
{
MessageBox.Show("The following error occurred: " + ex.Message);
}
}
PS: Sorry if my english isn't great.

I made use of the EWS api (https://msdn.microsoft.com/en-us/library/office/dd633710(v=exchg.80).aspx)
the code i used is:
try
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.UseDefaultCredentials = true;
service.Credentials = new WebCredentials("user#domain.com", "password");
service.Url = new Uri("https://mail.domain.com/EWS/Exchange.asmx");
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "user2#domain.com");
Appointment appointment = new Appointment(service);
// Set the properties on the appointment object to create the appointment.
appointment.Subject = "Tennis lesson";
appointment.Body = "Focus on backhand this week.";
appointment.Start = DateTime.Now.AddDays(2);
appointment.End = appointment.Start.AddHours(1);
appointment.Location = "Tennis club";
appointment.ReminderDueBy = DateTime.Now;
// Save the appointment to your calendar.
appointment.Save(SendInvitationsMode.SendToNone);
// Verify that the appointment was created by using the appointment's item ID.
Item item = Item.Bind(service, appointment.Id, new PropertySet(ItemSchema.Subject));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

There are three main ways for creating appointments in Outlook. You need to use the Items collection of the folder (Calendar folder in our case). The Add method accepts the OlItemType enumeration too and returns a newly created Outlook item. All possible ways are described in depth in the How To: Create a new Outlook Appointment item article.
items = calendarFolder.Items;
appItem = items.Add(Outlook.OlItemType.olAppointmentItem) as Outlook.AppointmentItem;
appItem.Save();
appItem.Display(true);
Note, you need to get a shared calendar folder first. The GetSharedDefaultFolder method of the Namespace class returns a Folder object that represents the specified default folder for the specified user. This method is used in a delegation scenario, where one user has delegated access to another user for one or more of their default folders (for example, their shared Calendar folder). For example:
Sub ResolveName()
Dim myNamespace As Outlook.NameSpace
Dim myRecipient As Outlook.Recipient
Dim CalendarFolder As Outlook.Folder
Set myNamespace = Application.GetNamespace("MAPI")
Set myRecipient = myNamespace.CreateRecipient("Eugene Astafiev")
myRecipient.Resolve
If myRecipient.Resolved Then
Call ShowCalendar(myNamespace, myRecipient)
End If
End Sub
Sub ShowCalendar(myNamespace, myRecipient)
Dim CalendarFolder As Outlook.Folder
Set CalendarFolder = _
myNamespace.GetSharedDefaultFolder _
(myRecipient, olFolderCalendar)
CalendarFolder.Display
End Sub

Related

UWP Appointments: Appointment ID returning empty

I am trying to add Appointments to my UWP App.
I have successfully set up the Appointment but the result for created Appointment Id is empty which means that the appointment is not created.
Following is my Code:
public static Rect GetElementRect(FrameworkElement element)
{
GeneralTransform transform = element.TransformToVisual(null);
Point point = transform.TransformPoint(new Point());
return new Rect(point, new Size(element.ActualWidth, element.ActualHeight));
}
private async Task<ManagerResponseModel> AddAppointmentToOutlookCalendar(ViewingSummaryModel model)
{
ManagerResponseModel result = new ManagerResponseModel();
//Add appointment if assigned to the same user
if(model.HousingOfficerId == AppSession.LoggedinUserId)
{
// Create an Appointment that should be added the user's appointments provider app.
var appointment = new Appointment();
//Populate Viewing Data in appointment
appointment.Subject = string.Format("Viewing at {0}", model.PropertyAddress);
appointment.Location = (string.IsNullOrWhiteSpace(model.PropertyAddress)) ? "NA" : model.PropertyAddress;
appointment.BusyStatus = AppointmentBusyStatus.Tentative;
appointment.Sensitivity = AppointmentSensitivity.Public;
appointment.AllDay = false;
//var timeZoneOffset = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now);
var date = GeneralHelper.GetCombinedDateTimeStringForViewing(model.ViewingDate, model.FormattedTime);
//var startTime = new DateTimeOffset(date.Year, date.Month, date.Day, date.Hour, date.Minute, 0, TimeZoneInfo.Local.BaseUtcOffset);
appointment.StartTime = date;
appointment.Details = string.Format("Customer: {0}", model.CustomerName) + "\r"
+ string.Format("Housing Officer: {0}", (string.IsNullOrWhiteSpace(model.AssignedTo)) ? "NA" : model.AssignedTo) + "\r"
+ string.Format("Address: {0}", model.PropertyAddress) + "\r"
+ string.Format("Created by: {0}", (string.IsNullOrWhiteSpace(model.CreatorName)) ? "You" : model.CreatorName);
// Get the selection rect of the button pressed to add this appointment
var rect = GetElementRect(this.Frame as FrameworkElement);
string appointmentId = string.Empty;
// ShowAddAppointmentAsync returns an appointment id if the appointment given was added to the user's calendar.
// This value should be stored in app data and roamed so that the appointment can be replaced or removed in the future.
// An empty string return value indicates that the user canceled the operation before the appointment was added.
if (!string.IsNullOrWhiteSpace(model.OutlookIdentifier))
{
appointmentId = await AppointmentManager.ShowReplaceAppointmentAsync(model.OutlookIdentifier, appointment, rect, Placement.Default, date);
/*Appointment doesn't exist on this system, try to add a new one*/
if (string.IsNullOrWhiteSpace(appointmentId))
{
appointmentId = await AppointmentManager.ShowAddAppointmentAsync(appointment, rect, Windows.UI.Popups.Placement.Default);
}
}
else
{
appointmentId = await AppointmentManager.ShowAddAppointmentAsync(appointment, rect, Windows.UI.Popups.Placement.Default);
}
model.OutlookIdentifier = appointmentId;
result.isSuccessful = string.IsNullOrWhiteSpace(appointmentId);
result.responseObject = model;
}
else
{
result.isSuccessful = true;
result.responseObject = model;
}
return result;
}
The following line:
appointmentId = await AppointmentManager.ShowAddAppointmentAsync(appointment, rect, Windows.UI.Popups.Placement.Default);
returns empty only if user cancels the operation or there is some other issue resulting in failure in creation of appointment. I am not cancelling the operation, nor is there any raised exception so I have no idea what am I doing wrong here.
I figured it out after reading a related thread on MSDN. It was a really stupid mistake. I had forgotten to add the Appointments capability in my Package.appxmanifest file.
So the problem was, my App was not authorized to add appointments to User's calendar which is why the appointment Id was returning empty (Would have been nice if the relevant error was returned too, Microsoft).
To fix this, add the following line to your package.appxmanifest file in Capabilities:
<Capabilities>
<uap:Capability Name="appointments" />
</Capabilities>
Or alternatively, you can just click on the file, go to Capabilities tab and check the "Appointments" capability like in the screenshot below:

The account does not have permission to impersonate the requested user while saving appointment on other user's outlook calendar

I want to create appointment on outlook calendar by using EWS. I followed https://msdn.microsoft.com/en-us/library/office/dn722379(v=exchg.150).aspx link. but I am seeing this error:
"The account does not have permission to impersonate the requested user".
Please go through my 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
{
if (appointment.RequiredAttendees.Count > 0)
{
// The appointment has attendees so send them the meeting request.
appointment.Save(SendInvitationsMode.SendToAllAndSaveCopy);
}
else
{
// The appointment does not have attendees, so just save to calendar.
appointment.Save(SendInvitationsMode.SendToNone);
}
}
catch (ServiceResponseException ex)
{
Console.WriteLine(string.Format("Could not create appointment for {0}", emailAddress));
Console.WriteLine(ex.Message);
}
}
}
It seems as you only have delegate access to the calendar, you want to save appointments to.
In order to get your code working, please remove the line
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, emailAddress);
and change the Save methods like this:
appointment.Save(new FolderId(WellKnownFolderName.Calendar, new Mailbox(emailAddress)), SendInvitationsMode.SendOnlyToAllAndSaveCopy);

Editing an appointment programmatically

I'm using Microsoft.Office.Interop.Outlook to load appointments into the interface and to edit appointments . I can load appointments completely fine, editing does work but not 100% of the time. Sometimes I get the error The operation cannot be performed because the message has been changed
May I ask is there a better approach for editing appointments to avoid The operation cannot be performed because the message has been changed error. Error occurs when trying to Save()
public Outlook.AppointmentItem EditOutlookAppointment(CustomAppointment appointment, int retries = 0)
{
Outlook.AppointmentItem appointReturned = null;
try
{
Outlook.Application outlookApp = new Outlook.Application();
MAPIFolder calendarFolder = outlookApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
for (int i = calendarFolder.Items.Count; i > 0; i--)
{
var appointmentItem = ((Outlook.AppointmentItem)calendarFolder.Items[i]);
if (appointmentItem.GlobalAppointmentID == appointment.UniqueId)
{
// set some properties
appointmentItem.Subject = appointment.Subject;
appointmentItem.Body = appointment.Body;
appointmentItem.Location = appointment.Location; //Set the location
appointmentItem.Start = appointment.Start;
appointmentItem.End = appointment.End;
appointmentItem.Save();
return appointmentItem;
}
}
}
catch (Exception ex)
{
//Error message implementation here
}
return appointReturned;
}
Firstly, errors like that are unavoidable - it means the appointment was modified between the time Outlook opened it and the time you called Save. And since Outlook really likes to cache the appointments (it always caches the appointment being edited in Outlook or the previously edited appointment), that period of time can be quite large. This can happen if the appointment was modified by the Exchange server itself or by an incoming meeting update processing.
Secondly, looping through all items in the Calendar folder can be a huge performance problem. Unfortunately Outlook won't let you search (Items.Find/FindNext and Items.Restrict) on binary (PT_BINARY) properties such as GlobalAppointmentID. You'd need to use Extended MAPI (C++ or Delphi) or Redemption (I am its author - any language) for this: (RDOtems.Find/FindNext/Restrict in Redemption allow to search on binary properties).
UPDATE. The following should work using Redemption (off the top of my head):
publicRedemption.RDOAppointmentItem EditOutlookAppointment(CustomAppointment appointment, int retries = 0)
{
try
{
Outlook.Application outlookApp = new Outlook.Application();
Redemption.RDOSession session = new Redemption.RDOSession();
session.MAPIOBJECT = outlookApp.Session.MAPIOBJECT; //share the Outlook session
RDOFolder calendarFolder = session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
Redemption.RDOAppointmentItem appointmentItem = calendarFolder.Items.Find("GlobalAppointmentID = '"+appointment.UniqueId + "'");
if (appointmentItem != null)
{
// set some properties
appointmentItem.Subject = appointment.Subject;
appointmentItem.Body = appointment.Body;
appointmentItem.Location = appointment.Location; //Set the location
appointmentItem.Start = appointment.Start;
appointmentItem.End = appointment.End;
appointmentItem.Save();
return appointmentItem;
}
}
catch (Exception ex)
{
//Error message implementation here
}
return null;
}

Outlook appointment on Server not working

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)?

RemoveExtendedProperty throws error when used on an occurrence of a recurring appointment

I am developing an application that syncs an exchange calendar to another calendar. I put extended properties on the exchange appointments in order to preserve the mapping between appointments in the two calendars. Everything is working fine until I try to remove an extended property from an occurrence of a recurring appointment. When I try doing this, I get the error:
The delete action is not supported for this property.
Here is a code snippet that demonstrates the error:
public void ExchangeTest()
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1)
{
Credentials = new NetworkCredential("username", "password", "domain")
};
service.AutodiscoverUrl("username#domain.com");
Appointment appt = new Appointment(service)
{
Recurrence = new Recurrence.DailyPattern(DateTime.Now, 2) { NumberOfOccurrences = 3},
Start = DateTime.Now,
End = DateTime.Now.AddHours(2),
Subject = "Test Appointment"
};
NameResolutionCollection resolutionCollection = service.ResolveName("username", ResolveNameSearchLocation.DirectoryOnly, false);
string mailboxAddress = resolutionCollection.First().Mailbox.Address;
FolderId folderId = new FolderId(WellKnownFolderName.Calendar, mailboxAddress);
appt.Save(folderId);
PropertySet properties = new PropertySet(AppointmentSchema.ICalUid);
appt.Load(properties);
CalendarView view = new CalendarView(DateTime.Today, DateTime.Today.AddDays(8)){PropertySet = properties};
IEnumerable<Appointment> occurrences = service.FindAppointments(folderId, view)
.Where(a => a.ICalUid == appt.ICalUid);
ExtendedPropertyDefinition definition = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "TestProperty", MapiPropertyType.String);
Appointment firstOccurrence = occurrences.First();
firstOccurrence.SetExtendedProperty(definition, "test");
firstOccurrence.Update(ConflictResolutionMode.AutoResolve);
//The error occurs on the next line.
firstOccurrence.RemoveExtendedProperty(definition);
firstOccurrence.Update(ConflictResolutionMode.AutoResolve);
//clean up
appt.Delete(DeleteMode.HardDelete);
}
It appears that the error is only thrown for an Exchange 2007 server (It works on 2010). Am I doing something wrong, or is this a problem with Exchange? Is there a way to work around this issue? Any help will be appreciated.
I ended up not using the RemoveExtendedProperty function. Instead, I worked around it by just setting the property again, but setting it to an empty space. I then handled the empty space in code. This appears to be a problem with Exchange or the managed API.
Did you try;
appointment.Delete(DeleteMode.SoftDelete,SendCancellationsMode.SendToAllAndSaveCopy);

Categories