Skip to content

Instantly share code, notes, and snippets.

@ryancollingwood
Last active November 14, 2016 22:26
Show Gist options
  • Save ryancollingwood/0bec04df27b33c609a860e6c747212bb to your computer and use it in GitHub Desktop.
Save ryancollingwood/0bec04df27b33c609a860e6c747212bb to your computer and use it in GitHub Desktop.
A Class Encapsulating The Microsoft Exchange 2007 Managed Api. Some methods are not available on Exchange Server 2007, particularly meeting rooms. Will require a reference to Microsoft.Exchange.WebServices
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Exchange.WebServices.Data;
using System.Net;
namespace ExchangeConnector
{
/// <summary>
/// <br>A Class Encapsulating The Microsoft Exchange Managed Api</br>
/// <br>Some methods are not available on Exchange Server 2007, particularly meeting rooms</br>
/// <br>Will require a reference to Microsoft.Exchange.WebServices</br>
/// </summary>
public class Connection
{
private ExchangeService _exchangeService = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
private String SMTPAddress = String.Empty;
public ExchangeService exchangeService
{
get { return _exchangeService; }
}
/// <summary>
/// Connect To Exchange Server using User Impersonation
/// </summary>
/// <param name="UserName">String - Username Without Domain</param>
/// <param name="Password">String - User Password</param>
/// <param name="Domain">String - User Domain</param>
/// <param name="Email">String - User Email Address, used in finding the Exchange Server</param>
public Connection(String UserName, String Password, String Domain, String Email)
{
this.SMTPAddress = Email;
_exchangeService.Credentials = new NetworkCredential(UserName, Password, Domain);
_exchangeService.AutodiscoverUrl(Email);
}
/// <summary>
/// Connect To Exchange Server as User
/// </summary>
/// <param name="Email">String - User Email Address Used In Discovery Of Exchange Server</param>
public Connection(String Email)
{
this.SMTPAddress = Email;
_exchangeService.UseDefaultCredentials = true;
_exchangeService.AutodiscoverUrl(Email);
}
/// <summary>
/// Create A New Appointment
/// </summary>
/// <param name="Title">String - Appointment Title</param>
/// <param name="Body">String - Appointment Details</param>
/// <param name="Start">DateTime - Appointment Start</param>
/// <param name="End">DateTime - Appointment End</param>
/// <param name="IsAllDay">bool - All Day Event</param>
public void CreateAppointment(string Title, string Body, DateTime Start, DateTime End, bool IsAllDay)
{
this.CreateAppointment(Title, Body, Start, End, IsAllDay, DateTime.MinValue, SendInvitationsMode.SendToNone, LegacyFreeBusyStatus.Free);
}
/// <summary>
/// Create A New Appointment
/// </summary>
/// <param name="Title">String - Appointment Title</param>
/// <param name="Body">String - Appointment Details</param>
/// <param name="Start">DateTime - Appointment Start</param>
/// <param name="End">DateTime - Appointment End</param>
/// <param name="IsAllDay">bool - All Day Event</param>
/// <param name="Reminder">DateTime - Appointment Reminder, if DateTime.Min no reminder is set</param>
/// <param name="SendInvitations">SendInvitationsMode - Send Invitations Mode</param>
/// <param name="FreeBusyStatus">LegacyFreeBusyStatus - Mark the time as Busy or Free in Calender. Set to LegacyFreeBusyStatus.Free for events such as sports seasons.</param>
/// <param name="Catagories">String[] - Catagories This Appointment Falls Under. If not in the Exchange master catagory list and not in the users catagory list, will appear without visual colour information</param>
/// <param name="RequiredAttendeesID">String[] - Unique IDs of Required Attendees</param>
/// <param name="OptionalAttendessID">String[] - Unique IDs of Optional Attendees</param>
public void CreateAppointment(
String Title,
String Body,
DateTime Start,
DateTime End,
bool IsAllDay,
DateTime Reminder,
SendInvitationsMode SendInvitations,
LegacyFreeBusyStatus FreeBusyStatus,
String[] Catagories = null,
String[] RequiredAttendeesID = null,
String[] OptionalAttendessID = null
)
{
Appointment newAppointment = new Appointment(_exchangeService);
newAppointment.Subject = Title;
newAppointment.Body = Body;
newAppointment.IsAllDayEvent = IsAllDay;
newAppointment.Start = Start;
newAppointment.End = End;
if (Reminder == DateTime.MinValue)
{
newAppointment.IsReminderSet = false;
}
else
{
newAppointment.IsReminderSet = true;
newAppointment.ReminderDueBy = Reminder;
}
AddContactAddress(newAppointment, RequiredAttendeesID, true);
AddContactAddress(newAppointment, OptionalAttendessID, false);
foreach (String sCat in Catagories)
{
newAppointment.Categories.Add(sCat);
}
newAppointment.LegacyFreeBusyStatus = FreeBusyStatus;
newAppointment.Save(SendInvitations);
}
/// <summary>
/// Delete An Appointment
/// </summary>
/// <param name="ID">String - Unique ID of Appointment</param>
/// <param name="SendCancellations">bool - Send Cancellations or Stealthy Delete</param>
public void DeleteAppointment(string ID, bool SendCancellations)
{
Appointment appDelete = Appointment.Bind(_exchangeService, new ItemId(ID));
if (appDelete == null)
{
return;
}
appDelete.Delete(DeleteMode.MoveToDeletedItems, SendCancellationsMode.SendOnlyToAll);
}
/// <summary>
/// Add Attnedess To An Appointment
/// </summary>
/// <param name="Appointment">Appointment - Instance to be updated</param>
/// <param name="Addresses">String[] - Array of Contact/Contact Group Unique IDs</param>
/// <param name="IsRequired">bool - Required or Optional Attendees</param>
private void AddContactAddress(Appointment Appointment, String[] Addresses, bool IsRequired)
{
if (Addresses != null)
{
foreach (String item in Addresses)
{
var con = Item.Bind(_exchangeService, item);
if (con.GetType() == typeof(ContactGroup))
{
AddContactGroupAddress(Appointment, item, IsRequired);
continue;
}
EmailAddress conEmail = new EmailAddress();
if (((Contact)con).EmailAddresses.TryGetValue(EmailAddressKey.EmailAddress1, out conEmail))
{
if (IsRequired)
{
Appointment.RequiredAttendees.Add(conEmail.Address);
}
else
{
Appointment.OptionalAttendees.Add(conEmail.Address);
}
}
}
}
}
/// <summary>
/// Add members of Contact Group To An Appointment
/// </summary>
/// <param name="Appointment">Appointment - Appointment </param>
/// <param name="GroupID">String - Unique identity of the contact group</param>
/// <param name="IsRequired">Boolean - Required or Optional Attendee</param>
private void AddContactGroupAddress(Appointment Appointment, String GroupID, bool IsRequired)
{
ContactGroup con = ContactGroup.Bind(_exchangeService, GroupID);
// GroupMember Functions Only Implement in Exchange Server > 2007
if (_exchangeService.RequestedServerVersion == ExchangeVersion.Exchange2007_SP1)
{
ExpandGroupResults groupResults = _exchangeService.ExpandGroup(con.Id);
foreach (var member in groupResults)
{
if (IsRequired)
{
Appointment.RequiredAttendees.Add(member.Address);
}
else
{
Appointment.OptionalAttendees.Add(member.Address);
}
}
}
else
{
foreach (GroupMember itemGroupMember in con.Members)
{
if (IsRequired)
{
Appointment.RequiredAttendees.Add(itemGroupMember.AddressInformation.Address);
}
else
{
Appointment.OptionalAttendees.Add(itemGroupMember.AddressInformation.Address);
}
}
}
}
/// <summary>
/// Return Appointments In The Exchange Calendar
/// </summary>
/// <param name="AStart">DateTime - Start Date For Matching Appointments</param>
/// <param name="AEnd">DateTime - End Date For Matching Appointments</param>
/// <returns></returns>
public FindItemsResults<Appointment> FindAppointments(DateTime AStart, DateTime AEnd)
{
CalendarView calendarView = new CalendarView(AStart, AEnd);
return _exchangeService.FindAppointments(WellKnownFolderName.Calendar, calendarView);
}
/// <summary>
/// Return an Appointment By Unique ID
/// </summary>
/// <param name="ID">String - Appoint Unique ID</param>
/// <returns></returns>
public Appointment GetAppointmentByID(String ID)
{
Appointment current = Appointment.Bind(_exchangeService, ID);
return current;
}
/// <summary>
/// Gets the object id string from uid.
/// <remarks>The UID is formatted as a hex-string and the GlobalObjectId is displayed as a Base64 string.</remarks>
/// </summary>
/// <param name="id">The uid.</param>
/// <returns></returns>
private String GetObjectIdStringFromUid(String id)
{
var buffer = new byte[id.Length / 2];
for (int i = 0; i < id.Length / 2; i++)
{
var hexValue = byte.Parse(id.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
buffer[i] = hexValue;
}
return Convert.ToBase64String(buffer);
}
/// <summary>
/// Find Exchange Contacts In User Address Book
/// </summary>
/// <param name="Search">String - Substring To Match Display Name On</param>
/// <returns></returns>
public FindItemsResults<Item> FindPeople(String Search)
{
ItemView result = new ItemView(100) { PropertySet = new PropertySet(BasePropertySet.FirstClassProperties) };
SearchFilter FinalsearchFilter = new SearchFilter.ContainsSubstring(ContactSchema.DisplayName, Search);
return this._exchangeService.FindItems(WellKnownFolderName.Contacts, FinalsearchFilter, result);
}
/// <summary>
/// Return (maximum 1000) Contacts In Exchange Address Book
/// </summary>
/// <returns></returns>
public FindItemsResults<Item> GetContacts()
{
ItemView result = new ItemView(1000) { PropertySet = new PropertySet(BasePropertySet.FirstClassProperties) };
SearchFilter FinalsearchFilter = new SearchFilter.Exists(ContactSchema.DisplayName);
return this._exchangeService.FindItems(WellKnownFolderName.Contacts, FinalsearchFilter, result);
}
// RYCOL: Presently unable to enumerate delegate access via Exchange Webservices Due to Configuration
// issue with Exchange 2007 :/
/*
/// <summary>
/// Does the passed email account have delegate access to the Current Exchange Account
/// </summary>
/// <param name="EmailAddress"></param>
/// <returns></returns>
public bool AllowedAccess(String EmailAddress)
{
UserId passedUser = new UserId(EmailAddress);
Mailbox mail = new Mailbox(this.SMTPAddress);
DelegateInformation delegates = _exchangeService.GetDelegates(mail, true);
foreach (DelegateUserResponse item in delegates.DelegateUserResponses)
{
if (item.DelegateUser.UserId.SID == passedUser.SID)
{
return true;
}
}
return false;
}
*/
/// <summary>
/// Finds the related appiontment.
/// </summary>
/// <param name="apptRequest">The appt request.</param>
/// <returns></returns>
private Appointment FindRelatedAppiontment(Appointment apptRequest)
{
var filter = new SearchFilter.IsEqualTo
{
PropertyDefinition = new ExtendedPropertyDefinition
(DefaultExtendedPropertySet.Meeting, 0x03, MapiPropertyType.Binary),
Value = GetObjectIdStringFromUid(apptRequest.ICalUid) //Hex value converted to byte and base64 encoded
};
var view = new ItemView(1) { PropertySet = new PropertySet(BasePropertySet.FirstClassProperties) };
return _exchangeService.FindItems(WellKnownFolderName.Calendar, filter, view).Items[0] as Appointment;
}
/// <summary>
/// Returns Master Category List
/// </summary>
/// <remarks>Only Works In Exchange Server 2010</remarks>
/// <returns></returns>
public MasterCategoryList.MasterCategoryList MasterCategoryList()
{
return ExchangeConnector.MasterCategoryList.MasterCategoryList.Bind(_exchangeService);
}
}
}
@ryancollingwood
Copy link
Author

For interacting with a Microsoft Exchange Server 2007
It's a little late, but at this point if you're still in 2007 land, you're more than welcome to my code 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment