GettingStartedwiththeEWSManaged
API
Referencing the Assembly
The Exchange Web Services (EWS) Managed API consists of a single assembly,
Microsoft.Exchange.WebServices.dll, and an accompanying IntelliSense XML file,
Microsoft.Exchange.WebServices.xml.
Drop these two files into the folder of your choice. Then, from your Microsoft Visual Studio project, add
a reference to Microsoft.Exchange.WebServices.dll, and add a using clause for the
Microsoft.Exchange.WebServices.Data namespace.
Using the EWS Managed API against a Test Server
Test servers are deployed with self-signed certificates, which are not trusted by the Microsoft .NET
Framework. If you use the EWS Managed API against a test server, you might receive the following error:
To resolve this issue, include the following code in your application:
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
// Hook up the cert callback.
System.Net.ServicePointManager.ServerCertificateValidationCallback =
Object obj,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors errors)
delegate(
{
// Validate the certificate and return true or false as appropriate.
// Note that it not a good practice to always return true because not
// all certificates should be trusted.
};
Accessing EWS By Using the EWS Managed API
To access EWS by using the EWS Managed API, all you need is an instance of the ExchangeService class,
as shown in the following example.
ExchangeService service = new ExchangeService();
// Setting credentials is unnecessary when you connect from a computer that is
// logged on to the domain.
service.Credentials = new WebCredentials("username", "password", "domain");
// Or use NetworkCredential directly (WebCredentials is a wrapper
// around NetworkCredential).
service.Credentials = new NetworkCredential("username", "password", "domain");
Setting the URL of the Service
You can set the URL of the service in one of two ways:
Manually, if you know the URL of Exchange Web Services or if you have previously determined it
via the Autodiscover service.
By using the Autodiscover service.
To set the URL manually, use the following:
service.Url = new Uri("");
To set the URL by using Autodiscover, use the following:
service.AutodiscoverUrl("");
We recommend that you use the Autodiscover service, for the following reasons:
Autodiscover determines the best endpoint for a given user (the endpoint that is closest to the
user’s Mailbox server).
The EWS URL might change as your administrators deploy new Client Access servers.
You can safely cache the URL that is returned by the Autodiscover service and reuse it. Autodiscover
should be called periodically, or when EWS connectivity to a given URL is lost.
Note that you should either set the URL manually or call AutodiscoverUrl, but you should not do both.
Important: The EWS Managed API follows a series of steps to determine the endpoint of the
Autodiscover service for a given e-mail address. Those steps may include DNS-based redirections to
potentially unsafe locations (in the case of a DNS spoofing attack, for example).
By default, AutodiscoverUrl will never follow redirections and will throw an exception when it
determines that a redirection is necessary.
To allow AutodiscoverUrl to follow redirections, you must implement a URL validation callback and use
an overload of the AutodiscoverUrl, as follows:
// Validate the URL and return true to allow the redirection or false to prevent it.
private static bool ValidateRedirectionUrlCallback(string url)
{
}
public void Example()
{
…
service.AutodiscoverUrl("", ValidateRedirectionUrlCallback);
…
}
You should never return true unconditionally from your URL validation callback. Additionally, only
redirections to SSL endpoints should be allowed (URLs that start with https://).
Items
The EWS Managed API defines a class hierarchy of items. Each class in the hierarchy maps to a given
item type in Exchange. For example, the EmailMessage class represents e-mail messages and the
Appointment class represents calendar events and meetings.
The following figure shows the EWS Managed API item class hierarchy.
Folders
The EWS Managed API also defines a class hierarchy for folders, as shown in the following figure.
Item and Folder Identifiers
Items and folders in Exchange are uniquely identified. In the EWS Managed API, items and folders have
an ID property that holds their Exchange unique identity. The ID of an item is of type ItemId; the ID of a
folder is of type FolderId.
Binding to an Existing Item
If you know the unique identifier of an e-mail message and want to retrieve its details from Exchange,
you have to write the following:
// Bind to an existing message using its unique identifier.
EmailMessage message = EmailMessage.Bind(service, new ItemId(uniqueId));
// Write the sender's name.
Console.WriteLine(message.Sender.Name);
If you do not know what type of item the unique identifier maps to, you can also write the following:
// Bind to an existing item using its unique identifier.
Item item = Item.Bind(service, new ItemId(uniqueId));
if (item is EmailMessage)
{
// If the item is an e-mail message, write the sender's name.
Console.WriteLine((item as EmailMessage).Sender.Name);
}
else if (item is Appointment)
{
// If the item is an appointment, write its start time.
Console.WriteLine((item as Appointment).Start);
}
else
{
}
// Handle other types.
Binding to an Existing Folder
Bind to an existing folder in the same way that you bind to an existing item.
// Bind to an existing folder using its unique identifier.
Folder folder = Folder.Bind(service, new FolderId(uniqueId));
You can also bind to a well-known folder (Inbox, Calendar, Tasks, and so on) without knowing its ID.
// Bind to the Inbox.
Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);
Sending a Message
EmailMessage message = new EmailMessage(service);
message.Subject = "Hello world!";
message.Body = "Sent using the EWS Managed API.";
message.ToRecipients.Add("someone@contoso.com");
message.SendAndSaveCopy();
Replying To/Forwarding a Message
public void ReplyToMessage(EmailMessage messageToReplyTo, string reply)
{
messageToReplyTo.Reply(reply, true /* replyAll */);
// Or
ResponseMessage responseMessage = messageToReplyTo.CreateReply(true);
responseMessage.BodyPrefix = reply;
responseMessage.CcRecipients.Add("someone@contoso.com");
responseMessage.SendAndSaveCopy();
}
Use .Forward or .CreateForward to forward a message.
Creating a Recurring Appointment
Appointment appointment = new Appointment(service);
appointment.Subject = "Meditation";
appointment.Body = "My weekly relaxation time.";
appointment.Start = new DateTime(2008, 1, 1, 18, 0, 0);
appointment.End = appointment.Start.AddHours(2);
// Occurs every weeks on Tuesday and Thursday
appointment.Recurrence = new Recurrence.WeeklyPattern(
new DateTime(2008, 1, 1),
2,
DayOfWeek.Tuesday,
DayOfWeek.Thursday);
appointment.Save();
Inviting Attendees to the Previously Created Appointment to Make it a
Meeting
appointment.RequiredAttendees.Add("someone@contoso.com");
appointment.Update(ConflictResolutionMode.AutoResolve);
Note: You can also do this when you create the meeting.
Creating a Personal Distribution List
DistributionList distributionList = new DistributionList(service);
distributionList.DisplayName = "My DL";
distributionList.Members.Add(new DistributionListMember("Jane Dow", "jane.dow@contoso.com"));
distributionList.Save();
Deleting an Item of Any Type
message.Delete(DeleteMode.HardDelete);
Creating a Folder
Folder folder = new Folder(service);
folder.DisplayName = "This is a new folder";
// Creates the folder as a child of the Inbox folder.
folder.Save(WellKnownFolderName.Inbox);
Searching
List the first ten items in the Inbox
public void ListFirstTenItems()
{
FindItemsResults- findResults = service.FindItems(
WellKnownFolderName.Inbox,
new ItemView(10));
foreach (Item item in findResults.Items)
{
}
// Do something with the item.
}
Retrieve all the items in the Inbox by groups of 50 items
public void PageThroughEntireInbox()
{
ItemView view = new ItemView(50);
FindItemsResults
- findResults;
do
{
findResults = service.FindItems(WellKnownFolderName.Inbox, view);
foreach (Item item in findResults.Items)
{
}
view.Offset += 50;
// Do something with the item.
} while (findResults.MoreAvailable);
}
Find the first 10 messages in the Inbox that have a subject that contains the
words "EWS" or "API", order by date received, and only return the Subject and
DateTimeReceived properties
public void FindItems()
{
ItemView view = new ItemView(10);
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Ascending);
view.PropertySet = new PropertySet(
BasePropertySet.IdOnly,
ItemSchema.Subject,
ItemSchema.DateTimeReceived);
FindItemsResults
- findResults = service.FindItems(
WellKnownFolderName.Inbox,
new SearchFilter.SearchFilterCollection(
LogicalOperator.Or,
new SearchFilter.ContainsSubstring(ItemSchema.Subject, "EWS"),
new SearchFilter.ContainsSubstring(ItemSchema.Subject, "API")),
view);
Console.WriteLine("Total number of items found: " + findResults.TotalCount.ToString());
foreach (Item item in findResults)
{
// Do something with the item.
}
}
Find all child folders of the Inbox folder
public void FindChildFolders()
{
FindFoldersResults findResults = service.FindFolders(
WellKnownFolderName.Inbox,
new FolderView(int.MaxValue));
foreach (Folder folder in findResults.Folders)
{
}
// Do something with the folder.
}
Get all appointments between startDate and endDate in the specified folder,
including recurring meeting occurrences
public void FindAppointments(CalendarFolder folder, DateTime startDate, DateTime endDate)
{
FindItemsResults
findResults = folder.FindAppointments(
new CalendarView(startDate, endDate));
foreach (Appointment appointment in findResults.Items)
{
}
// Do something with the appointment.
}
Resolving an Ambiguous Name
// Resolve a partial name against the Active Directory and the Contacts folder (in that order).
NameResolutionCollection nameResolutions = service.ResolveName(
"ambiguous name",
NameResolutionSearchScope.ActiveDirectoryContacts,
true /* returnFullContactData */);
foreach (NameResolution nameResolution in nameResolutions)
{
Console.WriteLine(nameResolution.Mailbox.Name);
Console.WriteLine(nameResolution.Contact.PhoneNumbers[PhoneNumberKey.BusinessPhone]);
// Do additional things with the name resolution.
}
Extended Properties
Items in the EWS Managed API expose strongly typed, first-class properties that provide easy access to
the most commonly used properties (for example, Item.Subject, Item.Body,
EmailMessage.ToRecipients, Appointment.Start and Contact.Birthday). Exchange allows for additional
properties to be added to items. Exchange Web Services calls these Extended Properties.
To stamp an e-mail message with a custom extended property, do the following:
// Create a new e-mail message.
EmailMessage message = new EmailMessage(service);
message.Subject = "Message with custom extended property";
// Define a property set identifier. This identifier should be defined once and
// reused wherever the extended property is accessed. For example, you can
// define one property set identifier for your application and use it for all the
// custom extended properties that your application reads and writes.
//
// NOTE: The following is JUST AN EXAMPLE. You should generate NEW GUIDs for your
// property set identifiers. This way, you will ensure that there won't be any conflict
// with the extended properties your application sets and the extended properties
// other applications set.
Guid yourPropertySetId = new Guid("{01638372-9F96-43b2-A403-B504ED14A910}");
// Define the extended property itself.
ExtendedPropertyDefinition extendedPropertyDefinition = new ExtendedPropertyDefinition(
yourPropertySetId,
"MyProperty",
MapiPropertyType.String);
// Stamp the extended property on a message.
message.SetExtendedProperty(extendedPropertyDefinition, "MyValue");
// Save the message.
message.Save();
To retrieve the value of this extended property when binding to an existing message, do the following:
// Define a property set that includes all first class porperties and the
// custom extended property.
PropertySet propertySet = new PropertySet(
BasePropertySet.FirstClassProperties,
extendedPropertyDefinition);
// Bind to the message by using the property set.
EmailMessage message = EmailMessage.Bind(
service,
new ItemId(uniqueId),
propertySet);
// Write the values of the extended properties.
foreach (ExtendedProperty extendedProperty in message.ExtendedProperties)
{
}
Console.WriteLine(extendedProperty.Value);
Availability Service
The EWS Managed API makes it very easy to consume the Availability service. The Availability service
makes it possible to retrieve free/busy information for users on which the caller does not necessarily
have access rights. It also provides meeting time suggestions.
The following example shows how to call the Availability service by using the EWS Managed API.