原文 Office 365 – Exchange Online examples

2012 is upon us and here’s wishing you all a very happy and prosperous new year! Last year we’ve taken a quick look at What Exchange Online extensibility is and what you can use it for, and in today’s post we’ll take a bit more of a hands-on approach and look at some examples of performing various tasks in Exchange Online using the Exchange Web Services API.

Let’s jump straight into some code by creating a new console application in Visual Studio 2010:

Add a reference to Microsoft.Exchange.WebServices.dll, you’ll find it the C:\Program Files\Microsoft\Exchange\Web Services\1.1 folder. If you do not have the Microsoft.Exchange.WebServices dll, you probably do not have the Exchange Web Services Managed API installed. You can download it from the Microsoft Download Center.

Connecting to the Exchange Service

Before you can perform any task or run any queries against Exchange Online, you need to connect to the Exchange Online service. To do this you use the ExchangeService object.

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
service.Credentials = new WebCredentials("user@domain.com", "UserPassword");
service.AutodiscoverUrl("user@domain.com", RedirectionUrlValidationCallback);

Although the AutodiscoverUrl method has a constructor that only takes the user’s e-mail address; it will always throw an exception if the validateRedirectionUrlCallback parameter is not specified. The RedirectionUrlValidationCallback method should verify that the redirection address is valid and as a best practise, should never return true unconditionally.

static bool RedirectionUrlValidationCallback(String redirectionUrl)
{
bool redirectionValidated = false;
if (redirectionUrl.Equals(
"https://autodiscover-s.outlook.com/autodiscover/autodiscover.xml"))
redirectionValidated = true;
 
return redirectionValidated;
}

Creating a contact

With the serviced code in place, we can now create a contact with the following code:

// Create the Contact
Contact newContact = new Contact(service);
newContact.GivenName = "John";
newContact.Surname = "Smith";
newContact.FileAsMapping = FileAsMapping.GivenNameSpaceSurname;
newContact.CompanyName = "Smith & Smith Inc.";
newContact.JobTitle = "CEO";
newContact.AssistantName = "Pocahontas";
newContact.Body = "Captain John Smith (c. January 1580 – 21 June 1631) Admiral " +
"of New England was an English soldier, explorer, and author. He was knighted " +
"for his services to Sigismund Bathory, Prince of Transylvania and friend Mozes Szekely.";
// Add E-mail Addresses
EmailAddress contactEmail1 = new EmailAddress("Work", "johnS@s-and-s.com");
EmailAddress contactEmail2 = new EmailAddress("Home", "john@gmail.com");
newContact.EmailAddresses[EmailAddressKey.EmailAddress1] = contactEmail1;
newContact.EmailAddresses[EmailAddressKey.EmailAddress2] = contactEmail2;
//Add Contact Photo
FileAttachment contactPhoto =
newContact.Attachments.AddFileAttachment(@"C:\Temp\JohnSmith.png");
contactPhoto.IsContactPhoto = true;
//Add Extended Property
Guid propertySetId = new Guid("{F4FD924D-5489-4AE1-BD43-25491342529B}");
ExtendedPropertyDefinition clientIdPropertyDefinition =
new ExtendedPropertyDefinition(propertySetId, "ClientId", MapiPropertyType.String);
newContact.SetExtendedProperty(clientIdPropertyDefinition, "SMITHINC");
 
newContact.Save();

The code will seem familiar if you worked with the Outlook Object model before. However, there are a number of differences: in the first part of the method, we set the standard Exchange properties. We then add 2 e-mail addresses to the contact; each e-mail address can have a descriptive name.

Next, an image is added to the contact as a file attachment. Setting the IsContactPhoto property to true will set the attached file as the contact’s picture. Finally, we add an extended property to the contact. A GUID is declared as the propertySetId, this only needs to be declared once and should be reused when accessing the extended property. You can define one property set identifier and use it for all the extended properties that get read or written to throughout your application.

When you run this code you should see the new contact in the Outlook Web app:

If you need to create a new contact in Outlook, see this post How to create a new Outlook Contact item programmatically.

Finding contacts by name

To search for a contact in Exchange Online use the following code:

static void FindContactsByGivenName()
{
string search = "John";
FindItemsResults<Item> foundItems =
service.FindItems(WellKnownFolderName.Contacts,
new SearchFilter.IsEqualTo(ContactSchema.GivenName, search),
new ItemView(5));
 
foreach (Item item in foundItems)
{
if (item is Contact)
{
Contact foundContact = (Contact)item;
Console.WriteLine(String.Format("{0} - {1}",
foundContact.CompleteName.FullName,
foundContact.CompanyName));
}
}
}

In the above code, we created a new FindItemResults collection and set it equal to the return value of the services’ FindItems method. The FindItems method accepts three parameters:

  • the first is an enumeration value specifying which folder to search;
  • the second is a new instance of a SearchFilter object, where we specify on what criteria we want to search; and
  • lastly we pass in a new instance of an ItemView object where we set the number of records to return. We then loop through the foundItems collection and print the contact details.

Finding contacts by Extended property

You can also search for an item based on the values in an extended property:

static void FindContactByExtendedProperty()
{
string search = "SMITHINC";
ExtendedPropertyDefinition clientIdPropertyDefinition =
new ExtendedPropertyDefinition(propertySetId, "ClientId",
MapiPropertyType.String);
 
FindItemsResults<Item> foundItems =
service.FindItems(WellKnownFolderName.Contacts,
new SearchFilter.IsEqualTo(clientIdPropertyDefinition, search),
new ItemView(5));
 
foreach (Item item in foundItems)
{
if (item is Contact)
{
Contact foundContact = (Contact)item;
Console.WriteLine(String.Format("{0} - {1}",
foundContact.CompleteName.FullName,
foundContact.CompanyName));
}
}
 
}

The above code is similar to searching for a contact by name except that we first declare a reference to the extended property we’ve created earlier. You’ll notice we’re reusing the Property Set Id which was declared earlier. We then pass the clientIdPropertyDefinition as a parameter for the SearchFilter. The result is a list of all contacts whose ClientId extended property has a value of "SMITHINC"

Updating contacts

Update the contact with the following code:

static void UpdateContact(string email = "johnS@s-and-s.com")
{
FindItemsResults<Item> foundItems =
service.FindItems(WellKnownFolderName.Contacts,
new SearchFilter.IsEqualTo(ContactSchema.EmailAddress1, email),
new ItemView(5));
 
Item foundItem = foundItems.FirstOrDefault();
if (foundItem != null && foundItem is Contact)
{
Contact foundContact = (Contact)foundItem;
foundContact.JobTitle = "Chief Operating Officer";
foundContact.Update(ConflictResolutionMode.AutoResolve);
}
}

The code above first searches for a contact by e-mail address, if the contact is found we set the JobTitleproperty and call the Update method on the Contact object. The Update method accepts an enumeration parameter ConflictResolutionMode. Possible values for the parameter are:

  • ConflictResolution.AlwaysOverwrite – Any local property changes will overwrite any server-side changes.
  • ConflictResolution.AutoResolve – Unless the server-side copy is more recent than the local copy, its values will be overwritten by any local property changes.
  • ConflictResolution.NeverOverwrite – All local property changes are discarded.

If you compiled the code and ran it again, you would be able to see that John Smith’s Job Title has changed.

Creating and sending an e-mail message

Creating and sending an e-mail is also similar to the Outlook object model:

static void CreateAndSendEmail()
{
EmailMessage email = new EmailMessage(service);
email.ToRecipients.Add(new EmailAddress(userEmail));
email.Subject = "Sending from EWS";
email.Body = "Hi There, this was sent using Exchange Web Services. Pretty neat!";
 
email.Attachments.AddFileAttachment(@"C:\Temp\JohnSmith.png");
email.SendAndSaveCopy();
}

In the code above, we created a new e-mail message and added an EmailAddress object to its ToRecipientscollection. Adding an attachment is done in a similar fashion as with the contact previously. When you want to send the e-mail you have a choice between two methods on the EmailMessage object: Send orSendAndSaveCopy. The SendAndSaveCopy method sends the e-mail and saves a copy of it to the Sent Items folder. The Send method sends the e-mail and does not store a copy of it.

Once your e-mail is sent, you should see it in your Office 365 Outlook Inbox.

If you need to create and send an e-mail in Outlook, see this post How to create and send an Outlook message programmatically.

Finding e-mails by subject

Finding email is similar to searching for contacts:

static void FindEmailBySubject(string subject = "Sending from EWS")
{
FindItemsResults<Item> foundItems =
service.FindItems(WellKnownFolderName.Inbox,
new SearchFilter.IsEqualTo(EmailMessageSchema.Subject, subject),
new ItemView(5));
 
foreach (Item item in foundItems)
{
if (item is EmailMessage)
{
EmailMessage foundEmail = (EmailMessage)item;
Console.WriteLine("From Address: " + foundEmail.From.Name);
Console.WriteLine("Received: " +
foundEmail.DateTimeReceived.ToShortDateString());
Console.WriteLine("----------------------------");
}
}
}

The only difference between this code and searching for contacts is the WellKnowFolderName and theSearchFilter‘s parameter.

For an Outlook sample, see How to use Find and FindNext methods to retrieve Outlook mail items.

Creating appointments

To create an appointment in the default calendar use the following code:

static void CreateAppointment()
{
Appointment app = new Appointment(service);
app.Subject = "Meet George";
app.Body = "You need to meet George";
app.Location = "1st Floor Boardroom";
app.Start = DateTime.Now.AddHours(2);
app.End = DateTime.Now.AddHours(3);
app.IsReminderSet = true;
app.ReminderMinutesBeforeStart = 15;
app.RequiredAttendees.Add(new Attendee(userEmail));
app.Save(SendInvitationsMode.SendToAllAndSaveCopy);
}

This code creates an appointment in the default calendar and sends a meeting request to the logged-in user. The Save method accepts the SendInvitationsMode enumeration as parameter and possible values for this are:

  • SendInvitationsMode.SendOnlyToAll – Sends meeting invitations to all attendees, but does not save a copy of the meeting invitation in the organizer’s Sent Items folder.
  • SendInvitationsMode.SendToAllAndSaveCopy – Will send the meeting invitation to all attendees and save a copy of it in the organizer’s Sent Items folder.
  • SendInvitationsMode.SendToNone – Will not send any meeting invitations.

Once created you should see the meeting in your Office 365 Outlook Calendar.

If you develop for Outlook, see How to create a new Outlook Appointment item.

Find appointments for today and tomorrow

To find any appointments for today and tomorrow you can use the following code:

static void FindAppointmentsForTodayTomorrow()
{
FindItemsResults<Appointment> foundAppointments =
service.FindAppointments(WellKnownFolderName.Calendar,
new CalendarView(DateTime.Now, DateTime.Now.AddDays(1)));
 
foreach (Appointment app in foundAppointments)
{
Console.WriteLine("Subject: " + app.Subject);
Console.WriteLine("Start: " + app.Start);
Console.WriteLine("Duration: " + app.Duration);
Console.WriteLine("------------------------");
}
}

The code is similar to finding e-mails or contacts, except the FindItemsResults collection contains anAppointment object and we used the FindAppointments method of the ExchangeService object to find the appointments. The filter is applied using a CalendarView object.

Creating folders

Creating folders in Exchange online can easily be done using the code below:

static void CreateFolder()
{
Folder readLaterFolder = new Folder(service);
readLaterFolder.DisplayName = "Read Later";
readLaterFolder.Save(WellKnownFolderName.Inbox);
 
Folder workEmailFolder = new Folder(service);
workEmailFolder.DisplayName = "Work mail";
workEmailFolder.Save(readLaterFolder.Id);
}

You can create a folder by declaring a new Folder object and setting its DisplayName property. The Savemethods required the parent folder to be specified, you can pass in a WellKnownFolderName enumeration value or an existing folders’ Id.

You will notice two new folders in your Office 365 Outlook:

List Inbox sub-folders

To list the sub-folders in the Inbox use the following code:

static void ListFoldersInInbox()
{
FindFoldersResults findResults = service.FindFolders(WellKnownFolderName.Inbox,
new FolderView(10));
 
foreach (Folder folder in findResults.Folders)
{
Console.WriteLine(folder.DisplayName);
}
}

In the code above we declare a FindFoldersResults object and set it equal to the return value of the FindFolders method on the ExchangeService object. The FindFolders method accepts either aWellKnownFolderName enumeration value or the Id of an existing folder.

Out of office

Exchange web services allow you not only to create and edit Exchange items but also to leverage its business logic. For example the following code will enable the specified user’s Out of office message:

static void SetOutOfOffice()
{
OofSettings settings = new OofSettings();
settings.State=OofState.Enabled;
settings.InternalReply = new OofReply(
"Hi Team Member, I'm out on my 2 day break. Back Soon!");
settings.ExternalReply = new OofReply(
"Dear Customer, I'm currently out of the office. " +
"Please forward all queries to Sam at sam@s-and-s.com");
settings.ExternalAudience = OofExternalAudience.Known;
service.SetUserOofSettings(userEmail,settings);
}

By setting the State property you either enable or disable the Out of Office notification, setting it to Scheduled and specifying the Duration allow you to schedule the Out of Office notification for a later date. You also have the choice to specify different messages for internal or external addresses as well as which audience to send the response to.

You can not only set the user’s Out of Office status but can also get another user’s Out of Office status by using the following code:

static void GetOutOfOffice()
{
OofSettings settings = service.GetUserOofSettings(userEmail);
if (settings.State == OofState.Enabled)
{
Console.WriteLine("You are currently OUT of the office");
}
else if (settings.State == OofState.Scheduled)
{
Console.WriteLine("You are currently OUT of the office and will return on " +
settings.Duration.EndTime.ToLongDateString());
}
else
{
Console.WriteLine("You are currently IN the office");
}
}

Availability

You can also check a users’ availability using the EWS API. In the following example I used theGetUserAvailability method of the ExchangeService object to get an AttendeeAvailability object

static void GetAvailability()
{
List<AttendeeInfo> attendees = new List<AttendeeInfo>();
attendees.Add(new AttendeeInfo(userEmail));
 
GetUserAvailabilityResults results =
service.GetUserAvailability(attendees,
new TimeWindow(DateTime.Now, DateTime.Now.AddHours(24)),
AvailabilityData.FreeBusy);
 
AttendeeAvailability myAvailablity =
results.AttendeesAvailability.FirstOrDefault();
if (myAvailablity != null)
{
Console.WriteLine(String.Format(
"You have {0} appointments/meetings in the next 24 hours",
myAvailablity.CalendarEvents.Count));
}
}

There you have it, a crash course in some of the functionality available to you as developer when using Exchange Web services with Office 365. Please see the attached sample project for the code to all the above examples.

Thank you for reading. Until next time, keep coding!

Available downloads:

C# sample project

Office 365 – Exchange Online examples的更多相关文章

  1. Exchange & Office 365最小混合部署

    前言 这篇文章的主题是混合部署~ 混合使得本地组织和云环境像一个单一的.协作紧密的组织一样运作.当组织决定进行混合部署,达到本地Exchange Server和Office 365共存的状态时,就会面 ...

  2. 使用Powershell链接到Office 365

    今天主要讲使用Powershell管理Office 365 可以分为office365用户管理,Exchange Online的管理等 1. 使用Powershell 链接到office 365 用户 ...

  3. 准备使用 Office 365 中国版--邮箱迁移

    微软产品一贯的作风是从来不缺文档和教程,Office 365也不例外.无论是最终用户还是企业IT管理员,都可参照Office 365使用指南顺利的开启Office 365之旅.不过比较奇怪的是,貌似很 ...

  4. 启用MFA的office 365 账号如何连接Exchange online

    第一篇随手笔记,从简单开始... 如何使用Exchange Online PowerShell呢? 以Windows操作系统为例,如Windows10:首先需要安装Exchange Online Po ...

  5. Office 365常见问题解答(第一期)

    前不久进行的一次网络调查中,有不少朋友反馈了一些对于Office 365的实际问题,这里集中地做一个解答,请大家参考 1. Office 365的UI样式是否有开源计划 据我所知已经开源了:https ...

  6. Office 365 系列五 -------- Imap邮箱迁移步骤

    当客户购买了我们的Office 365之后,第一个功能必然是会用我们的企业邮箱,如果企业之前是用 263.腾讯.网易等的邮件厂商的话,必然会涉及到邮件的迁移, 其实说到邮箱迁移,我们办法很多,如果人数 ...

  7. Office 365 系列四 ------ 绑定公司域名

    Office 365包含了企业邮箱服务(Exchange Online),我们如果要用微软的企业邮箱,那么我们必须绑定我们公司的自己域名,而不是用微软 提供的二级域名,其实微软的整个Exchange ...

  8. Windows 商店应用中使用 Office 365 API Tools

    本篇我们介绍一个API 工具,用于在 Windows Store App 中使用 Office 365 API. 首先来说一下本文的背景: 使用 SharePoint 做过开发的同学们应该都知道,Sh ...

  9. 准备使用 Office 365 中国版--购买

    Office 365中国版支持两种购买方式,Web Direct(在线购买)和CSP(代理商购买).如果客户的企业规模不大(几十个用户,小于100用户)或者是个人/家庭购买,可以直接选择在线购买方式. ...

随机推荐

  1. WPF学习(9)样式和行为

    在asp.net世界中,我们的美工人员会为我们准备好静态页面,它注意包括三个部分:html.css和js.而在WPF世界里,也同样有着类似这三个部分的静态页面:Xaml.Style和Behaviors ...

  2. debian 该分区的部分安装移动硬盘后无法识别。

    有一个新的团购1T移动硬盘.购买格化学式ntfs经过几次简单的子区域. 4G硬盘PE.100G高速互动,盈800许多G分为两个相等的存储盘. 到您的计算机USB接口后,, 桌面弹出自己主动4一封信. ...

  3. unity3D实际的原始视频游戏开发系列讲座10它《战斗:外来入侵》在第一季度游戏开发

    解说文件夹 <保卫战:异形入侵>游戏开发 第一讲   游戏演示和资源的介绍 第二讲  "异形"怪物的实现 第三讲  "异形"怪物生命值的体现 第四讲 ...

  4. Java魔法堂:注解用法详解——@SuppressWarnings(转)

    一.前言 编码时我们总会发现如下变量未被使用的警告提示: 上述代码编译通过且可以运行,但每行前面的“感叹号”就严重阻碍了我们判断该行是否设置的断点了.这时我们可以在方法前添加 @SuppressWar ...

  5. 83. 从视图索引说Notes数据库(上)

    索引是数据库系统重要的feature,不管是传统的关系型数据库还是时兴的NoSQL数据库,它攸关查询性能,因而在设计数据库时须要细加考量.然而,Lotus Notes隐藏技术底层.以用户界面为导向.追 ...

  6. [jQuery1.9]Cannot read property ‘msie’ of undefined错误的解决方法

    原文:[jQuery1.9]Cannot read property 'msie' of undefined错误的解决方法 $.browser在jQuery1.9里被删除了,所以项目的js代码里用到$ ...

  7. Unity最优化摘要

    我们的游戏已经wp8.ios和android平台上的线. 这是我第一次做Unity工程,过程中遇到很多困难和挫折,但是,我和小伙伴探路,现在.该游戏已经上线一段时间.而且很稳定.为Unity.我一直在 ...

  8. IOS遍历未知对象属性、函数

    #import <objc/runtime.h> @implementation NSObject (PropertyListing) /* 获取对象的全部属性 */ - (NSDicti ...

  9. malloc,free简单的实现

    有关标准库首先简要malloc其原理:     标准库内部通过一个双向链表.管理在堆中动态分配的内存.     malloc函数分配内存时会附加若干(一般是12个)字节,存放控制信息.     该信息 ...

  10. handlebar的一些用法——个人使用总结

    handlebar的一些用法 概述与介绍 Handlebars 是 JavaScript 一个语义模板库,通过对view和data的分离来快速构建Web模板.它采用"Logic-less t ...