0% found this document useful (0 votes)
732 views5,901 pages

Exchange Client Developer

This document provides guidance for developers on which Exchange technologies are supported in current versions of Exchange and Office 365, and recommendations for which technologies to migrate to if an existing technology is no longer supported. It includes tables comparing support for various Exchange development technologies across product versions. The document also provides recommendations for migrating from technologies like ADSI and CDOEX that are no longer supported.

Uploaded by

pcitest123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
732 views5,901 pages

Exchange Client Developer

This document provides guidance for developers on which Exchange technologies are supported in current versions of Exchange and Office 365, and recommendations for which technologies to migrate to if an existing technology is no longer supported. It includes tables comparing support for various Exchange development technologies across product versions. The document also provides recommendations for migrating from technologies like ADSI and CDOEX that are no longer supported.

Uploaded by

pcitest123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5901

Tell us about your PDF experience.

Exchange Online and Exchange


development
Article • 03/29/2023 • 3 minutes to read

Find in-depth developer documentation for Exchange Server, including Exchange Online
as part of Office 365 and Exchange Server on-premises versions.

You can use the how to, get started, new feature, and API reference documentation to
develop tools to access and manage mailbox data from services, websites, desktop
computers, and mobile devices, and to create custom solutions for email, calendar,
contacts, and other items that are stored in Exchange Online or on an Exchange 2010,
2013, 2016, and 2019 server.

You can use Graph API, REST API, Exchange Web Services (EWS), Autodiscover, Outlook
add-ins, or other APIs to develop your applications. This page helps you choose the
right Exchange technology.

7 Note

We’re removing the ability to use Basic authentication in Exchange Online for EWS
beginning October 2022. For more information, see Deprecation of Basic
authentication in Exchange Online. You should use OAuth authentication instead.
Authenticate an EWS application by using OAuth and Authenticate an IMAP, POP
or SMTP connection using OAuth.

Exchange developer content


Use the following table to identify the technology and related API content that will help
you meet your development goals.

) Important

Microsoft Graph is the recommended API to use for accessing Exchange Online
data. New applications designed to access Exchange Online data should use
Microsoft Graph.

If you are building... Start here


If you are building... Start here

A REST-based app to access Exchange Online as part of Office Microsoft Graph REST APIs for
365 mail, calendars, and contacts

A context-sensitive app to display information in Outlook, Outlook add-ins and EWS in


Outlook Web App, or OWA for Devices Exchange

A mailbox client that is not based on the .NET Framework or Explore the EWS Managed API,
Java EWS, and web services in
Exchange

A mailbox client that uses the .NET Framework to access EWS Get started with EWS Managed
API client applications

A mailbox client that uses Java to access EWS EWS Java API on GitHub

An application that customizes the Outlook user interface or Outlook VBA reference
relies on Outlook business logic

An application that targets Exchange Online or Exchange 2013 Migrating to Exchange


that you need to migrate from a previous version of Exchange technologies

A custom management tool that uses Windows PowerShell Exchange Management Shell
from managed code

A solution to back up or restore Exchange data Backup and restore for Exchange

An extension to support accessing messages in the transport Transport agents in Exchange


pipeline

A mailbox client for a mobile device Exchange ActiveSync

Exchange interactions with custom applications


Some of these technologies enable your applications to work with data that is stored in
Exchange, and others are used to manage and control the Exchange server. In many
cases, you can use more than one programming technology or language to accomplish
a task, which makes it possible for you to use the technologies and languages that you
are familiar with. For example, you can set properties on items in the Exchange store by
using the Mail REST API, EWS, or the EWS Managed API.

Exchange interacts with custom applications in a variety of ways, depending on the


application architecture and functionality. At its core, Exchange not only transports
messages, but also maintains mailboxes, executes form-based applications, and more.
Exchange Description
interaction

Message Exchange serves as a standard mail server for applications that send messages.

transport Exchange includes several APIs that transfer messages, including REST, EWS,
and the EWS Managed API.

In addition, applications can use transport agents to respond as messages are


processed and delivered by Exchange.

Mailbox Exchange provides a hierarchical structure of folders, items, and properties for
storage applications that access data stored in mailboxes.

You can access that stored information by using a combination of database


and component object styles.

You can perform queries on the data, and Exchange manages access to the
stored data based on user and store permissions.

Applications that handle mailbox data typically use REST, EWS, or the EWS
Managed API.

Managed Exchange functions as a managed server for applications that manage


enterprise Exchange servers and stores.

server Applications can configure, control, and monitor current activity and the health
of Exchange servers across the organization.

Exchange management applications use the Exchange Management Shell to


manage Exchange servers.

See also
Server API reference for Exchange
Read about Exchange on Office Blogs
Get 101 code samples for Exchange 2013
Get the EWS Managed API (GitHub)
Get support for Exchange Server
Migrating to Exchange technologies
Article • 03/29/2023 • 4 minutes to read

If you're migrating from an earlier version of Exchange, use the information in this article
to find out which development technologies are supported in current product versions,
and which technology to migrate to.

Determine if your technology is available in


current versions
Use the following table to determine whether a development technology is supported in
Exchange Online or Exchange 2019. If the technology is not supported, see Choose a
development technology to migrate to.

Exchange development technologies and product versions

Technology Office 365 Exchange Exchange Exchange Exchange Exchange


and 2019 2016 2013 2010 2007
Exchange
Online

Office 365 APIs X X² X¹ ²


platform
overview

EWS Managed API


X X X X X X

Exchange Web X X X X X X
Services (EWS)

Mail apps for X X X X


Outlook

Outlook Object X X X X X X
Model (OOM)

Exchange X X X X X X
Management Shell

Backup and restore X X X X X

Transport agents
X X X X X
Technology Office 365 Exchange Exchange Exchange Exchange Exchange
and 2019 2016 2013 2010 2007
Exchange
Online

Active Directory X
Services Interface
(ADSI)

Collaborative Data X
Objects for
Exchange (CDOEX)

Collaborative Data X
Objects for
Windows 2000
(CDOSYS)

Exchange OLE DB X
Provider
(EXOLEDB)

Exchange Store X
Event Sinks

Incremental X
Change
Synchronization
(ICS)

Lightweight X
Directory Access
Protocol (LDAP)

Messaging API X X X X X X
(MAPI)

Outlook Web App X X X X


customization

Web Distributed X
Authoring and
Versioning
(WebDAV)

¹REST API and Graph API require the Cumulative Update 3 for Exchange 2016.

²Only hybrid customers are able to take advantage of the REST APIs for both Office 365
and on-premises mailboxes.
Choose a development technology to migrate
to
If the technology your application uses is not supported or deemphasized in Exchange
Online or Exchange 2013, use the following table to decide which technology to migrate
to.

Recommended technology migration paths

Technology Supported in Migrate to More info


Office 365,
Exchange
Online, and
Exchange
2019?

ADSI Yes, but Exchange None.


deemphasized Management
Shell

CDOEX No EWS The EWS Managed API and EWS can access the
Managed API same Exchange store that CDOEX provides.
or EWS
Unlike client applications built by using CDOEX,
you can run EWS applications on a local or
remote computer.

CDOEXM No
Exchange Exchange Management Shell commands control
Management Exchange servers, storage groups, databases,
Shell
and users more simply than the corresponding
CDOEXM APIs. Plus, you can easily migrate your
CDOEXM applications to Exchange
Management Shell commands.

CDOSYS
No
Transport Use transport agents for notification-based
agents applications that work with versions of
Exchange starting with Exchange 2010.

CDOSYS is included in current versions of


Windows. The functionality in CDOSYS is
available in the .NET Framework.

CDOWF No Windows You can use WWF to create advanced workflow


Workflow applications that work with Exchange 2007.
Foundation
(WWF)

Technology Supported in Migrate to More info


Office 365,
Exchange
Online, and
Exchange
2019?

ExOLEDB No EWS The EWS Managed API and EWS provide the
Managed API same access to the Exchange store that
or EWS
ExOLEDB provides. Unlike client applications
built by using ExOLEDB, You can run EWS
applications on a local or remote computer.

ICS Yes, but EWS You can use the EWS Managed API or EWS to
deemphasized Managed API subscribe to notifications and synchronize
or EWS
mailbox data.

LDAP Yes, but Exchange None.


deemphasized Management
Shell

MAPI Yes, but Office 365 Although MAPI is currently a supported


deemphasized APIs development technology, you will eventually
platform have to redesign your MAPI applications to use
overview, a newer technology.

EWS
Managed If your MAPI application is performing simple
API, EWS
read, write, and update operations on mail,
calendar, or contact objects, and targets Office
365, Exchange 2019² or Exchange 2016¹ ² you
can use the Office 365 REST APIs for mail,
calendars, and contacts.

If you are targeting Exchange on-premises and


you need to access all the properties that MAPI
can access, you can use the EWS Managed API
or EWS and either schematized properties or
extended properties .

NOTE: The ExtendedPropertyDefinition class


provides access to MAPI from the EWS
Managed API, and the ExtendedFieldURI
element provides access to MAPI properties
from EWS.

Outlook Web No Mail apps


None.
App
customization
Technology Supported in Migrate to More info
Office 365,
Exchange
Online, and
Exchange
2019?

Store event No EWS You can use the EWS Managed API or EWS to
sinks Managed API subscribe to notifications and synchronize
or EWS
mailbox data.

The notifications in EWS provide the same


access to the Exchange store that store event
sinks provide. You can use Visual Studio tools to
streamline the development of store event-
aware client applications that use EWS.

Streaming No Volume None.


backup and Shadow
restore Copy Service
(VSS) writer

WebDAV No Office 365 If your WebDAV application is performing


APIs simple read, write, and update operations on
platform mail, calendar, or contact objects, and you will
overview, be targeting Office 365, Exchange 2019² or
EWS Exchange 2016¹ ² you can use the Office 365
Managed API REST APIs for mail, calendars, and contacts.

or EWS

Otherwise, if you are targeting Exchange on-


premises and you need access to the same
properties in the Exchange store that WebDAV
provides, use the EWS Managed API or EWS.

WebDAV No EWS You can use the EWS Managed API or EWS to
notifications Managed API subscribe to notifications.
or EWS

Web forms No ASP.NET


Switch to ASP.NET and update applications to
access mailbox and server information by using
EWS.

WMI No Exchange None.


providers Management
Shell

¹REST API and Graph API require the Cumulative Update 3 for Exchange 2016.

²Only hybrid customers are able to take advantage of the REST APIs for both Office 365
and on-premises mailboxes.
See also
Selecting an API or technology for developing solutions for Outlook
On-Premises Architectural Requirements for the REST API
Explore the EWS Managed API, EWS,
and web services in Exchange
Article • 06/14/2022 • 2 minutes to read

Use the EWS Managed API, EWS, Autodiscover, and other web services in Exchange to
create solutions for managing business email, calendar, and contacts on desktop and
mobile devices and online.

Exchange provides Exchange web services (EWS) and other web services that you can
use to implement client applications that access and manage Exchange store items.

7 Note

The terms specified in the License information topic apply to your use of this
content. Please review the terms carefully.

Create EWS Managed API, EWS, and web


services solutions
Use the following table to find to the content that will help you learn about and work
with the EWS Managed API, EWS, and web services in Exchange.

If you want to... Start here

Get started with your first .NET Framework EWS client Get started with EWS Managed API
application. client applications

Get started with your first EWS client application. Get started with EWS client
applications

Find out about the latest new features in the EWS What's new in EWS in Exchange

Managed API and EWS.

Learn the fundamentals of web service development with Start using web services in Exchange

Exchange.

Check out some EWS Managed API code samples. Exchange 2013: 101 Code Samples

Find design guidance for EWS Managed API and EWS EWS client design overview for
applications. Exchange

If you want to... Start here

Find how-to information and code examples for the EWS Develop web service clients for
Managed API and EWS. Exchange

Find reference material. Web services reference for Exchange

See also
Sign up for an Exchange Online and Office 365 Developer Site
What's new in EWS and other web services
in Exchange
Article • 01/15/2020 • 7 minutes to read

Find out what's new in EWS and web services in Exchange and the EWS Managed API.

Web services in Exchange have been updated to include new features.

Table 1. New web service features in Exchange Online, Exchange 2013, and the EWS Managed
API

Feature Implemented in Implemented in Implemented in the EWS


Exchange Online Exchange 2013 Managed API

eDiscovery
Yes Yes Yes

Archiving
Yes Yes Yes

Personas
Yes Yes No

Unified Contact Store


Yes Yes No

Retention policies
Yes Yes Yes

User photos
Yes Yes No

Mail apps for Outlook Yes Yes Yes


management

Propose new meeting Yes No No


time

eDiscovery in EWS
eDiscovery is a federated query web service that enables external applications, such as
SharePoint 2013, to perform queries of Exchange data. Discovery consists of several phases,
including identifying and preserving key data, culling down and reviewing the data, and
producing data in court. eDiscovery queries facilitate the discovery process by providing a single
discovery workflow across Exchange and SharePoint.

Table 2. EWS operations and EWS Managed API methods for working with eDiscovery

Operation name EWS Managed API method Description


Operation name EWS Managed API method Description

GetDiscoverySearchConfiguration ExchangeService.GetDiscoverySearchConfiguration() Gets configuration


operation
information for in-
place holds, saved
discovery searches,
and the mailboxes
that are enabled for
discovery search.

GetHoldOnMailboxes ExchangeService.GetHoldOnMailboxes()
Gets the status of a
operation
query-based hold,
which is set by using
the
SetHoldOnMailboxes
operation.

GetNonIndexableItemDetails ExchangeService.GetNonIndexableItemDetails()
Gets details about
operation
items that cannot be
indexed. This
includes, but is not
limited to, the item
identifier, an error
code, an error
description, when an
attempt was made to
index the item, and
additional
information about
the item.

GetNonIndexableItemStatistics ExchangeService.GetNonIndexableItemStatistics()
Gets the count of
operation
items that cannot be
indexed in a mailbox.

GetSearchableMailboxes ExchangeService.GetSearchableMailboxes()
Gets a list of
operation
mailboxes that the
client has permission
to search or perform
eDiscovery on.

SearchMailboxes operation
ExchangeService.SearchMailboxes()
Searches for items in
specific mailboxes
that match query
keywords.

SetHoldOnMailboxes ExchangeService.SetHoldOnMailboxes()
Sets a query-based
operation
hold on items.

Archiving in EWS
Archive mailboxes are secondary mailboxes that are associated with a user. Archive mailboxes
are typically used to manage email storage limits. For example, older email items might
periodically be moved from the Inbox to the archive mailbox.

Exchange introduces two new EWS operations that you can use to archive a set of mail items
from a primary mailbox. Archiving Inbox items in this way preserves the folder hierarchy of the
items. In addition, archive mailboxes can now be stored either locally on a client, or remotely, in
a way that is mostly opaque to a user, by using a folder path to point to the contents of the
archive.

Table 3. EWS operations and EWS Managed API methods for working with archiving

Operation name EWS Managed API method Description

ArchiveItem ExchangeService.ArchiveItems() Moves an item from the primary mailbox to


operation
the archive mailbox.

CreateFolderPath Not implemented. Creates a folder hierarchy in a primary or


operation
archive mailbox.

Personas in EWS
A persona is a collection of data that is associated with an individual. The data can come from
one or more sources and is associated with the persona by means of a common link ID.
Personas in EWS enable you to link, search, browse, and retrieve information about a person
from multiple sources and organize that information into a single logical entity. Personas differ
from contacts in that a contact is a collection of data from a single source that is associated with
an individual; for example, a personal Outlook contact or an entry in a global address list (GAL).

The EWS Managed API does not implement this functionality.

7 Note

The Unified Contact Store also exposes persona functionality by means of the operations
that support that feature.

Table 4. EWS operations for working with personas

Operation name Description

FindPeople Returns all persona objects from a specified contact folder or retrieves all contacts that
operation
match a specified query string.

GetPersona Retrieves a persona.


operation

Unified Contact Store in EWS


The Unified Contact Store is a feature that provides a consistent contact experience across Office
products and acts as an integration point for third-party applications to use the same contact
store. It allows users and applications to store, manage, and access contact information and
make it available globally among Lync, Exchange 2013, Outlook, Outlook Web App and any
other application that implements access to the Unified Contact Store. Exchange is the contact
store for the Unified Contact Store experience.

The EWS Managed API does not implement this functionality.

Table 5. EWS operations for working with the Unified Contact Store

Operation name Description

AddNewImContactToGroup Adds a new IM contact to a group. The Unified Contact Store can
operation
contain a maximum of 1000 contacts.

AddImContactToGroup operation
Adds an existing IM contact to a group. The Unified Contact Store
can contain a maximum of 1000 contacts.

AddImGroup operation
Adds a new IM group. The Unified Contact Store can contain a
maximum of 64 groups.

AddNewTelUriContactToGroup Adds a new contact to a group based on a contact's phone


operation
number.

AddDistributionGroupToImList Adds a new distribution list group. The Unified Contact Store can
operation
contain a maximum of 64 groups.

GetImItemList operation
Retrieves a list of IM groups and IM contact personas.

GetImItems operation
Retrieves information about the specified IM groups and IM
contact personas.

RemoveContactFromImList Removes the specified contact from all IM groups.


operation

RemoveImContactFromGroup Removes an IM contact from a group.


operation

RemoveDistributionGroupFromImList Removes the specified IM distribution list group.


operation

RemoveImGroup operation
Removes the specified IM group.

SetImGroup operation
Changes the display name of a group.

Retention policies in EWS


Retention policies are policies that are used in Exchange to group one or more retention tags, to
apply retention settings to folders or individual items such as email and voice mail messages,
and to apply retention settings to a mailbox.

Exchange includes three types of retention tags:

Default policy tags that apply to mailbox items that have no other type of retention tag
applied.

System folder policy tags that are applied to default folders such as the Inbox.

Personal tags that a user can apply to folders they create or to individual items.

Only one retention policy can be assigned to a mailbox, but the policy can have one or more
retention tags of various types linked to it. Retention tags can be linked to or unlinked from a
retention policy at any time. EWS in Exchange exposes a new operation,
GetUserRetentionPolicyTags , and the EWS Managed API implements a new method,
ExchangeService.GetUserRetentionPolicyTags() , that provides a list of all the tags that are
linked to a retention policy. You can set and retrieve retention policy tags for items and folders
by using the CreateItem, CreateFolder, UpdateItem, UpdateFolder, GetItem, and GetFolder
operations.

Requesting user photos


You can request user photos from the Exchange server by using one of the two implementations
of the GetUserPhoto operation : REST or SOAP. The REST endpoint uses a standard HTTPS GET
request to get the user photo. The service will either return a user photo stored in Exchange or a
photo from Active Directory Domain Services (AD DS).

The EWS Managed API does not implement this functionality. You can, however, use the EWS
Managed API to return user photos that are stored in a mailbox by getting the photo that is
attached to a contact.

Block senders and mark email as junk in EWS


You can now block senders and mark email as junk by using the new MarkAsJunk operation in
EWS or the ExchangeService.MarkAsJunk() method in the EWS Managed API.

Mail apps for Outlook


EWS now includes support for managing mail apps for Outlook.

Table 6. EWS operations and EWS Managed API methods for working with mail apps for
Outlook

Operation name EWS Managed API method Description

DisableApp operation
ExchangeService.DisableApp()
Disables an installed app.
Operation name EWS Managed API method Description

GetAppManifests operation
ExchangeService.GetAppManifests()
Gets the app manifests for
a mailbox.

GetAppMarketplaceUrl ExchangeService.GetAppMarketplaceUrl() Gets the app marketplace


operation
URL.

GetClientAccessToken ExchangeService.GetClientAccessToken()
Gets client access tokens.
operation

InstallApp operation
ExchangeService.InstallApp()
Installs an app for a
mailbox.

UninstallApp operation
ExchangeService.UninstallApp
Uninstalls an app from a
mailbox.

Propose new meeting time


The propose new time feature was introduced in version 15.00.0800.007 of Exchange. This allows
meeting attendees to propose new meeting times to the meeting organizer.

The EWS Managed API does not implement this functionality.

See also
Explore the EWS Managed API, EWS, and web services in Exchange
EWS client design overview for Exchange
Mail apps for Outlook and EWS in Exchange
Archiving in EWS in Exchange
eDiscovery in EWS in Exchange
People and contacts in EWS in Exchange
Start using web services in Exchange
Article • 01/15/2020 • 3 minutes to read

Find information to help you get started with EWS and other web services in Exchange.

The web services in Exchange provide access to mailbox data stored in Exchange Online,
Exchange Online as part of Office 365, and on-premises versions of Exchange starting
with Exchange Server 2007, and enable you to create custom applications that you can
use to manage that information according to the requirements of your organization.
While the range of EWS and web service applications that you can create is practically
infinite, certain fundamental concepts apply for any type of application. This section
provides information about the fundamental concepts you need to be familiar with in
order to start using EWS and other web services in Exchange.

Build your knowledge


Whether you use the .NET Framework or another platform to develop your web service
application, you will want to understand some important concepts before you begin
your development project.

Table 1. Web services concepts

Concept Summary

Architecture
Learn about how EWS works within the Exchange architecture and the
protocols it uses.

EWS application Find out about the most common types of applications that you can create
types
by using EWS in Exchange.

EWS access
Exchange administrators can limit access to EWS globally for the entire
organization, for individual users, and to individual applications. Find out
which access level is right for you.

Setup
Find information about the tasks you need to complete in order to create
applications that use the EWS Managed API or EWS to communicate with
Exchange.

Authentication
Learn about the authentication options for connecting to Exchange Online
and Exchange on-premises.

Autodiscover
Learn about the set of services that you can use to discover the URL
endpoint where a user's account can access information via EWS.
Concept Summary

Mailbox server
Find out about the primary repository of information made available to an
EWS client. EWS has access to a limited set of information stored in Active
Directory Domain Services (AD DS).

Mail apps for Find information about mail apps for Outlook and how they work with
Outlook and EWS
EWS in Exchange.

Office 365 REST APIs Learn about the Office 365 APIs that you can use to access mail, calendars,
for mail, calendars, and contacts in Exchange Online as part of Office 365.
and contacts

The EWS Managed Find information about the preferred client API for .NET Framework
API
developers.

EWS
Find information about creating your first application by using EWS XML
requests and responses.

EWS functionality in Find out what EWS functionality is available in version of Exchange.
Exchange product
versions

Trace and Find out how to trace EWS requests and responses in order to
troubleshoot
troubleshoot errors in your EWS Managed API application.

Create your first application


If you're ready to get to the business of writing your first .NET Framework or EWS client
application, see Get started with EWS Managed API client applications or Get started
with EWS client applications.

Get code samples


To find code samples and examples that show you how to work with EWS and other web
services in Exchange, see the following resources:

Exchange code samples

CodePlex

Exchange API documentation

Exchange Development forum

Many other samples are available in blogs, code demonstration sites, and forums. We
also recommend that you download the EWSEditor . This project implements most of
the EWS functionality; you can find examples of all the core EWS functionality here.

If you're not a .NET Framework developer, you can find many client libraries out there
for EWS development that use Java, Python, PHP, and other languages.

Ask questions and solve problems


Need help getting things done and you're not finding answers? You can search the
Exchange Development forum to find out whether someone else has encountered
and resolved the same issue. A community of contributors have answered hundreds of
questions about Exchange development. You can also find third-party sites, forums, and
blogs that cover Exchange development and might have the solution you're looking for.

Contact Microsoft support if you need additional assistance. The Exchange Developer
support team is staffed with seasoned professionals who can help answer your
questions about Exchange development.

See also
Explore the EWS Managed API, EWS, and web services in Exchange
EWS client design overview for Exchange
Develop web service clients for Exchange
Web services reference for Exchange
EWS applications and the Exchange
architecture
Article • 01/18/2019 • 6 minutes to read

Learn about how EWS works within the Exchange architecture, and find out which
protocols EWS relies on.

Exchange Web Services (EWS) is a cross-platform API that enables applications to access
mailbox items such as email messages, meetings, and contacts from Exchange Online,
Exchange Online as part of Office 365, or on-premises versions of Exchange starting
with Exchange Server 2007. EWS applications can access mailbox items locally or
remotely by sending a request in a SOAP-based XML message. The SOAP message is
embedded in an HTTP message when sent between the application and the server,
which means that as long as your application can post XML through HTTP, it can use
EWS to access Exchange.

Exchange architecture overview


The following diagrams show the authentication methods and communication paths
used by EWS applications when communicating with Exchange 2013 and Exchange
Online. From the EWS application perspective, the communication paths are identical
and the authentication methods only vary slightly; the main difference is the visibility
you have into the Exchange backend.

Figure 1. EWS application and the Exchange on-premises architecture


Figure 2 shows the same communication paths shown in Figure 1, as used by EWS
applications when communicating with Exchange Online.

Figure 2. EWS application and the Exchange Online architecture


The following are the components that are shown in the diagrams:

1. EWS application — This can be a client, portal, or service application and it can be
installed on a client or on an Exchange on-premises Client Access server. If you use
the EWS Managed API to develop the EWS application, the EWS Managed API
assemblies have to be installed on the client and redistributed by your application.

2. The SOAP XML message — An XML message, in a SOAP envelope, embedded in


an HTTP/S message that conforms to the Services.wsdl file on the Client Access
server. HTTPS is recommended for Exchange on-premises and is required for
Exchange Online.

3. Authentication methods — EWS messages include basic, NTLM (Windows


Integrated authentication), or OAuth authentication information as part of the
HTTP payload.

4. Load balancer — The load balancer distributes the message to a Client Access
server in the Client Access server array. This component is only visible in the
Exchange on-premises architecture.

5. Client Access server array — Client Access servers are organized into a load-
balanced group called a Client Access server array. Individual Client Access servers
provide authentication, limited redirection, and proxy services. The Client Access
servers themselves don't do any data rendering, and no data is queued or stored
on a Client Access server - it is thin and stateless; it simply authenticates the
request, performs an Autodiscover lookup, and then proxies the request to the
Mailbox server. The Client Access server does maintain a 1:1 relationship with the
Mailbox server that hosts the user's data. The HTTP protocol (secured via SSL using
a self-signed certificate) is used between the Client Access server and Mailbox
server. This component is only visible in the Exchange on-premises architecture.

6. Autodiscover service — The Autodiscover service performs a service discovery by


accessing Active Directory Domain Services (AD DS) to retrieve the mailbox version
and the location of the Mailbox server that is hosting the active copy of the user's
data.

7. EWS service —The EWS service is described by three files: Services.wsdl,


Messages.xsd, and Types.xsd, as well as the EWS Managed API assemblies.
Services.wsdl describes the contract between the client and server, Messages.xsd
defines the request and response SOAP messages, and Types.xsd defines the
elements used in the SOAP messages. Messages.xsd and Types.xsd always contain
the latest versions of the schema, although earlier versions of the schema exist.
Note that Services.wsdl, Messages.xsd, and Types.xsd are made available on the
Client Access server, but are not actually used for schema validation — they are
provided for reference only. The EWS Managed API assemblies are provided for
server-side EWS client applications and are deployed on all Exchange Server roles,
not just the Client Access servers. This component is only visible in the Exchange
on-premises architecture.

Feature availability is based on the EWS schema version that your application
targets. Because EWS schemas are backward- and forward-compatible, if you
create an application that targets an earlier schema version, such as Exchange 2007
SP1, your application will also work against a later schema version, such as the
Exchange 2010 SP2 service, as well as Exchange Online. Because features and
feature updates are driven by the schema, we recommend that you use the earliest
common code base that targets the EWS features that you want to implement in
your client application. Many applications can target the Exchange2007_SP1
version, because the Exchange 2007 SP1 schema contains almost all the core
Exchange functionality for working with items and folders in the Exchange store.
For more information, see EWS client features.

8. Database Availability Group (DAG) — Mailbox servers are organized into a highly
available DAG, which can be deployed in one or more datacenters. The Mailbox
server contains the mailbox database and handles all activity for the active
mailboxes on that server. All components that process, render, and store data are
on the Mailbox server. Clients do not connect directly to the Mailbox server; all
connections are handled by the Client Access server. This component is only visible
in the Exchange on-premises architecture.

9. Exchange Online and Exchange Online as part of Office 365 — The hosted
messaging solution that delivers Exchange features as a cloud-based service.

When an EWS application requests information from the Exchange store, an XML
request message that complies with the SOAP standard is created and sent to the
Exchange server. When the Exchange server receives the request, it verifies the
credentials that are provided by the client and automatically parses the XML for the
requested data. The server then builds a SOAP response that contains XML data that
represents the requested strongly typed objects and their properties. The XML data is
sent back to the application in an HTTP response. The application then deserializes the
XML and uses the data to reform the strongly typed objects.

Protocols and standards that EWS applications


must support
To communicate with an Exchange server, EWS applications must support the following
protocols and standards.

Table 1. Protocols

Protocol How it's used

HTTP/S Enables EWS applications to access Exchange database data over the network,
regardless of whether the client is on the Internet or intranet.

SOAP 1.0 Forms an envelope around the messaging payload. EWS implements the SOAP
protocol by using different parts of the SOAP envelope to enable different
functionality. The SOAP header is used for impersonation and to provide versioning
data. The SOAP body provides information about the operation to run and the data
that is submitted to the operation. SOAP relies on WSDL to describe the operations to
call.

WSDL 1.0 Describes the bindings, the operations, and the properties that are used to call EWS
operations, in the Services.wsdl file. This file, along with the referenced schema files,
comprises the contract between an EWS application and the Exchange server, and is
often used along with vendor-specific tools to create platform-specific applications.
The WSDL file is located in the EWS virtual directory, which is at the root of the
website.
Protocol How it's used

Transport Provides secure web communications on the Internet or on intranet. TLS enables
Layer applications to authenticate servers or, optionally, servers to authenticate EWS
Security applications. It also provides a security channel by encrypting communications. TLS is
(TLS)/SSL the latest version of the Secure Sockets Layer (SSL) protocol.

XML/XSD Provides a universal message format for the exchange of information between the
Exchange server and the client. XML provides complex Exchange database data to
client applications, but in a defined structure. The beauty of XML is that it allows for
the exchange of data even when an EWS application and server do not share a
common platform.

In addition, EWS applications must support the following authentication standards:

Basic authentication over SSL, for applications that target Exchange Online or
Exchange on-premises.

NTLM authentication over SSL, for applications that support Exchange on-
premises.

OAuth 2.0 token authentication, for trusted partner applications and


interoperability with Lync Server 2013 and SharePoint Server 2013.

See also
Start using web services in Exchange

EWS application types

EWS client design overview for Exchange


EWS application types
Article • 01/18/2019 • 2 minutes to read

Find out about the most common types of applications that you can create by using
EWS in Exchange.

The EWS and Exchange architecture provides a uniform development model that you
can use to create the most common types of applications in a consistent way, including
the following:

Client applications — Standalone applications that use EWS to access Exchange


data. Outlook and Outlook Web App are examples of client applications.

Portal applications — Applications that extend an existing web page by including


information retrieved from Exchange, such as free/busy or contact information. A
SharePoint web part that retrieves Exchange data is an example of a portal
application.

Service applications — Background jobs used to integrate or synchronize data


from Exchange into an existing system. For example, an application that
synchronizes contact information from Exchange into a CRM application.

Each of these application models can use a common code base to retrieve information
from Exchange - so you don't need to change the EWS code used to retrieve item
information between a client, portal, or service application. What might change from
one application to the next is the mailbox access and authentication mechanism. For
example, client applications commonly use direct user access and basic or NTLM
authentication, whereas a service application likely uses impersonation for mailbox
access and OAuth authentication.

Client applications
An EWS client application is any standalone application that uses EWS to retrieve
information from the Exchange store. EWS client applications use direct client access or
delegate access to retrieve data from the mailbox store. The following are some
examples of client applications that use EWS:

Outlook, in features such as MailTips, availability, and user OOF status

OWA for Devices

Outlook for Mac 2011


Lync, for availability information

Client applications commonly use direct access and basic or NTLM authentication, so
that users are limited to accessing information in their own mailbox with their own
logon credentials. Client applications should also support delegate access for users who
have been given permission to access another user's mailbox.

Portal applications
A portal application extends an existing web page or portal to include Exchange mailbox
information as a personalized component of the page. SharePoint web parts are the
most common portal applications and provide users with a personalized experience by
providing views into Exchange mailbox data, such as unread messages, most recent
messages, and calendar events, alongside their commonly viewed SharePoint portal
page. EWS portal applications can use direct client access, delegate access, or
impersonation to retrieve data from the mailbox store. Because Exchange 2013 and
SharePoint 2013 both support the OAuth authorization protocol for server-to-server
authentication, OAuth provides the most seamless and secure authentication method.

Service applications
A service application is usually a background job built into an existing application that
extends to Exchange to correlate data between the system and the Exchange store.
Service applications typically do not have a user interface and use impersonation or
OAuth for authentication and access. Creating a service account to impersonate users is
common in EWS service apps because you can grant a single account permission to
impersonate a set of users and perform mailbox operations for those accounts. For
example, an EWS service application can synchronize data between marketing lists in a
CRM solution and Exchange distribution groups by using a service account and
impersonation.

See also
Start using web services in Exchange

EWS applications and the Exchange architecture

EWS client design overview for Exchange


Get started with EWS Managed API
client applications
Article • 03/04/2022 • 9 minutes to read

Develop a simple Hello World email client application for Exchange by using the EWS
Managed API.

The EWS Managed API provides an intuitive, easy-to-use object model for sending
and receiving web service messages from client applications, portal applications, and
service applications. You can access almost all the information stored in an Exchange
Online, Exchange Online as part of Office 365, or an Exchange server mailbox by using
the EWS Managed API. You can use the information in this article to help you develop
your first EWS Managed API client application.

7 Note

We’re removing the ability to use Basic authentication in Exchange Online for EWS
beginning October 2022: Deprecation of Basic authentication in Exchange Online.
You should use OAuth authentication instead. Authenticate an EWS application by
using OAuth

7 Note

The EWS Managed API is now available as an open source project on GitHub .
You can use the open source library to:

Contribute bug fixes and enhancements to the API.


Get fixes and enhancements before they are available in an official release.
Access the most comprehensive and up-to-date implementation of the API, to
use as a reference or to create new libraries on new platforms.

We welcome your contributions on GitHub.

You'll need an Exchange server


If you already have an Exchange mailbox account, you can skip this section. Otherwise,
you have the following options for setting up an Exchange mailbox for your first EWS
client application:
Get an Office 365 Developer Site (recommended). This is the quickest way for
you to set up an Exchange mailbox.

Download Exchange Server .

After you have verified that you can send and receive email from Exchange, you are
ready to set up your development environment. You can use the Exchange web client
Outlook Web App to verify that you can send email.

Set up your development environment


Make sure that you have access to the following:

Any version of Visual Studio that supports the .NET Framework 4. Although
technically, you don't need Visual Studio because you can use any C# compiler, we
recommend that you use it.

The EWS Managed API . You can use either the 64-bit or 32-bit version,
depending on your system. Use the default installation location.

Create your first EWS Managed API application


These steps assume that you set up an Office 365 Developer Site. If you downloaded
and installed Exchange, you will need to install a valid certificate on your Exchange
server or implement a certificate validation callback for a self-signed certificate that is
provided by default. Also note that these steps might vary slightly depending on the
version of Visual Studio that you are using.

Step 1: Create a project in Visual Studio


1. In Visual Studio, on the File menu, choose New, and then choose Project. The New
Project dialog box opens.

2. Create a C# Console Application. From the Templates pane, choose Visual C#, and
then choose Console Application.

3. Name the project HelloWorld, and then choose OK.

Visual Studio creates the project and opens the Program.cs code document window.

Step 2: Add a reference to the EWS Managed API


1. If the Solution Explorer window is already open, skip this step and proceed to step
2. To open the Solution Explorer window, on the View menu, choose Solution
Explorer.

2. In the Solution Explorer and the HelloWorld project, open the shortcut menu
(right-click) for References and choose Add Reference from the context menu. A
dialog box for managing project references will open.

3. Choose the Browse option. Browse to the location where you installed the EWS
Managed API DLL. The default path set by the installer is the following: C:\Program
Files\Microsoft\Exchange\Web Services<version>. The path can vary based on
whether you download the 32 or 64 bit version of the
Microsoft.Exchange.WebServices.dll. Choose Microsoft.Exchange.WebServices.dll
and select OK or Add. This adds the EWS Managed API reference to your project.

4. If you are using EWS Managed API 2.0, change the HelloWorld project to target
the .NET Framework 4. Other versions of the EWS Managed API might use a
different target version of the .NET Framework.

5. Confirm that you are using the correct target version of the .NET Framework. Open
the shortcut menu (right-click) for your HelloWorld project in the Solution
Explorer, and choose Properties. Verify that the .NET Framework 4 is selected in
the Target framework drop-down box.

Now that you have your project set up and you created a reference to the EWS
Managed API, you are ready to create your first application. To keep things simple, add
your code to the Program.cs file. Read Reference the EWS Managed API assembly for
more information about referencing the EWS Managed API. In the next step, you will
develop the basic code to write most EWS Managed API client applications.]

Step 3: Set up URL redirection validation for Autodiscover


Add the following redirection validation callback method after the Main(string[]
args) method. This validates whether redirected URLs returned by Autodiscover
represent an HTTPS endpoint.

C#

private static bool RedirectionUrlValidationCallback(string


redirectionUrl)

// The default for the validation callback is to reject the URL.

bool result = false;


Uri redirectionUri = new Uri(redirectionUrl);

// Validate the contents of the redirection URL. In this simple


validation

// callback, the redirection URL is considered valid if it is using


HTTPS

// to encrypt the authentication credentials.

if (redirectionUri.Scheme == "https")

result = true;

return result;

This validation callback will be passed to the ExchangeService object in step 4. You need
this so that your application will trust and follow Autodiscover redirects - the results of
the Autodiscover redirect provides the EWS endpoint for our application.

Step 4: Prepare the ExchangeService object


1. Add a using directive reference to the EWS Managed API. Add the following code
after the last using directive at the top of Program.cs.

C#

using Microsoft.Exchange.WebServices.Data;

2. In the Main method, instantiate the ExchangeService object with the service
version you intend to target. This example targets the earliest version of the EWS
schema.

C#

ExchangeService service = new


ExchangeService(ExchangeVersion.Exchange2007_SP1);

3. If you are targeting an on-premises Exchange server and your client is domain
joined, proceed to step 4. If you client is targeting an Exchange Online or Office
365 Developer Site mailbox, you have to pass explicit credentials. Add the
following code after the instantiation of the ExchangeService object and set the
credentials for your mailbox account. The user name should be the user principal
name. Proceed to step 5.

C#

service.Credentials = new WebCredentials("[email protected]",


"password");

4. Domain-joined clients that target an on-premises Exchange server can use the
default credentials of the user who is logged on, assuming the credentials are
associated with a mailbox. Add the following code after the instantiation of the
ExchangeService object.

C#

service.UseDefaultCredentials = true;

If your client targets an Exchange Online or Office 365 Developer Site mailbox,
verify that UseDefaultCredentials is set to false, which is the default value. Your
client is ready to make the first call to the Autodiscover service to get the service
URL for calls to the EWS service.

5. The AutodiscoverUrl method on the ExchangeService object performs a series of


calls to the Autodiscover service to get the service URL. If this method call is
successful, the URL property on the ExchangeService object will be set with the
service URL. Pass the user's email address and the
RedirectionUrlValidationCallback to the AutodiscoverUrl method. Add the
following code after the credentials have been specified in step 3 or 4. Change
[email protected] to your email address so that the Autodiscover service finds

your EWS endpoint.

C#

service.AutodiscoverUrl("[email protected]",
RedirectionUrlValidationCallback);

At this point, your client is set up to make calls to EWS to access mailbox data. If you run
your code now, you can verify that the AutodiscoverUrl method call worked by
examining the contents of the ExchangeService.Url property. If this property contains
a URL, your call was a success! This means that your application successfully
authenticated with the service and discovered the EWS endpoint for your mailbox. Now
you are ready to make your first calls to EWS. Read Set the EWS service URL by using the
EWS Managed API for more information about setting the EWS URL.

Step 6: Create your first Hello World email message


1. After the AutodiscoverUrl method call, instantiate a new EmailMessage object and
pass in the service object you created.

C#
EmailMessage email = new EmailMessage(service);

You now have an email message on which the service binding is set. Any calls
initiated on the EmailMessage object will be targeted at the service.

2. Now set the To: line recipient of the email message. To do this, change
[email protected] to use your SMTP address.

C#

email.ToRecipients.Add("[email protected]");

3. Set the subject and the body of the email message.

C#

email.Subject = "HelloWorld";

email.Body = new MessageBody("This is the first email I've sent by


using the EWS Managed API.");

4. You are now ready to send your first email message by using the EWS Managed
API. The Send method will call the service and submit the email message for
delivery. Read Communicate with EWS by using the EWS Managed API to learn
about other methods you can use to communicate with Exchange.

C#

email.Send();

5. You are ready to run your Hello World application. In Visual Studio, select F5. A
blank console window will open. You will not see anything in the console window
while your application authenticates, follows Autodiscover redirections, and then
makes its first call to create an email message that you send to yourself. If you
want to see the calls being made, add the following two lines of code before the
AutodiscoverUrl method is called. Then press F5. This will trace out the EWS
requests and responses to the console window.

C#

service.TraceEnabled = true;

service.TraceFlags = TraceFlags.All;

You now have a working EWS Managed API client application. For your convenience, the
following example shows all the code that you added to Program.cs to create your Hello
World application.

C#

using System;

using Microsoft.Exchange.WebServices.Data;

namespace HelloWorld

class Program

static void Main(string[] args)

ExchangeService service = new


ExchangeService(ExchangeVersion.Exchange2007_SP1);

service.Credentials = new WebCredentials("[email protected]",


"password");

service.TraceEnabled = true;

service.TraceFlags = TraceFlags.All;

service.AutodiscoverUrl("[email protected]",
RedirectionUrlValidationCallback);

EmailMessage email = new EmailMessage(service);

email.ToRecipients.Add("[email protected]");

email.Subject = "HelloWorld";

email.Body = new MessageBody("This is the first email I've sent by


using the EWS Managed API");

email.Send();

private static bool RedirectionUrlValidationCallback(string


redirectionUrl)

// The default for the validation callback is to reject the URL.

bool result = false;

Uri redirectionUri = new Uri(redirectionUrl);

// Validate the contents of the redirection URL. In this simple


validation

// callback, the redirection URL is considered valid if it is using


HTTPS

// to encrypt the authentication credentials.

if (redirectionUri.Scheme == "https")

result = true;

return result;

Next steps
If you're ready to do more with your first EWS Managed API client application, explore
the following resources:

Exchange 2013: 101 code samples


Folders and items
EWSEditor

If you run into any issues with your application, try posting a question or comment in
the forum (and don't forget to read the top post).

In this section
Reference the EWS Managed API assembly
Set the EWS service URL by using the EWS Managed API
Communicate with EWS by using the EWS Managed API

See also
Start using web services in Exchange
EWS client design overview for Exchange
Develop web service clients for Exchange
Trace requests and responses to troubleshoot EWS Managed API applications
Reference the EWS Managed API
assembly
Article • 03/04/2022 • 2 minutes to read

Find information about how to reference the EWS Managed API assembly.

The EWS Managed API provides a simple and full-featured interface for developing and
extending applications that use Exchange Web Services (EWS). Whether you are using
Visual Studio or another code editor to develop your EWS Managed API application, you
will need to make a reference to the EWS Managed API assembly. If you haven't
installed the EWS Managed API already, be sure to download the API .

7 Note

The EWS Managed API is now available as an open source project on GitHub .
You can use the open source library to:

Contribute bug fixes and enhancements to the API.


Get fixes and enhancements before they are available in an official release.
Access the most comprehensive and up-to-date implementation of the API, to
use as a reference or to create new libraries on new platforms.

We welcome your contributions via GitHub.

Referencing the assembly


The most common way to add a reference is to use Visual Studio. We know that some
developers out there like to use other editors, so we are including instructions for using
the command-line compiler as well as instructions for using Visual Studio. You might
notice that the code examples that follow have the same using statements. The
difference between the two methods is that the command-line compiler needs the
location of the assembly file. The Visual Studio reference handles this for you behind the
scenes.

To add a reference by using Visual Studio


1. Put the Microsoft.Exchange.WebServices.dll file and the
Microsoft.Exchange.WebServices.xml file into a folder of your choice. By default,
the files are installed in C:\Program Files\Microsoft\Exchange\Web Services\2.0\ ,
but you can store the files anywhere on your computer.

2. In the Solution Explorer pane in Visual Studio, select References, and then choose
Add Reference. This opens the Add Reference window.

3. In the Add Reference window, navigate to the Browse tab, browse to the location
of the Microsoft.Exchange.WebServices.dll file, select that file, and then select OK.

4. To use the EWS Managed API in your application, add a using statement for the
Microsoft.Exchange.WebServices.Data namespace.

C#

using Microsoft.Exchange.WebServices.Data;

To add a reference and build your application with the


command-line compiler
1. Put the Microsoft.Exchange.WebServices.dll file into a folder of your choice. This
folder will be the output folder for the compiler.

2. In your source code editor, add a using statement to the source code for the
Microsoft.Exchange.WebServices.Data namespace.

C#

using Microsoft.Exchange.WebServices.Data;

3. Run the command-line compiler to build the application. The following command
uses the .NET Framework C# compiler to build the Windows application defined in
the source code file "program.cs". It assumes that the compiler is located in the
default installation directory and that the Microsoft.Exchange.WebServices.dll file is
in a subdirectory of the current directory named "build".

C#

c:\Windows\Microsoft.NET\Framework\3.5\csc /target: winexe /out:


build\testApplication /reference:
build\Microsoft.Exchange.WebServices.dll program.cs

See also
Get started with EWS Managed API client applications
Setting up your Exchange application development environment
Communicate with EWS by using the EWS Managed API
Set the EWS service URL by using the
EWS Managed API
Article • 01/15/2020 • 2 minutes to read

Find information about how to set the EWS service URL in your EWS Managed API
application.

The service URL is the address that Exchange uses to communicate with Exchange Web
Services (EWS). After your EWS Managed API application has this address, and has
appropriate access to communicate with EWS, it can make calls to the ExchangeService
class . The service URL for an on-premises Exchange server might look like the
following.

HTML

https://computer.domain.contoso.com/EWS/Exchange.asmx

You can set the EWS URL in your application in a couple of ways. We recommend that
you use the Autodiscover service to get the URL because in a large forest of servers,
the URL can change if the mailbox is migrated to another server. However, because
calling Autodiscover can take some time and can slow down your application if you
need to make multiple calls in a short period of time, you might want to cache the URL
value you get from Autodiscover and manually set the EWS service URL with this cached
value. This will improve the performance of your application; just make sure that you use
Autodiscover to update your cached value periodically in case the value changes on the
server.

Set the EWS service URL by using the


Autodiscover service
The AutodiscoverUrl method uses the email address to set the ExchangeService
endpoint and enables your application to use any methods included in the
ExchangeService proxy classes. The following example shows how to use the
AutodiscoverURL method.

C#

// Create the binding.

ExchangeService service = new ExchangeService();

// Set the credentials for the on-premises server.

service.Credentials = new WebCredentials("[email protected]", "password");

// Set the URL.

service.AutodiscoverUrl("[email protected]");

Set the Exchange service URL manually


The following example shows you how to set the EWS service URL by using a cached
value. Before you do this, make sure to use the Autodiscover service to get the EWS
URL.

C#

// Create the binding.

ExchangeService service = new ExchangeService();

// Set the credentials for the on-premises server.

service.Credentials = new WebCredentials("[email protected]", "password");

// Set the URL.

service.Url = new
Uri("https://computername.domain.contoso.com/EWS/Exchange.asmx");

See also
Get started with EWS Managed API client applications
Setting up your Exchange application development environment
Control access to EWS in Exchange
Communicate with EWS by using the EWS Managed API
Use Autodiscover to find connection points
Communicate with EWS by using the
EWS Managed API
Article • 03/04/2022 • 3 minutes to read

Find information about how to use the EWS Managed API to communicate with EWS in
Exchange.

7 Note

We’re removing the ability to use Basic authentication in Exchange Online for EWS
beginning October 2022 Deprecation of Basic authentication in Exchange Online.
You should use OAuth authentication instead. Authenticate an EWS application by
using OAuth

The ExchangeService class in the EWS Managed API contains the methods and
properties that you use to set user credentials, identify the EWS endpoint, send and
receive SOAP messages, and configure the binding to communicate with EWS. Before
you can use the EWS Managed API to perform any task, you have to create an instance
of the ExchangeService class and bind it to EWS.

After you set up an ExchangeService object with user credentials and the EWS
endpoint, any mailbox object that references the ExchangeService object can use the
following method types to communicate with EWS:

ExchangeService object methods — All the methods on the ExchangeService


object that are not inherited from the base Object type make calls to EWS.
Exchange mailbox item and folder type methods.

Table 1. Mailbox item and folder type methods that communicate with EWS

Method What it does Operations that it


calls

Load
Gets properties on an item, attachment, or user configuration GetItem operation

object.
GetAttachment
operation

GetUserConfiguration
operation

Method What it does Operations that it


calls

Bind
Populates a new item on the client with information from an GetItem operation

existing item on the server.

Save
Saves the copy of the client item on the server. UpdateItem
operation

UpdateFolder
operation

CreateItem
operation

CreateFolder
operation

Update Updates the server with the changes made on the client.
UpdateItem
operation

For items and folders, the Update method uses the


UpdateItem operation and the UpdateFolder operation . UpdateFolder
operation

Delete
Deletes an item on the server.
DeleteItem
operation

For items and folders, the Delete method uses the and the
DeleteFolder operation . DeleteFolder
operation

Copy
Creates a copy of the item or folders on the server. CopyItem
operation

CopyFolder
operation

Move
Moves items or folders on the server. MoveItem
operation

MoveFolder
operation

To use the EWS Managed API to communicate


with EWS
1. Instantiate the ExchangeService class.

C#
ExchangeService service = new ExchangeService();

7 Note

Instantiating ExchangeService with an empty constructor will create an


instance that is bound to the latest known version of Exchange. Alternatively,
you can target a specific version of Exchange by specifying version as a
parameter. ExchangeService service = new
ExchangeService(ExchangeVersion.Exchange2007_SP1);

2. Set the credentials of the user who sends requests to the Exchange server. If you
want to connect to EWS from a computer that is logged on to the domain, using
the credentials of the authenticated user, set the UseDefaultCredentials property
on the ExchangeService object to true.

C#

// Connect by using the default credentials of the authenticated user.

service.UseDefaultCredentials = true;

If you do not want to connect by using the default user credentials, set the
Credentials property on the ExchangeService object to explicitly specify the
credentials of a different user. If you are using Exchange Online or Exchange
Online as part of Office 365, you'll use basic authentication, with just a user name
and password. A domain name is required for NTLM authentication.

C#

// Connect by using the credentials of user1 at contoso.com.

service.Credentials = new WebCredentials("[email protected]",


"password");

You can also specify the credentials of the user by using the user's domain name
and password.

C#

// Connect by using the credentials of contoso/user1.

service.Credentials = new WebCredentials("user1", "password",


"contoso");

7 Note

If the UseDefaultCredentials property is set to true, the value of the


Credentials property is ignored.

3. Set the URL of the EWS endpoint. This URL locates the exchange.asmx file on Client
Access server.

C#

// Use Autodiscover to set the URL endpoint.

service.AutodiscoverUrl("[email protected]");

7 Note

Although you can explicitly set the Url property of the ExchangeService to a
hardcoded value, we recommend that you use the Autodiscover service
instead, 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 if new Client Access servers are deployed. In
this scenario, using Autodiscover means no code changes are necessary.
You should either set the URL explicitly or call AutodiscoverUrl, but you
should not do both.

See also
Get started with EWS Managed API client applications
Use Autodiscover to find connection points
Develop web service clients for Exchange
Trace requests and responses to
troubleshoot EWS Managed API apps
Article • 01/15/2020 • 2 minutes to read

Find out how to trace EWS requests and responses to troubleshoot errors in your EWS
Managed API application.

Debugging a web service-based application can be difficult because part of the


processing is performed on a remote computer that you might not have access to.
Because you cannot step through the code on the server, it can be helpful to see the
XML requests and responses that are sent between the client and the server to
determine which part of the application is causing an error.

If you are using EWS, you already have access to the XML request and response; you can
put a break point in your code to review the server's response to your request in order
to troubleshoot an issue. If you're using the EWS Managed API, you don't have direct
access to the EWS request and response. However, you can use tracing methods on the
ExchangeService object to capture the XML request and response, and you can then
use the XML to determine why your code is not working.

For example, if you did not set a property correctly, you might get an unexpected
response, and you can use the trace output to look at the XML request and response to
identify the error. The trace output from the EWS Managed API can also help you
manually build the XML request to create your EWS application. If you are using EWS,
you can create a small application by using EWS Managed API, trace it, and then use the
XML request information to help you build your EWS request.

Enabling tracing on the ExchangeService object


To enable tracing, create an ExchangeService object for your application, and set the
tracing properties as shown in the following example.

C#

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);

service.TraceListener = ITraceListenerInstance;

// Optional flags to indicate the requests and responses to trace.

service.TraceFlags = TraceFlags.EwsRequest | TraceFlags.EwsResponse

service.TraceEnabled = true;

After you set the TraceEnabled property to true, all requests that match the trace flags
will be sent to the specified trace listener. You can specify a single trace flag, or you can
specify multiple trace flags by combining them with a logical OR. You can use the
TraceFlags enumeration to specify values for EWS and for Autodiscover requests and
responses.

Implementing a TraceListener object


You can set the TraceEnabled property to true to output the XML requests and
responses to your application, such as a console window. If you want to control the
trace output and save it to a file, we recommend that you implement a TraceListener
class object. The following code example shows a simple object that implements the
ITraceListener interface and stores the traced requests and responses in XML or text
files.

C#

class TraceListener : ITraceListener

#region ITraceListener Members

public void Trace(string traceType, string traceMessage)

CreateXMLTextFile(traceType, traceMessage.ToString());

#endregion

private void CreateXMLTextFile(string fileName, string traceContent)

// Create a new XML file for the trace information.

try

// If the trace data is valid XML, create an XmlDocument object and


save.

XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(traceContent);

xmlDoc.Save(fileName + ".xml");

catch

// If the trace data is not valid XML, save it as a text document.

System.IO.File.WriteAllText(fileName + ".txt", traceContent);

See also
Start using web services in Exchange
Handling Autodiscover error messages
Reference the EWS Managed API assembly
Communicate with EWS by using the EWS Managed API
Get started with EWS client applications
Article • 03/04/2022 • 10 minutes to read

Create your first application by using Exchange Web Services (EWS) in Exchange.

EWS is a comprehensive service that your applications can use to access almost all the
information stored in an Exchange Online, Exchange Online as part of Office 365, or
Exchange on-premises mailbox. EWS uses standard web protocols to provide access to
an Exchange server; libraries like the EWS Managed API wrap the EWS operations to
provide an object-oriented interface. After you've run the examples in this article, you
will have a basic understanding of what you can do with EWS.

You can call EWS operations from any operating system or language, because the EWS
requests and responses use the SOAP protocol. The examples in this article are written
using C# and make use of the .NET Framework HttpWebRequest and
HttpWebResponse objects; however, the important part of the code is the XML used
to make the EWS request and the XML response returned from the server. The code
examples emphasize the XML transactions and not processing the XML.

7 Note

We’re removing the ability to use Basic authentication in Exchange Online for EWS
beginning October 2022 Deprecation of Basic authentication in Exchange Online.
You should use OAuth authentication instead. Authenticate an EWS application by
using OAuth

You'll need an Exchange server


If you already have an Exchange mailbox account, you can skip this step. Otherwise, you
have the following options for setting up an Exchange mailbox for your first EWS
application:

Get an Office 365 Developer Site(recommended). This is the quickest way for you
to get an Exchange mailbox.

Download Exchange Server .

After you've verified that you can send and receive email from your Exchange server you
are ready to set up your development environment. You can use Outlook Web App to
verify that you can send email.
You'll also need to know the URL of the EWS endpoint for your server. In a production
application, you'd use Autodiscover to determine the EWS URL. The examples in this
article use the Office 365 EWS endpoint URL,
https://outlook.office365.com/EWS/Exchange.asmx . The Next steps section has links to
more information about Autodiscover when you're ready.

If you are testing your application using an Exchange server that has the default self-
signed certificate, you'll need to create a certificate validation method that meets the
security requirements of your organization.

Set up your development environment


The tools that you use to create your first EWS application depend on the operating
system and language that you use, and are mostly a matter of taste. If you want to
follow along with the C# examples in this article, you'll need:

Any version of Visual Studio that supports the .NET Framework 4.0.
An Internet connection that your development machine can use to contact your
Exchange server. If you can use Outlook Web App with a DNS name rather than an
IP address to connect to your Exchange server, you are set up.

Create your first EWS application


The EWS application that you will create shows two typical scenarios for using EWS:

1. Get information from an Exchange mailbox and display that information to the
user.
2. Perform an action, such as sending an email, and check the response to see if the
action succeeded.

Let's get started.

Set up the solution


First, create a new console application solution using Visual Studio. When the solution is
ready, create a new object called Tracing.cs. Use this object to write information to both
the console and a log file so that you can review the results after you run your code.
Paste the following code into the Tracing.cs file.

C#
using System;

using System.IO;

namespace Microsoft.Exchange.Samples.EWS

class Tracing

private static TextWriter logFileWriter = null;

public static void OpenLog(string fileName)

logFileWriter = new StreamWriter(fileName);

public static void Write(string format, params object[] args)

Console.Write(format, args);

if (logFileWriter != null)

logFileWriter.Write(format, args);

public static void WriteLine(string format, params object[] args)

Console.WriteLine(format, args);

if (logFileWriter != null)

logFileWriter.WriteLine(format, args);

public static void CloseLog()

logFileWriter.Flush();

logFileWriter.Close();

Next, open the Program.cs file. You will put the rest of the code for the example in this
file.

First, set up the shell of the program. The program will:

1. Create a log file so that the request and response can be written to disk for later
study.
2. Get the email address and password of the account that you'll access.
3. Call the sample methods.

Replace the Main method in the Program.cs with the following code.

C#
static void Main(string[] args)

// Start tracing to console and a log file.

Tracing.OpenLog("./GetStartedWithEWS.log");

Tracing.WriteLine("EWS sample application started.");

var isValidEmailAddress = false;

Console.Write("Enter an email address: ");

var emailAddress = Console.ReadLine();

isValidEmailAddress = (emailAddress.Contains("@") &amp;&amp;


emailAddress.Contains("."));

if (!isValidEmailAddress)

Tracing.WriteLine("Email address " + emailAddress + " is not a valid


SMTP address. Closing program.");
return;

SecureString password = GetPasswordFromConsole();

if (password.Length == 0)

Tracing.WriteLine("Password empty, closing program.");

NetworkCredential userCredentials = new


NetworkCredential(emailAddress, password);

// These are the sample methods that demonstrate using EWS.

// ShowNumberOfMessagesInInbox(userCredentials);

// SendTestEmail(userCredentials);

Tracing.WriteLine("EWS sample application ends.");

Tracing.CloseLog();

Console.WriteLine("Press enter to exit: ");

Console.ReadLine();

// These method stubs will be filled in later.

private static void ShowNumberOfMessagesInInbox(NetworkCredential


userCredentials)

private static void SendTestEmail(NetworkCredential userCredentials)

The last thing that you need to do is add the GetPasswordFromConsole static method.
This method returns a SecureString object that contains a password typed at the
console.

C#

private static SecureString GetPasswordFromConsole()

SecureString password = new SecureString();

bool readingPassword = true;

Console.Write("Enter password: ");

while (readingPassword)

ConsoleKeyInfo userInput = Console.ReadKey(true);

switch (userInput.Key)

case (ConsoleKey.Enter):

readingPassword = false;

break;

case (ConsoleKey.Escape):

password.Clear();

readingPassword = false;

break;

case (ConsoleKey.Backspace):

if (password.Length > 0)

password.RemoveAt(password.Length - 1);

Console.SetCursorPosition(Console.CursorLeft - 1,
Console.CursorTop);

Console.Write(" ");

Console.SetCursorPosition(Console.CursorLeft - 1,
Console.CursorTop);

break;

default:

if (userInput.KeyChar != 0)

password.AppendChar(userInput.KeyChar);

Console.Write("*");

break;

Console.WriteLine();

password.MakeReadOnly();

return password;

Get the number of new messages in an Inbox


A common operation in an EWS application is to get information about email messages,
appointments, meetings, and the folders that store them. This example gets the number
of messages in an account's Inbox and displays the total number of messages and the
number of unread messages. It demonstrates the following common actions for EWS
applications:

Making an EWS request to the Exchange server.


Parsing the returned XML response for the requested information.
Handling common exceptions and error messages.
Add the following code to the ShowNumberOfMessagesInInbox method that was stubbed
out after the main method. When you run the application, it will print the number of
messages in the account's Inbox and the number of unread messages in the Inbox. After
you run the application, you can open the GetStartedWithEWS.log file to see the XML
request that was sent to the Exchange server and the response that the server returned.

C#

/// This is the XML request that is sent to the Exchange server.

var getFolderSOAPRequest =

"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +

"<soap:Envelope xmlns:soap=\"https://schemas.xmlsoap.org/soap/envelope/\"\n"
+

"
xmlns:t=\"https://schemas.microsoft.com/exchange/services/2006/types\">\n" +

"<soap:Header>\n" +

" <t:RequestServerVersion Version=\"Exchange2007_SP1\" />\n" +

" </soap:Header>\n" +

" <soap:Body>\n" +

" <GetFolder
xmlns=\"https://schemas.microsoft.com/exchange/services/2006/messages\"\n" +

"
xmlns:t=\"https://schemas.microsoft.com/exchange/services/2006/types\">\n" +

" <FolderShape>\n" +

" <t:BaseShape>Default</t:BaseShape>\n" +

" </FolderShape>\n" +

" <FolderIds>\n" +

" <t:DistinguishedFolderId Id=\"inbox\"/>\n" +

" </FolderIds>\n" +

" </GetFolder>\n" +

" </soap:Body>\n" +

"</soap:Envelope>\n";

// Write the get folder operation request to the console and log file.

Tracing.WriteLine("Get folder operation request:");

Tracing.WriteLine(getFolderSOAPRequest);

var getFolderRequest = WebRequest.CreateHttp(Office365WebServicesURL);

getFolderRequest.AllowAutoRedirect = false;

getFolderRequest.Credentials = userCredentials;

getFolderRequest.Method = "POST";

getFolderRequest.ContentType = "text/xml";

var requestWriter = new


StreamWriter(getFolderRequest.GetRequestStream());

requestWriter.Write(getFolderSOAPRequest);

requestWriter.Close();

try

var getFolderResponse = (HttpWebResponse)


(getFolderRequest.GetResponse());
if (getFolderResponse.StatusCode == HttpStatusCode.OK)

var responseStream = getFolderResponse.GetResponseStream();

XElement responseEnvelope = XElement.Load(responseStream);

if (responseEnvelope != null)

// Write the response to the console and log file.

Tracing.WriteLine("Response:");

StringBuilder stringBuilder = new StringBuilder();

XmlWriterSettings settings = new XmlWriterSettings();

settings.Indent = true;

XmlWriter writer = XmlWriter.Create(stringBuilder, settings);

responseEnvelope.Save(writer);

writer.Close();

Tracing.WriteLine(stringBuilder.ToString());

// Check the response for error codes. If there is an error,


throw an application exception.

IEnumerable<XElement> errorCodes = from errorCode in


responseEnvelope.Descendants

("
{https://schemas.microsoft.com/exchange/services/2006/messages}ResponseCode"
)

select errorCode;

foreach (var errorCode in errorCodes)

if (errorCode.Value != "NoError")

switch (errorCode.Parent.Name.LocalName.ToString())

case "Response":

string responseError = "Response-level error getting


inbox information:\n" + errorCode.Value;

throw new ApplicationException(responseError);

case "UserResponse":

string userError = "User-level error getting inbox


information:\n" + errorCode.Value;

throw new ApplicationException(userError);

// Process the response.

IEnumerable<XElement> folders = from folderElement in

responseEnvelope.Descendants

("
{https://schemas.microsoft.com/exchange/services/2006/messages}Folders")

select folderElement;

foreach (var folder in folders)

Tracing.Write("Folder name: ");

var folderName = from folderElement in

folder.Descendants

("
{https://schemas.microsoft.com/exchange/services/2006/types}DisplayName")

select folderElement.Value;

Tracing.WriteLine(folderName.ElementAt(0));

Tracing.Write("Total messages: ");

var totalCount = from folderElement in

folder.Descendants

("
{https://schemas.microsoft.com/exchange/services/2006/types}TotalCount")

select folderElement.Value;

Tracing.WriteLine(totalCount.ElementAt(0));

Tracing.Write("Unread messages: ");

var unreadCount = from folderElement in

folder.Descendants

("
{https://schemas.microsoft.com/exchange/services/2006/types}UnreadCount")

select folderElement.Value;

Tracing.WriteLine(unreadCount.ElementAt(0));

catch (WebException ex)

Tracing.WriteLine("Caught Web exception:");

Tracing.WriteLine(ex.Message);

catch (ApplicationException ex)

Tracing.WriteLine("Caught application exception:");

Tracing.WriteLine(ex.Message);

Send an email message


Another common operation for an EWS application is to send email messages or
meeting requests. This example creates and sends an email message using the user
credentials that were entered earlier. It demonstrates these common EWS application
tasks:

Creating and sending an email.

Parsing the returned XML response to determine if the email was correctly sent.

Handling common exceptions and error messages.

Add the following code to the SendTestEmail method that was stubbed out after the
main method. After you run the application, you can open the GetStartedWithEWS.log
file to see the XML request that was sent to the Exchange server and the response that
the server returned.

C#

var createItemSOAPRequest =

"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +

"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-
instance\" \n" +

"
xmlns:m=\"https://schemas.microsoft.com/exchange/services/2006/messages\"
\n" +

"
xmlns:t=\"https://schemas.microsoft.com/exchange/services/2006/types\" \n" +

"
xmlns:soap=\"https://schemas.xmlsoap.org/soap/envelope/\">\n" +

" <soap:Header>\n" +

" <t:RequestServerVersion Version=\"Exchange2007_SP1\" />\n" +

" </soap:Header>\n" +

" <soap:Body>\n" +

" <m:CreateItem MessageDisposition=\"SendAndSaveCopy\">\n" +

" <m:SavedItemFolderId>\n" +

" <t:DistinguishedFolderId Id=\"sentitems\" />\n" +

" </m:SavedItemFolderId>\n" +

" <m:Items>\n" +

" <t:Message>\n" +

" <t:Subject>Company Soccer Team</t:Subject>\n" +

" <t:Body BodyType=\"HTML\">Are you interested in joining?


</t:Body>\n" +

" <t:ToRecipients>\n" +

" <t:Mailbox>\n" +

" <t:EmailAddress>[email protected]</t:EmailAddress>\n" +

" </t:Mailbox>\n" +

" </t:ToRecipients>\n" +

" </t:Message>\n" +

" </m:Items>\n" +

" </m:CreateItem>\n" +

" </soap:Body>\n" +

"</soap:Envelope>\n";

// Write the create item operation request to the console and log
file.

Tracing.WriteLine("Get folder operation request:");

Tracing.WriteLine(createItemSOAPRequest);

var getFolderRequest = WebRequest.CreateHttp(Office365WebServicesURL);

getFolderRequest.AllowAutoRedirect = false;

getFolderRequest.Credentials = userCredentials;

getFolderRequest.Method = "POST";

getFolderRequest.ContentType = "text/xml";

var requestWriter = new


StreamWriter(getFolderRequest.GetRequestStream());

requestWriter.Write(createItemSOAPRequest);

requestWriter.Close();

try

var getFolderResponse = (HttpWebResponse)


(getFolderRequest.GetResponse());
if (getFolderResponse.StatusCode == HttpStatusCode.OK)

var responseStream = getFolderResponse.GetResponseStream();

XElement responseEnvelope = XElement.Load(responseStream);

if (responseEnvelope != null)

// Write the response to the console and log file.

Tracing.WriteLine("Response:");

StringBuilder stringBuilder = new StringBuilder();

XmlWriterSettings settings = new XmlWriterSettings();

settings.Indent = true;

XmlWriter writer = XmlWriter.Create(stringBuilder, settings);

responseEnvelope.Save(writer);

writer.Close();

Tracing.WriteLine(stringBuilder.ToString());

// Check the response for error codes. If there is an error,


throw an application exception.

IEnumerable<XElement> errorCodes = from errorCode in


responseEnvelope.Descendants

("
{https://schemas.microsoft.com/exchange/services/2006/messages}ResponseCode"
)

select errorCode;

foreach (var errorCode in errorCodes)

if (errorCode.Value != "NoError")

switch (errorCode.Parent.Name.LocalName.ToString())

case "Response":

string responseError = "Response-level error getting


inbox information:\n" + errorCode.Value;

throw new ApplicationException(responseError);

case "UserResponse":

string userError = "User-level error getting inbox


information:\n" + errorCode.Value;

throw new ApplicationException(userError);

Tracing.WriteLine("Message sent successfully.");

catch (WebException ex)

Tracing.WriteLine("Caught Web exception:");

Tracing.WriteLine(ex.Message);

catch (ApplicationException ex)

Tracing.WriteLine("Caught application exception:");

Tracing.WriteLine(ex.Message);

Next steps
Now that you've written your first EWS application, you're ready to discover other ways
to use EWS. Here are some ideas to get you started:
Implement Autodiscover in your application so that your application will connect
to the correct Exchange server based on the user's email address. See also the
Exchange 2013: Get user settings with Autodiscover sample.

Look at the EWS reference for more information about EWS.

See the EWS operations for information about the operations that are available.

Use EWS Editor to see the SOAP traffic sent to and from the server.

If you run into any issues with your application, try posting a question or comment in
the forum (and don't forget to read the first post).

See also
Start using web services in Exchange
Explore the EWS Managed API, EWS, and web services in Exchange
EWS client design overview for Exchange
Develop web service clients for Exchange
Get started with EWS Managed API client applications
EWS functionality in Exchange product
versions
Article • 09/15/2021 • 2 minutes to read

EWS implements new functionality in new product releases. Use the information in this
article to determine whether the version of Exchange you're targeting includes support
for the data or features you need access to.

The following table lists the versions of Exchange that include EWS and the major
features that were introduced in each version.

EWS features by product version


Product Features
version

Office 365 Includes all the features in the current version of Exchange in addition to any new
and features that are added for online clients.
Exchange
Online

Exchange Includes all features introduced in Exchange 2013. The following features were
2013 SP1 introduced in Exchange 2013 SP1:
Read receipts can now be suspended for updates and deletions.
You can get moderated transport approval information.
Voting responses can be viewed.
The SetHoldOnMailboxes method and SetHoldOnMailboxes operation
accept all the parameters in a single object.
eDiscovery searches can specify a language for search queries and a
culture-specific format for date ranges.
The StreamingSubscriptionConnection object can now access the
StreamingSubscription objects.
Conversations have a setting to indicate whether they contain email
messages that are protected by IRM.
Meeting attendees can propose new start and end times for meetings and
include them in their meeting response.
The SOAP Autodiscover GetUserSettings method now returns the
GroupingInformation setting that is used maintain affinity for a multiple
mailbox event subscription.
Product Features
version

Exchange Includes all features introduced in Exchange 2010 SP2. The following features
2013 were introduced in Exchange 2013:
Archiving
eDiscovery
Personas
Retention policies
Unified Contact Store
User photos

Exchange Includes all the features introduced in Exchange 2010 SP1. The following features
2010 SP2 were introduced in Exchange 2010 SP2:
Get Password Expiration
DateTime precision
Updated property identifiers for contacts
New impersonation scenarios

Exchange Includes all the features introduced in Exchange 2010. The following features
2010 SP1 were introduced in Exchange 2010 SP1:
Create, retrieve and modify Inbox rules
Programmatic access to Archive Mailbox
Conversations actions
Firewall traversing notifications
Improved administration features
Improved mixed version support
Throttling protection support
Control of application access to EWS
Client certificate authentication support

Exchange Includes all features introduced in Exchange 2007 SP1. The following features
2010 were introduced in the initial release version of Exchange 2010:
Full Private Distribution List
User Configuration Objects
Folder Associated Items
Message tracking
Unified Messaging
SOAP Autodiscover
Enhanced Time Zone support
Room resource availability information
Indexed search
Dumpster access
MailTips information
Product Features
version

Exchange Includes all the features introduced in Exchange 2007. The following features
2007 SP1 were introduced in Exchange 2007 SP1:
Delegate management
Folder permissions
Public folders
Post items
ID conversion

Exchange The following features were introduced in the initial release version of Exchange
2007 2007:
Full access to items, folders, and attachments (Create, Get, Update, Delete)
Availability
Out of Office settings
Notifications
Synchronization
Name resolution
Distribution list (DL) expansion
Search

See also
Start using web services in Exchange
Migrating to Exchange technologies
Explore the EWS Managed API, EWS, and web services in Exchange
Setting up your EWS application
Article • 01/18/2019 • 2 minutes to read

Find information about the tasks you need to complete in order to create applications
that use the EWS Managed API or EWS to communicate with Exchange.

When you create a client application that calls web services on Exchange Online,
Exchange Online as part of Office 365, or a version of Exchange starting with Exchange
2013, you'll need to set up your application to communicate with the Exchange server.
The articles in this section provide code examples that show you how to use the
Exchange Web Services (EWS) Managed API or EWS XML requests and responses to set
up your application.

In this section
Setting up your Exchange application development environment

Controlling client application access to EWS in Exchange

Managing user access by using EWS in Exchange

Validate a server certificate for the EWS Managed API

See also
Start using web services in Exchange

EWS client design overview for Exchange

Develop web service clients for Exchange


Setting up your Exchange application
development environment
Article • 01/22/2022 • 3 minutes to read

Learn about how to set up your development environment to create an EWS application
that communicates with Exchange.

Before you start writing your Exchange Web Services (EWS) application, you'll need to
make sure that your development environment meets a few minimum requirements.
You can use the EWS Managed API, the standard client access API for .NET Framework
applications, to develop your application, or you can use EWS on its own, with our
without an autogenerated proxy. In general, we recommend that you use the EWS
Managed API; however, you can explore the difference between these two options in
more detail to find out which one is right for you.

7 Note

The EWS Managed API is now available as an open source project on GitHub .
You can use the open source library to:

Contribute bug fixes and enhancements to the API.


Get fixes and enhancements before they are available in an official release.
Access the most comprehensive and up-to-date implementation of the API, to
use as a reference or to create new libraries on new platforms.

We welcome your contributions via GitHub.

Development environment for the EWS


Managed API
To create an EWS Managed API application, you'll need access to the following:

The EWS Managed API .

You can store the EWS Managed API files anywhere on your computer; by default,
they are installed in the Program Files\Microsoft\Exchange\Web Services<version
number> folder.
A mailbox on an Exchange server that is running Exchange Online, Exchange
Online as part of Office 365, or a version of Exchange starting with Exchange
Server 2007.

You can get an Exchange Online plan for business, including a free trial, from the
Office 365 site . In order to connect to the mailbox you must have the user name
and credentials of the account associated with the mailbox.

A version of Visual Studio starting with Visual Studio 2005. If you don't currently
have Visual Studio, you can download a free version .

A version of the .NET Framework starting with the .NET Framework 3.5. You can
download the .NET Framework 3.5 from the Microsoft Download Center .

In addition, it is helpful if you have some familiarity with C#. Although Visual Studio
supports other languages in addition to C#, most of the sample code available for the
EWS Managed API is written in C#.

Development environment for EWS


You can use EWS to develop your application in a couple of different ways. The simplest
way to use EWS is to create text files that contain your XML requests, and transmit them
to Exchange. To do this, here is what you need:

A simple text editor, like Notepad, to edit your XML request. Any text editor will
do, although you might want one that will help with your XML syntax validation
like XMetal.

A tool or application that can send and receive SOAP XML requests and responses,
in order to communicate with Exchange.

When you work with raw XML, it's also helpful to have a basic understanding of XML
formatting.

The second way to use EWS is to create an autogenerated proxy that enables you to
work with the operations by using a .NET language like C#. Here is what you need to
work with an autogenerated proxy:

A version of Visual Studio starting with Visual Studio 2005, to create a proxy
reference. You can download a free version .

A version of the .NET Framework starting with the .NET Framework 2.0. You can
download the .NET Framework 3.5 from the Microsoft Download Center .
If you use an autogenerated proxy, you'll want to have some familiarity with C#
programming.

7 Note

If you're a .NET Framework developer, we encourage you to use the EWS Managed
API rather than autogenerated proxies to develop against EWS. The EWS Managed
API object model is easier to use than autogenerated proxy object models. Also,
the EWS Managed API implements Autodiscover and includes client-side logic.

See also
Setting up your Exchange application development environment
EWS client design overview for Exchange
Control access to EWS in Exchange
EWS generated object models for Exchange
Controlling client application access to
EWS in Exchange
Article • 06/14/2022 • 2 minutes to read

Learn about the options for managing client application access to EWS.

Any EWS client application that you create must be granted access to Exchange Online,
Exchange Online as part of Office 365, or version of Exchange starting with Exchange
2013 before it can call EWS operations. Test or production server administrators can use
the Exchange Management Shell to limit access to EWS either for all users and
applications, for individual users, or for individual applications. Access control for EWS is
based on domain accounts. When a connection is made with credentials that are
authenticated by the local security authority, the server returns an error that indicates
that only domain accounts can connect.

Access control for EWS clients and users


Your test or production server administrator can configure access control for clients that
connect to EWS in the following ways:

By blocking all client applications from connecting.

By allowing specific client applications only to connect.

By allowing any client application to connect except those that are specifically
blocked.

By allowing any client application to connect.

Applications are identified by the user agent string that they send in the HTTP web
request.

) Important

Application-level blocking is not a security feature. The user agent string is easily
spoofed. If an application is allowed access to EWS, the application must still
present credentials that the server authenticates before the application can connect
to EWS.
Administrators can also configure access control for mailbox owners that connect to
EWS in the following ways:

By blocking or allowing an entire organization.

By blocking or allowing a group of users identified by a role-based authentication


scope that includes or excludes mailbox owners that do not have access to EWS.

By blocking or allowing an individual mailbox owner.

Specific access control settings override general access control settings. For example, if
an organization denies EWS access but an individual mailbox owner is allowed
application access, the individual setting prevails and access is allowed.

Delegation and EWS access management


When delegate users who do not have access to EWS use your client application, they
will not be able to access the principal user's mailbox by using EWS, even if the principal
user has EWS access. If the delegate user has EWS access, the delegate will be able to
use your EWS client application to access the principal user's mailbox even if the
principal user does not have EWS access.

Impersonation and EWS access management


Client applications that connect to EWS on behalf of mailbox owners might not be able
to use the EWS settings of the mailbox owner. For example, an application that archives
email messages for a company has to connect to EWS regardless of what the mailbox
users' settings are. Other applications, such as mail clients, do have to use the mailbox
owner's EWS settings.

Administrators should create an impersonation account for each application or


application class that they use on their server. This will enable the administrator to
configure the role-based access control scope for all users that do not have EWS
permissions.

To enable impersonation accounts, your test or production server administrator should


do one of the following:

Add the Authenticated Users group to the Pre-Win2K Compatible Access Group.

Add the Exchange Servers group to the Windows Authorization Access group.
Exchange Management Shell cmdlets for access
management
Administrators use the following Exchange Management Shell cmdlets to configure EWS
access controls:

Get-CASMailbox
Set-CASMailbox
Get-OrganizationConfig
Set-OrganizationConfig

See also
Start using web services in Exchange
Control access to EWS in Exchange
Exchange Server PowerShell (Exchange Management Shell)
Windows PowerShell
Control access to EWS in Exchange
Article • 06/14/2022 • 2 minutes to read

Find out how to control access to EWS for users, applications, or the entire organization.

Whether you are using the EWS Managed API, or EWS directly, in your application, you
can control access to Exchange Web Services (EWS). If you have administrator access to
your Exchange server, you can manage access to EWS by using the Exchange
Management Shell to control access globally, for each user, and for each application.

Exchange Management Shell cmdlets for


configuring access control
You can use the following Exchange Management Shell cmdlets to view the current
access configuration and set EWS access controls:

Get-CASMailbox - Shows you what parameters are set for a particular mailbox.
Set-CASMailbox - Sets parameters for a particular mailbox.
Get-OrganizationConfig - Shows you the parameters for the entire organization.
Set-OrganizationConfig - Sets the parameters for the entire organization.

Examples: Controlling access to EWS


Let's take a look at a few scenarios that show you how you can control access to your
application.

Table 1. Commands for controlling access to EWS

If you want to Use this command

Block all client applications from Set-OrganizationConfig -


using EWS. EwsApplicationAccessPolicy:EnforceAllowList

This allows applications listed in the AllowList to connect. In


this example, no applications are included in the AllowList, so
no applications can use EWS.
If you want to Use this command

Allow a list of client applications Set-OrganizationConfig -


to use EWS. EwsApplicationAccessPolicy:EnforceAllowList -
EwsAllowList:"OWA/*"

This allows specific applications to use EWS. In this example,


any application that has a user agent string that starts with
"OWA/" is allowed access.

Allow all client applications to Set-OrganizationConfig -


use EWS except those that are EwsApplicationAccessPolicy:EnforceBlockList -
specifically blocked. EwsBlockList:"OWA/*"

This example only blocks applications from using EWS that


have a user agent string that starts with "OWA/".

Allow all client applications to Set-OrganizationConfig -


use EWS. EwsApplicationAccessPolicy:EnforceBlockList

Because no BlockList is specified, all applications can use EWS.

Block the entire organization Set-OrganizationConfig -EwsEnabled:$false


from using EWS.

Allow the entire organization to Set-OrganizationConfig -EwsEnabled:$true


use EWS.

Block an individual mailbox from Set-CASMailbox -Identity [email protected] -


using EWS. EwsEnabled:$false

Allow an individual mailbox to Set-CASMailbox -Identity [email protected] -


use EWS. EwsEnabled:$true

See also
Setting up your EWS application
Controlling client application access to EWS in Exchange
Exchange Server PowerShell (Exchange Management Shell)
Windows PowerShell
Managing user access by using EWS in
Exchange
Article • 06/14/2022 • 2 minutes to read

Find out what your options are for managing user account access to your Exchange
server.

Exchange Web Services (EWS) and the EWS managed API provide a limited number of
operations that you can use to manage accounts on Exchange Online, Exchange Online
as part of Office 365, or a version of Exchange starting with Exchange 2013. You can use
the operations shown in the following figure to manage delegates and to set folder
access permissions for other accounts.

EWS operations for delegate and folder access

If your application needs additional control over the accounts on an Exchange server,
you can use Exchange Management Shell cmdlets to manage the accounts. You can call
the Exchange Management Shell cmdlets by doing one of the following:

Writing an application using C# or Visual Basic that calls the Exchange


Management Shell cmdlets. You can look at the sample code in the Exchange
Management Shell API documentation to learn how to call a cmdlet.

Using Windows PowerShell and Windows PowerShell scripts to call Exchange


Management Shell cmdlets. You can find a complete list of the Exchange Server
PowerShell (Exchange Management Shell), along with examples that show how to
use them.

See also
Setting up your EWS application
Exchange 2013 Cmdlets
Validate a server certificate for the EWS
Managed API
Article • 02/11/2022 • 3 minutes to read

Learn how to create and reference a certificate validation callback method so that you
can make EWS Managed API requests to an Exchange server.

By default, versions of Exchange starting with Exchange 2007 SP1 use self-signed X509
certificates to authenticate calls from EWS. When you are using the EWS Managed API,
you need to create a certificate validation callback method; otherwise, EWS Managed
API requests will fail. If you are using the Autodiscover service, the call to the EWS
Managed API Autodiscover method will fail with an AutodiscoverLocalException error.
If you are using a web-generated web service proxy, you might also have to create a
validation callback method, depending on how the proxy is created.

Prerequisites for creating a validation callback


method
To set up to validate a server certificate, ensure that the following are true:

Your Exchange server is using a self-signed certificate for EWS. If the administrator
has installed a valid certificate that traces to a root certificate, you do not need to
create a validation callback method.

You are creating a managed application that includes a reference to the following
required .NET Framework namespaces:
System.Net
System.Net.Security
System.Security.Cryptography.X509Certificates

Example: Callback method to validate a server


certificate for the EWS Managed API
The following code example shows how to create an X509 certificate validation callback
method for the EWS Managed API. This method will validate an X509 certificate and
only return true when either of the following criteria are met:

The certificate is valid and traces back to a valid root certificate.


The certificate is valid and is self-signed by the server that returned it.
) Important

The certificate validation callback method in this example provides sufficient


security for development and testing of EWS Managed API applications. However,
it might not provide sufficient security for your deployed application. You should
always make sure that the certificate validation callback method that you use meets
the security requirements of your organization.

C#

private static bool CertificateValidationCallBack(

object sender,

System.Security.Cryptography.X509Certificates.X509Certificate
certificate,

System.Security.Cryptography.X509Certificates.X509Chain chain,

System.Net.Security.SslPolicyErrors sslPolicyErrors)

// If the certificate is a valid, signed certificate, return true.

if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)

return true;

// If there are errors in the certificate chain, look at each error to


determine the cause.

if ((sslPolicyErrors &amp;
System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)

if (chain != null &amp;&amp; chain.ChainStatus != null)

foreach
(System.Security.Cryptography.X509Certificates.X509ChainStatus status in
chain.ChainStatus)

if ((certificate.Subject == certificate.Issuer) &amp;&amp;

(status.Status ==
System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.Untrusted
Root))

// Self-signed certificates with an untrusted root are valid.

continue;

else

if (status.Status !=
System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)

// If there are any other errors in the certificate chain,


the certificate is invalid,

// so the method returns false.

return false;

// When processing reaches this line, the only errors in the


certificate chain are

// untrusted root errors for self-signed certificates. These


certificates are valid

// for default Exchange server installations, so return true.

return true;

else

// In all other cases, return false.

return false;

You use the ServicePointManager class in the .NET System.Net namespace to hook up a
validation callback method by setting the ServerCertificateValidationCallback property.
You can use code similar to the following code example to set the
ServerCertificateValidationCallback property.

C#

ServicePointManager.ServerCertificateValidationCallback =
CertificateValidationCallBack;

Next steps
After you have created the validation callback method for the EWS Managed API, you
can use the Autodiscover service to get connection points and user and domain settings
from an Exchange server. For more information, see the following articles:

Use Autodiscover to find connection points

Get user settings from Exchange by using Autodiscover

Get user settings from Exchange by using Autodiscover

Get domain settings from an Exchange server

See also
Setting up your EWS application
Start using web services in Exchange
Authentication and EWS in Exchange
Article • 06/14/2022 • 4 minutes to read

Find information to help you choose the right authentication standard for your EWS
application that targets Exchange.

Authentication is a key part of your Exchange Web Services (EWS) application. Exchange
Online, Exchange Online as part of Office 365, and on-premises versions of Exchange
starting with Exchange Server 2013 support standard web authentication protocols to
help secure the communication between your application and the Exchange server.

If you're targeting Exchange Online, the authentication method that you choose must
use HTTPS to encrypt the requests and responses that your application sends. Although
you can use HTTP with Exchange on-premises servers, we recommend that you use
HTTPS for any request that your application sends to an EWS endpoint to help secure
communication between your application and an Exchange server.

Exchange provides the following authentication options for you to choose from:

OAuth 2.0 (Exchange Online only)

NTLM (Exchange on-premises only)

Basic (no longer recommended)

The authentication method that you choose depends on the security requirements of
your organization, whether you are using Exchange Online or Exchange on-premises,
and whether you have access to a third-party provider that can issue OAuth tokens. This
article provides information that will help you select the authentication standard that's
right for your application.

OAuth authentication
We recommend that all new applications use the OAuth standard to connect to
Exchange Online services. The advantage in security over basic authentication is worth
the additional work required to implement OAuth in your application. For the record,
however, there are also some disadvantages that you should be aware of.

Table 1. Advantages and disadvantages of using OAuth

Advantages Disadvantages
Advantages Disadvantages

OAuth is an industry-standard authentication protocol.


OAuth relies on a third-party
authentication provider. This can
Authentication is managed by a third-party provider. Your impose additional costs on your
application does not have to collect and store the Exchange organization or your customers.

credentials.

The OAuth standard is more


Fewer worries for you, because your application only receives difficult to implement than basic
an opaque token from the authentication provider; therefore, authentication.

a security breach in your application can only expose the


token, not the user's Exchange credentials. To implement OAuth, you need to
integrate your application with
both the authentication provider
and the Exchange server.

To help minimize the disadvantages, you can use the Microsoft Azure AD Authentication
Library (ADAL) to authenticate users to Active Directory Domain Services (AD DS) in the
cloud or on-premises and then obtain access tokens for securing calls to an Exchange
server. Exchange Online requires tokens issued by the Azure Active Directory service,
which is supported by the ADAL; however, you can use any third-party library.

To learn more about using OAuth authentication in your EWS application, see the
following resources:

Office 365 trial, to set up an Exchange server to use to test your client application.

Azure AD Authentication Library for .NET

Configure Azure Active Directory , to enable your application to use OAuth


tokens for authentication.

Review the sample code in Authenticate an EWS application by using OAuth for
example code that you can study.

NTLM authentication
NTLM authentication is only available for Exchange on-premises servers. For
applications that run inside the corporate firewall, integration between NTLM
authentication and the .NET Framework provides a built-in means to authenticate your
application.

Table 2. Advantages and disadvantages of using NTLM authentication

Advantages Disadvantages
Advantages Disadvantages

Works "out of the box" with your Exchange server. You Users must be logged on to a domain
can configure access to Exchange services by using an to use NTLM authentication.

Exchange Management Shell cmdlet.

It can be difficult to access email


Uses the .NET Framework CredentialCache object to accounts that are not associated with
automatically get the user's credentials.
the user's domain account.

Code samples are available that use the logged on Service applications must have a
user's credentials for authentication to an on-premises domain account to take advantage of
Exchange server. NTLM authentication.

Basic authentication
Basic authentication provides a, well, basic level of security for your client application.
We do recommend that all new applications use either NTLM or the OAuth protocol for
authentication; however, basic authentication can be the correct choice for your
application in some circumstances.

Table 3. Advantages and disadvantages of using basic authentication

Advantages Disadvantages

Works "out of the box" with your Exchange server. Requires your application to collect and
You can configure access to Exchange services by store the user's credentials.

using an Exchange Management Shell cmdlet.

You have to turn off NTLM authentication


Windows applications can use the logged on user's if you want to force all users to use basic
default credentials.
authentication.

Many code samples are available that show you If a security breach occurs in your
how to call EWS using basic authentication. application, it can expose the user's email
address and password to the attacker.

You need to decide if basic authentication meets the security requirements of your
organization and customers. Basic authentication can be the right choice if you want to
avoid extensive setup tasks, for example for simple test or demonstration applications.

7 Note

Basic authentication is no longer supported for EWS to connect to Exchange


Online. Use OAuth authentication in all your new or existing EWS applications to
connect to Exchange Online. OAuth authentication for EWS is only available in
Exchange Online as part of Microsoft 365. EWS applications that use OAuth must
be registered with Azure Active Directory first.

See also
Authenticate an EWS application by using OAuth
Start using web services in Exchange
Adding Sign-On to Your Web Application Using Microsoft Azure AD
Control access to EWS in Exchange
Controlling client application access to EWS in Exchange
Supported token and claim types
Authenticate an EWS application by
using OAuth
Article • 10/31/2022 • 6 minutes to read

Learn how to use OAuth authentication with your EWS Managed API applications.

You can use the OAuth authentication service provided by Azure Active Directory to
enable your EWS Managed API applications to access Exchange Online in Office 365. To
use OAuth with your application you will need to:

1. Register your application with Azure Active Directory.


2. Add code to get an authentication token to get an authentication token from a
token server.
3. Add an authentication token to EWS requests that you send.

7 Note

OAuth authentication for EWS is only available in Exchange Online as part of


Microsoft 365. EWS applications that use OAuth must be registered with Azure
Active Directory.

To use the code in this article, you will need to have access to the following:

A Microsoft 365 account with an Exchange Online mailbox. If you do not have a
Microsoft 365 account, you can sign up for the Microsoft 365 Developer Program
to get a free Microsoft 365 subscription.
The Microsoft Authentication Library for .NET.
The EWS Managed API .

There are two types of OAuth permissions that can be used to access EWS APIs in
Exchange Online. Before you proceed with the tutorial, you will need to choose the
specific permission type to use.

Delegated permissions are used by apps that have a signed-in user present. For
these apps, either the user or an administrator consents to the permissions that
the app requests and the app can act as the signed-in user when making API calls.
Application permissions are used by apps that run without a signed-in user
present; for example, apps that run as background services or daemons and can
access multiple mailboxes.
Register your application
To use OAuth, an application must have an application ID issued by Azure Active
Directory. In this tutorial, it is assumed that the application is a console application, so
you need to register your application as a public client with Azure Active Directory. You
can register an application in the Azure Active Directory admin center or by using
Microsoft Graph.

1. Open a browser and navigate to the Azure Active Directory admin center and
login using a personal account (aka: Microsoft Account) or Work or School
Account.

2. Select Azure Active Directory in the left-hand navigation, then select App
registrations under Manage.

3. Select New registration. On the Register an application page, set the values as
follows.

Set Name to a friendly name for your app.


Set Supported account types to the choice that makes sense for your
scenario.
For Redirect URI, change the dropdown to Public client (mobile & desktop)
and set the value to
https://login.microsoftonline.com/common/oauth2/nativeclient .

4. Choose Register. On the next page, copy the values of the Application (client) ID
and Directory (tenant) ID and save them, you will need them later.

Configure for delegated authentication


If your application uses delegated authentication, no further configuration is required.
The Microsoft identity platform allows apps to request permissions dynamically, so you
do not have to pre-configure permissions on the app registration. However, in some
scenarios (like the on-behalf-of flow) pre-configuring permissions is required. Use the
following steps to pre-configure EWS permissions.

1. Select Manifest in the left-hand navigation under Manage.

2. Locate the requiredResourceAccess property in the manifest, and add the following
inside the square brackets ( [] ):

JSON
{

"resourceAppId": "00000002-0000-0ff1-ce00-000000000000",

"resourceAccess": [

"id": "3b5f3d61-589b-4a3c-a359-5dd4b5ee5bd5",

"type": "Scope"

3. Select Save.

4. Select API permissions under Manage. Confirm that the EWS.AccessAsUser.All


permission is listed.

Configure for app-only authentication


To use application permissions, follow these additional steps.

1. Select Manifest in the left-hand navigation under Manage.

2. Locate the requiredResourceAccess property in the manifest, and add the following
inside the square brackets ( [] ):

JSON

"resourceAppId": "00000002-0000-0ff1-ce00-000000000000",

"resourceAccess": [

"id": "dc890d15-9560-4a4c-9b7f-a736ec74ec40",

"type": "Role"

3. Select Save.

4. Select API permissions under Manage. Confirm that the full_access_as_app


permission is listed.

5. Select Grant admin consent for org and accept the consent dialog.

6. Select Certificates & Secrets in the left-hand navigation under Manage.

7. Select New client secret, enter a short description and select Add.
8. Copy the Value of the newly added client secret and save it, you will need it later.

Add code to get an authentication token


The following code snippets show how to use the Microsoft Authentication Library to
get authentication tokens for delegated permissions and application permissions. These
snippets assume that the information required to make the authentication request is
stored in the application's App.config file. These examples do not include error
checking, see the Code samples for the complete code.

Get a token with delegated auth


C#

// Using Microsoft.Identity.Client 4.22.0

// Configure the MSAL client to get tokens

var pcaOptions = new PublicClientApplicationOptions

ClientId = ConfigurationManager.AppSettings["appId"],

TenantId = ConfigurationManager.AppSettings["tenantId"]

};

var pca = PublicClientApplicationBuilder

.CreateWithApplicationOptions(pcaOptions).Build();

// The permission scope required for EWS access

var ewsScopes = new string[] {


"https://outlook.office365.com/EWS.AccessAsUser.All" };

// Make the interactive token request

var authResult = await


pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();

Get a token with app-only auth


C#

// Using Microsoft.Identity.Client 4.22.0

var cca = ConfidentialClientApplicationBuilder

.Create(ConfigurationManager.AppSettings["appId"])

.WithClientSecret(ConfigurationManager.AppSettings["clientSecret"])

.WithTenantId(ConfigurationManager.AppSettings["tenantId"])

.Build();

// The permission scope required for EWS access

var ewsScopes = new string[] { "https://outlook.office365.com/.default" };

//Make the token request

var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync();

Add an authentication token to EWS requests


After you've received the AuthenticationResult object you can use the AccessToken
property to get the token issued by the token service.

C#

// Configure the ExchangeService with the access token

var ewsClient = new ExchangeService();

ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");

ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);

To use application permissions, you will also need to explicitly impersonate a mailbox
that you would like to access.

C#

//Impersonate the mailbox you'd like to access.

ewsClient.ImpersonatedUserId = new
ImpersonatedUserId(ConnectingIdType.SmtpAddress,
"[email protected]");

Code samples

Delegated authentication
The following is the complete code sample that demonstrates making an OAuth-
authenticated EWS request using delegated authentication.

C#

using Microsoft.Exchange.WebServices.Data;

using Microsoft.Identity.Client;

using System;

using System.Configuration;

namespace EwsOAuth

class Program

static async System.Threading.Tasks.Task Main(string[] args)

// Using Microsoft.Identity.Client 4.22.0

// Configure the MSAL client to get tokens

var pcaOptions = new PublicClientApplicationOptions

ClientId = ConfigurationManager.AppSettings["appId"],

TenantId = ConfigurationManager.AppSettings["tenantId"]

};

var pca = PublicClientApplicationBuilder

.CreateWithApplicationOptions(pcaOptions).Build();

// The permission scope required for EWS access

var ewsScopes = new string[] {


"https://outlook.office365.com/EWS.AccessAsUser.All" };

try

// Make the interactive token request

var authResult = await


pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();

// Configure the ExchangeService with the access token

var ewsClient = new ExchangeService();

ewsClient.Url = new
Uri("https://outlook.office365.com/EWS/Exchange.asmx");

ewsClient.Credentials = new
OAuthCredentials(authResult.AccessToken);

// Make an EWS call

var folders =
ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new
FolderView(10));

foreach(var folder in folders)

Console.WriteLine($"Folder: {folder.DisplayName}");

catch (MsalException ex)

Console.WriteLine($"Error acquiring access token: {ex}");

catch (Exception ex)

Console.WriteLine($"Error: {ex}");

if (System.Diagnostics.Debugger.IsAttached)

Console.WriteLine("Hit any key to exit...");

Console.ReadKey();

App-only authentication
The following is the complete code sample that demonstrates making an OAuth-
authenticated EWS request using app-only authentication.

7 Note

When using impersonation you must always use the X-AnchorMailbox request
header, which should be set to the SMTP address of the impersonated mailbox.

C#

using Microsoft.Exchange.WebServices.Data;

using Microsoft.Identity.Client;

using System;

using System.Configuration;

namespace EwsOAuth

class Program

static async System.Threading.Tasks.Task Main(string[] args)

// Using Microsoft.Identity.Client 4.22.0

var cca = ConfidentialClientApplicationBuilder

.Create(ConfigurationManager.AppSettings["appId"])

.WithClientSecret(ConfigurationManager.AppSettings["clientSecret"])

.WithTenantId(ConfigurationManager.AppSettings["tenantId"])

.Build();

var ewsScopes = new string[] {


"https://outlook.office365.com/.default" };

try

var authResult = await cca.AcquireTokenForClient(ewsScopes)

.ExecuteAsync();

// Configure the ExchangeService with the access token

var ewsClient = new ExchangeService();

ewsClient.Url = new
Uri("https://outlook.office365.com/EWS/Exchange.asmx");

ewsClient.Credentials = new
OAuthCredentials(authResult.AccessToken);

ewsClient.ImpersonatedUserId =

new ImpersonatedUserId(ConnectingIdType.SmtpAddress,
"[email protected]");

//Include x-anchormailbox header

ewsClient.HttpHeaders.Add("X-AnchorMailbox",
"[email protected]");

// Make an EWS call

var folders =
ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new
FolderView(10));

foreach(var folder in folders)

Console.WriteLine($"Folder: {folder.DisplayName}");

catch (MsalException ex)

Console.WriteLine($"Error acquiring access token: {ex}");

catch (Exception ex)

Console.WriteLine($"Error: {ex}");

if (System.Diagnostics.Debugger.IsAttached)

Console.WriteLine("Hit any key to exit...");

Console.ReadKey();

The sample code in both cases requires an App.config file with the following entries:

XML

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<startup>

<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />

</startup>

<appSettings>

<!-- The application ID from your app registration -->

<add key="appId" value="YOUR_APP_ID_HERE" />

<!-- The tenant ID copied from your app registration -->

<add key="tenantId" value="YOUR_TENANT_ID_HERE"/>

<!-- The application's client secret from your app registration. Needed
for application permission access -->

<add key="clientSecret" value="YOUR_CLIENT_SECRET_HERE"/>

</appSettings>

</configuration>

See also
Authentication and EWS in Exchange
What to do with EWS Managed API PowerShell scripts that use Basic
Authentication
Autodiscover for Exchange
Article • 09/14/2022 • 5 minutes to read

Learn about the Autodiscover service in Exchange.

The Exchange Autodiscover service provides an easy way for your client application to
configure itself with minimal user input. Most users know their email address and
password, and with those two pieces of information, you can retrieve all the other
details you need to get up and running. For Exchange Web Services (EWS) clients,
Autodiscover is typically used to find the EWS endpoint URL, but Autodiscover can also
provide information to configure clients that use other protocols. Autodiscover works
for client applications that are inside or outside firewalls and will work in resource forest
and multiple forest scenarios.

Overview of the Autodiscover process


The Autodiscover process essentially has three phases. In phase one, you generate a list
of potential Autodiscover servers, and in phase two, you try each server in your list until
you (hopefully) get a successful response. If none of your candidates worked out, you
move on to phase three, which represents a "last ditch" attempt to find an Autodiscover
endpoint.

The ExchangeService.AutodiscoverUrl method in the EWS Managed API implements


all three phases of this process for you, so if you are using the EWS Managed API, you
don't need to worry about implementing Autodiscover yourself. The following figure
shows the three phases of the Autodiscover process.

Figure 1. Three phases of the Autodiscover process


Phase 1: Defining the candidate pool
Before you can use Autodiscover, you have to locate the right Autodiscover server for
your user. Luckily, Autodiscover defines a limited number of places for you to look. In
the case where multiple candidates are found, Autodiscover also defines a way to
generate and prioritize the list.

Table 1: Autodiscover endpoint candidate sources

Place to What you'll find


look

Active For domain-joined clients, this is the first place to look. Exchange publishes service
Directory connection point (SCP) objects in AD DS, which allows Autodiscover requests to be
Domain routed to servers based on Active Directory sites. The results of an SCP lookup
Services should be at the top of your candidate list.
(AD DS)
NOTE: SCP lookup isn't available for clients that are not joined to a domain or that
do not have access to Active Directory servers. In this case, you should skip SCP
lookup.

Place to What you'll find


look

The user's Autodiscover defines two standard endpoint URL forms that are derived from the
email domain portion of the user's email address:
address "https://" + domain + "/autodiscover/autodiscover" + *fileExtension*
domain "https://autodiscover." + domain + "/autodiscover/autodiscover" +
*fileExtension*

The value of fileExtension depends on which Autodiscover access method you are
using, SOAP or POX . The SOAP service uses a ".svc" file extension; POX uses
".xml".

The following figure shows how to generate an Autodiscover endpoint list.

Figure 2. Process for generating an Autodiscover endpoint list

Phase 2: Trying each candidate


After you generate an ordered list of potential candidates, the next step is try each one
in the list by sending a request to the URL and validating the results, as shown in Figure
3. When you get a successful response, you're done!

Figure 3. Trying each endpoint candidate in order


Before you send a request to a candidate, make sure it is trustworthy. Remember that
you're sending the user's credentials, so it's important to make sure that you're only
sharing them with a server you can trust. At a minimum, you should verify:

That the endpoint is an HTTPS endpoint. Client applications should not


authenticate or send data to a non-SSL endpoint.

That the SSL certificate presented by the server is valid and from a trusted
authority.

7 Note

These are just basic security suggestions. Whenever you are working with
authentication, make sure that your code meets the security requirements of your
organization.

The type of request you send depends on how you are accessing the Autodiscover
service.

Table 2. Types of Autodiscover requests

If you are using… Send a request by using…

The EWS Managed API The GetUserSettings method.

The SOAP Autodiscover service The GetUserSettings operation.


If you are using… Send a request by using…

The POX Autodiscover service An HTTP POST with an Autodiscover request body .

Phase 3: Trying other alternatives


In some cases you might try all the endpoints in your list, only to find that all of them
return an error. Before throwing in the towel, you can try a couple more things: you can
send an unauthenticated GET request, or query DNS for an SRV record. If these attempts
also don't yield results, you cannot contact the Autodiscover service.

Figure 4. Trying other alternatives

Sending an unauthenticated GET request

The first thing to try is to send an unauthenticated GET request to an endpoint derived
from the user's email address. The format of that endpoint is "http://autodiscover." +
domain + "/autodiscover/autodiscover.xml". Note that this is NOT an SSL endpoint. If
the server returns a 302 redirect response, you can then attempt to resend the
Autodiscover request to the endpoint URL in the Location header of the response.

Querying DNS for an SRV record


If the unauthenticated GET request doesn't work out, the last thing to try is a DNS query
for SRV records for the Autodiscover service. The record will take the form
"_autodiscover._tcp." + domain. This query might return multiple records, but you
should only use records that point to an SSL endpoint and that have the highest priority
and weight.

Options for using Autodiscover


You can access Autodiscover either by using the SOAP or the POX web service. The
method you use depends on your requirements and environment; however, we
recommend using the SOAP web service, if possible. The EWS Managed API is also an
option. It implements the client portion of both the SOAP and POX Autodiscover
services.

Table 3: Options for accessing Autodiscover

Option Pros Cons

EWS Managed Implements Limited to the user settings that are available in the
API
the Microsoft.Exchange.WebServices.Autodiscover.UserSettingName
Autodiscover enumeration.

process for
you.
Only available for .NET Framework applications.

Uses both
the SOAP
and POX
Autodiscover
services.

Works with
Exchange
Online,
Exchange
Online as
part of Office
365, or a
version of
Exchange
starting with
Exchange
2007 SP1.

Easy to use.

SOAP Platform Not available in Exchange 2007.


Autodiscover independent.

Allows you
to request
just the
settings you
are
interested in.
Option Pros Cons

POX Platform Does not allow you to request specific settings.


Autodiscover independent.

Supported in
Exchange
Online and
all versions
of Exchange
starting with
Exchange
2007 SP1.

In this section
Find Autodiscover endpoints by using SCP lookup in Exchange

Generate a list of Autodiscover endpoints

Use Autodiscover to find connection points

Get user settings from Exchange by using Autodiscover

Get domain settings from an Exchange server

Refresh configuration information by using Autodiscover

Handling Autodiscover error messages

Improving performance when using Autodiscover for Exchange

See also
Start using web services in Exchange
Develop web service clients for Exchange
Find Autodiscover endpoints by using
SCP lookup in Exchange
Article • 11/18/2020 • 8 minutes to read

Find out how to locate Autodiscover SCP objects in Active Directory Domain Services
(AD DS) and use them to find Autodiscover endpoint URLs to use with the Exchange
Autodiscover service.

Autodiscover makes it easy to retrieve information that you need to connect to


mailboxes on Exchange servers. However, in order to use Autodiscover, you need a way
to find Autodiscover servers that are appropriate for the user you're retrieving settings
for. Service connection point (SCP) objects in AD DS provide an easy way for domain-
joined clients to look up Autodiscover servers.

Get set up to find Autodiscover endpoints


To locate Autodiscover SCP objects in AD DS, you need to have access to the following:

A server that is running a version of Exchange on-premises starting with Exchange


2007 SP1.

A client computer that is joined to the domain that the Exchange server is installed
in.

A user account that has a mailbox on the Exchange server.

Also, before you begin, you'll want to be familiar some basic concepts. The following are
some resources that you'll find helpful.

Table 1. Related articles for finding Autodiscover endpoints from SCP objects

Read this article To learn about…

Autodiscover for Exchange


How the Autodiscover service works.

Publishing with Service Connection How SCP objects are used to publish service-specific
Points
data.

Locate Autodiscover SCP objects in AD DS


The first step toward finding Autodiscover endpoints published in AD DS is to locate the
Autodiscover SCP objects. Exchange publishes two types of SCP objects for
Autodiscover:

SCP pointers — These contain information that points to specific LDAP servers that
should be used to locate Autodiscover SCP objects for the user's domain. SCP
pointers are stamped with the following GUID: 67661d7F-8FC4-4fa7-BFAC-
E1D7794C1F68.

SCP URLs — These contain URLs for Autodiscover endpoints. SCP URLs are
stamped with the following GUID: 77378F46-2C66-4aa9-A6A6-3E7A48B19596.

To locate Autodiscover SCP objects


1. Read the configurationNamingContext property of the root DSE entry in AD DS to
get the path to the configuration naming context for the domain. You can do this
by using the DirectoryEntry class, or any other API that can acces AD DS.

2. Search for SCP objects in the configuration naming context that have either the
SCP pointer GUID or the SCP URL GUID in the keywords property.

3. Check the SCP objects you found for an SCP pointer that is scoped to the user's
domain by checking the keywords property for an entry equal to "Domain=
<domain>" . For example, if the user's email address is [email protected], you

would look for an SCP pointer with an entry in the keywords property that is equal
to "Domain=contoso.com" . If a matching SCP pointer is found, discard the set of SCP
objects and start over at step 1 using the value of the serviceBindingInformation
property as the server to connect to for the Root DSE entry.

4. If you don't find any SCP pointers scoped to the user's domain, check for any SCP
pointers that aren't scoped to any domain, and save the value of the
serviceBindingInformation property as a "fallback" server, in case the current
server doesn't give you any results.

5. If you didn't find any SCP pointers scoped to the domain, you're ready to move on
to the next step: generating a prioritized list of Autodiscover endpoints from your
results.

Generate a prioritized list of Autodiscover


endpoints
You can generate a prioritized list of Autodiscover endpoint URLs, using the set of SCP
objects that you located, by doing the following:

1. Get the Active Directory site name of the client computer.

2. Check the keywords property on each SCP URL in the set of SCP objects you
found, and assign a priority to the URL based on the following rules:

If the keywords property contains a value of "Site=<site name>" , where <site


name> equals the name of the Active Directory site you retrieved in the previous
step, assign the URL a priority of 1.

If the keywords property does not contain an entry with a value that starts with
"Site=" , assign the URL a priority of 2.

If the keywords property contains a value of "Site=<site name> , where <site


name> does not equal the name of the Active Directory site you retrieved in the
previous step, assign the URL a priority of 3.

Code example: Performing an SCP lookup


In the following code example, you'll see how to locate Autodiscover SCP objects and
generate a prioritized list of Autodiscover endpoints.

C#

using System;

using System.Collections.Generic;
using System.DirectoryServices;

using System.DirectoryServices.ActiveDirectory;

namespace ScpLookup

// This sample is for demonstration purposes only. Before you run this
sample, make sure

// that the code meets the coding requirements of your organization.

class Program

static void Main(string[] args)

string domain = args[0];

Console.WriteLine("Performing SCP lookup for {0}.", domain);

List<string> scpUrls = GetScpUrls(null, domain);

Console.WriteLine("\nOrdered List of Autodiscover endpoints:");

foreach (string url in scpUrls)

Console.WriteLine(" {0}", url);

Console.WriteLine("SCP lookup done.");

// GUID for SCP URL keyword.

private const string ScpUrlGuidString = @"77378F46-2C66-4aa9-A6A6-


3E7A48B19596";

// GUID for SCP pointer keyword.

private const string ScpPtrGuidString = @"67661d7F-8FC4-4fa7-BFAC-


E1D7794C1F68";

static List<string> GetScpUrls(string ldapServer, string domain)

// Create a new list to return.

List<string> scpUrlList = new List<string>();

string rootDSEPath = null;

// If ldapServer is null/empty, use LDAP://RootDSE to

// connect to Active Directory Domain Services (AD DS).


Otherwise, use

// LDAP://SERVERNAME/RootDSE to connect to a specific server.

if (string.IsNullOrEmpty(ldapServer))

rootDSEPath = "LDAP://RootDSE";

else

rootDSEPath = ldapServer + "/RootDSE";

SearchResultCollection scpEntries = null;

try

// Get the root directory entry.

DirectoryEntry rootDSE = new DirectoryEntry(rootDSEPath);

// Get the configuration path.

string configPath =
rootDSE.Properties["configurationNamingContext"].Value as string;

// Get the configuration entry.

DirectoryEntry configEntry = new DirectoryEntry("LDAP://" +


configPath);

// Create a search object for the configuration entry.

DirectorySearcher configSearch = new


DirectorySearcher(configEntry);

// Set the search filter to find SCP URLs and SCP pointers.

configSearch.Filter = "(&amp;
(objectClass=serviceConnectionPoint)" +

"(|(keywords=" + ScpPtrGuidString + ")(keywords=" +


ScpUrlGuidString + ")))";

// Specify which properties you want to retrieve.

configSearch.PropertiesToLoad.Add("keywords");

configSearch.PropertiesToLoad.Add("serviceBindingInformation");

scpEntries = configSearch.FindAll();

catch (Exception ex)

Console.WriteLine("SCP lookup failed with: ");

Console.WriteLine(ex.ToString());

// If no SCP entries were found, then exit.

if (scpEntries == null || scpEntries.Count <= 0)

Console.WriteLine("No SCP records found.");

return null;

string fallBackLdapPath = null;

// Check for SCP pointers.

foreach (SearchResult scpEntry in scpEntries)

ResultPropertyValueCollection entryKeywords =
scpEntry.Properties["keywords"];

if (CollectionContainsExactValue(entryKeywords,
ScpPtrGuidString))

string ptrLdapPath =
scpEntry.Properties["serviceBindingInformation"][0] as string;

// Determine whether this pointer is scoped to the


user's domain.

if (CollectionContainsExactValue(entryKeywords,
"Domain=" + domain))

Console.WriteLine("Found SCP pointer for " + domain


+ " in " + scpEntry.Path);

// Restart SCP lookup with the server assigned for


the domain.

Console.WriteLine("Restarting SCP lookup in " +


ptrLdapPath);

return GetScpUrls(ptrLdapPath, domain);

else

// Save the first SCP pointer that is not scoped to


a domain as a fallback

// in case you do not get any results from this


server.

if (entryKeywords.Count == 1 &&
string.IsNullOrEmpty(fallBackLdapPath))

fallBackLdapPath = ptrLdapPath;

Console.WriteLine("Saved fallback SCP pointer: "


+ fallBackLdapPath);

string computerSiteName = null;

try

// Get the name of the ActiveDirectorySite the computer

// belongs to (if it belongs to one).

ActiveDirectorySite site =
ActiveDirectorySite.GetComputerSite();

computerSiteName = site.Name;

Console.WriteLine("Local computer in site: " +


computerSiteName);

catch (Exception ex)

Console.WriteLine("Unable to get computer site name.");

Console.WriteLine(ex.ToString());

if (!string.IsNullOrEmpty(computerSiteName))
{

// Scan the search results for SCP URLs.

// SCP URLs fit into three tiers:

// Priority 1: The URL is scoped to the computer's Active


Directory site.

// Priority 2: The URL is not scoped to any Active


Directory site.

// Priority 3: The URL is scoped to a different Active


Directory site.

// Temporary lists to hold priority 2 and 3 URLs.

List<string> priorityTwoUrls = new List<string>();

List<string> priorityThreeUrls = new List<string>();

foreach (SearchResult scpEntry in scpEntries)

ResultPropertyValueCollection entryKeywords =
scpEntry.Properties["keywords"];

// Check for SCP URLs.

if (CollectionContainsExactValue(entryKeywords,
ScpUrlGuidString))

string scpUrlPath = scpEntry.Properties["adsPath"]


[0] as string;

Console.WriteLine("SCP URL found at {0}",


scpUrlPath);

string scpUrl =
scpEntry.Properties["serviceBindingInformation"][0] as string;

scpUrl = scpUrl.ToLower();

// Determine whether this entry is scoped to the


computer's site.

if (CollectionContainsExactValue(entryKeywords,
"Site=" + computerSiteName))

// Priority 1.

if (!scpUrlList.Contains(scpUrl.ToLower()))

Console.WriteLine("Adding priority 1 SCP


URL: {0}", scpUrl.ToLower());

scpUrlList.Add(scpUrl);

else

Console.WriteLine("Priority 1 SCP URL


already found: {0}", scpUrl);

else

// Determine whether this is a priority 2 or 3


URL.

if (CollectionContainsPrefixValue(entryKeywords,
"Site="))

// Priority 3.

if (!priorityThreeUrls.Contains(scpUrl))

{
Console.WriteLine("Adding priority 3 SCP
URL: {0}", scpUrl);

priorityThreeUrls.Add(scpUrl);

}
else

{
Console.WriteLine("Priority 3 SCP URL
already found: {0}", scpUrl);

}
}

else

// Priority 2.

if (!priorityTwoUrls.Contains(scpUrl))

{
Console.WriteLine("Adding priority 2 SCP
URL: {0}", scpUrl);

priorityTwoUrls.Add(scpUrl);

}
else

{
Console.WriteLine("Priority 2 SCP URL
already found: {0}", scpUrl);

}
}

// Now add the priority 2 URLs into the main list.

foreach (string priorityTwoUrl in priorityTwoUrls)

// If the URL is already in the list as a priority 1,

// don't add it again.

if (!scpUrlList.Contains(priorityTwoUrl))

scpUrlList.Add(priorityTwoUrl);

// Now add the priority 3 URLs into the main list.

foreach (string priorityThreeUrl in priorityThreeUrls)

// If the URL is already in the list as a priority 1

// or priority 2, don't add it again.

if (!scpUrlList.Contains(priorityThreeUrl))

scpUrlList.Add(priorityThreeUrl);

// If after all this, you still have no URLs in your list,

// try the fallback SCP pointer, if you have one.

if (scpUrlList.Count == 0 && fallBackLdapPath != null)

return GetScpUrls(fallBackLdapPath, domain);

return scpUrlList;

private static bool


CollectionContainsExactValue(ResultPropertyValueCollection collection,
string value)

foreach (object obj in collection)

string entry = obj as string;

if (entry != null)

if (string.Compare(value, entry, true) == 0)

return true;

return false;

private static bool


CollectionContainsPrefixValue(ResultPropertyValueCollection collection,
string value)

foreach (object obj in collection)

string entry = obj as string;

if (entry != null)

if (entry.StartsWith(value))

return true;

return false;

Next steps
The next step in the Autodiscover process is to send Autodiscover requests to the URLs
that you found, starting with priority 1 URLs, then priority 2 URLs, and finally priority 3
URLs. To learn more about how to send Autodiscover requests and handle responses,
read the following articles:

Get user settings from Exchange by using Autodiscover


Handling Autodiscover error messages

See also
Autodiscover for Exchange
Setting up your EWS application
Generate a list of Autodiscover
endpoints
Article • 01/15/2020 • 3 minutes to read

Find out how to generate a prioritized list of Autodiscover endpoints.

The first task in the Autodiscover process is to generate a list of Autodiscover endpoints
for your application to try. These Autodiscover endpoints can come from an SCP lookup
or can be derived from the user's email address. In the end, you can end up with a large
number of endpoints. Let's take a look at how you can organize them by priority.

Start with SCP lookup


Autodiscover endpoints that come from an SCP lookup should have top priority in your
list. Administrators can configure SCP objects to route your client to the closest or most
efficient Autodiscover endpoint, so it is a good idea to start with these endpoints.
Because the SCP lookup process has its own prioritization scheme, the results of an SCP
lookup are already prioritized, as follows:

1. Autodiscover endpoints from SCP objects scoped to the Active Directory site that
the client computer belongs to.

2. Autodiscover endpoints from SCP objects not scoped to any Active Directory site.

3. Autodiscover endpoints from SCP objects scoped to a different Active Directory


site than the site that the client computer belongs to.

After you have the results of the SCP lookup process, you can add endpoints that derive
from the user's email address. These can serve as a default set of endpoints and a
fallback in case there are no SCP results or the endpoints returned from the SCP lookup
are not sufficient.

Add endpoints derived from the user's email


address
When SCP lookup doesn't work, or the endpoints returned by the SCP lookup don't
return a successful response, you can derive a set of default Autodiscover endpoints
from the user's email address. These endpoints should be a lower priority than any that
come from an SCP lookup, but you might need them if the SCP lookup was not
successful.
To derive Autodiscover endpoints
1. Extract the domain name from the user's email address. For example, if the user's
email address is [email protected], the domain name would be
contoso.com.

2. Construct endpoint URLs without file extensions in the following formats:

"https://" + domain + "/autodiscover/autodiscover"

"https://autodiscover." + domain + "/autodiscover/autodiscover"

After you compile the list of endpoint URLs that derive from both SCP lookup and the
user's email address, you might need to revise file name extensions in those URLs,
depending on whether you're using the SOAP Autodiscover web service or the POX
Autodiscover web service .

Add or replace file name extensions in


endpoint URLs
You can access the Autodiscover service by using either the SOAP Autodiscover web
service or the POX Autodiscover web service. Each service uses similar endpoint URLs,
with the only difference being the file name extension. The SOAP Autodiscover web
service uses the ".svc" file name extension, and the POX Autodiscover web service uses
the ".xml" file name extension.

By default, the Autodiscover endpoint URLs returned from an SCP lookup are POX URLs.
However, if you are using SOAP Autodiscover, you can simply change the file name
extension from ".xml" to ".svc" and try a SOAP request.

For the derived Autodiscover endpoint URLs, the file extension is omitted. Add the
appropriate file extension for the Autodiscover web service you are using prior to trying
the URL.

Example: Generating a list of Autodiscover


endpoints
Let's take a look at an example. Sadie Daniels ([email protected]) is using an
Exchange Web Services (EWS) application for the first time. The application uses
Autodiscover to configure itself. Sadie's computer is joined to the contoso.com domain
and is in the Redmond Active Directory site. The application generates the list of
Autodiscover endpoints shown in Figure 1.

Figure 1: Sample list of Autodiscover endpoints

The EWS application in this example prefers the SOAP Autodiscover web service, so it
changes the file name extension for the SCP results to ".svc" before sending SOAP
requests to them.

Next steps
After you generate a list of Autodiscover endpoints, try them by sending requests to
those endpoints.

See also
Autodiscover for Exchange

Find Autodiscover endpoints by using SCP lookup in Exchange

Handling Autodiscover error messages


Use Autodiscover to find connection
points
Article • 01/15/2020 • 6 minutes to read

Find out how to use the Autodiscover service to direct your client application to the
correct Exchange server.

The Exchange Autodiscover service provides your client application with configuration
settings for email accounts that are hosted on Exchange Online, Exchange Online as part
of Office 365, or an Exchange server running a version of Exchange starting with
Exchange 2013. The Autodiscover service is a web service that provides configuration
settings. The Autodiscover service is a web service that provides Exchange server
configuration information to your client application. Client applications use
Autodiscover to determine the endpoint of the Autodiscover service for a specific
mailbox. This article explains how to follow the responses from an Exchange server to
find the correct endpoint.

For information about how to get email address configuration settings, see Get user
settings from Exchange by using Autodiscover and Get domain settings from an
Exchange server.

7 Note

The process for finding the correct endpoint is part of the request for user or
domain settings. The Autodiscover service uses a series of redirect responses to
send the client application to the correct endpoint for an email address.

You can use one of the following Exchange development technologies to access the
Autodiscover service:

The Exchange Web Services (EWS) Managed API

EWS

If you are using EWS, you can use the following methods to retrieve user settings:

The SOAP-based Autodiscover service

The XML (POX) Autodiscover service

An autogenerated proxy generated from the SOAP or XML Autodiscover service


For more information about these methods, see Autodiscover for Exchange.

For more information about these Exchange development technologies, see Explore the
EWS Managed API, EWS, and web services in Exchange.

The EWS Managed API provides an object-based interface for retrieving user settings. If
your client application uses managed code, we recommend that you use the EWS
Managed API. The EWS Managed API interface is better optimized for a simple object
model than the typical autogenerated web service proxy.

If you are using EWS, we suggest that you use the SOAP Autodiscover service, because it
supports a richer set of features than the POX Autodiscover service.

Prerequisites for finding an endpoint


Before you can create a client application that uses the Autodiscover service, you need
to have access to the following:

Exchange Online or a server that is running a version of Exchange starting with


Exchange 2007 SP1. If you are using the SOAP-based Autodiscover service,
Exchange Online or a version of Exchange starting with Exchange 2010.

An Exchange server that is configured to accept connections from your client


application. For information about how to configure your Exchange server, see
Controlling client application access to EWS in Exchange.

An account that is authorized to use EWS. For information about how to configure
an account, see Controlling client application access to EWS in Exchange.

7 Note

If you are using the EWS Managed API, you must provide a certificate validation
callback in some circumstances. You may also need a certificate validation callback
with some generated proxy libraries, such as those created by Visual Studio. For
more information, see Validate a server certificate for the EWS Managed API.

Core concepts for finding an endpoint


Before you use Autodiscover to find an endpoint, you should be familiar with the
concepts listed in the following table.

Concept Description
Concept Description

Autodiscover for Exchange


Provides an overview of how the Autodiscover service works.

If you are using the EWS Managed API, you use the
Microsoft.Exchange.WebServices.Data.ExchangeService class in the
Microsoft.Exchange.WebServices.Data namespace to manage your connection to EWS.
To use the EWS Managed API code samples in this article, you need to reference the
following namespaces in your code:

System.Net

Microsoft.Exchange.WebServices.Data.ExchangeService

Find the correct endpoint by using the EWS


Managed API
If you are using the EWS Managed API, calls to the Autodiscover service are handled by
the ExchangeService class. To determine the correct endpoint for an email account, you
call the AutodiscoverUrl method on an [ExchangeService] object. The following code
example shows how to set the EWS web service endpoint for an email address to the
Exchange.asmx file on the correct Client Access server by using the EWS Managed API.

C#

NetworkCredential credentials = new NetworkCredential(securelyStoredEmail,


securelyStoredPassword);

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);

service.Credentials = credentials;

service.AutodiscoverUrl("[email protected]");

Find the correct endpoint by using EWS


The SOAP Autodiscover service may use a series of requests and responses to direct
your application to the correct endpoint for EWS. For information about the process for
determining the correct endpoint for an email account, see Autodiscover for Exchange.
The following XML examples show the series of requests and responses that you can
expect when making a SOAP Autodiscover request to find the correct endpoint.

SOAP Autodiscover endpoint request


The following example shows an XML request that is sent to the Autodiscover service to
find the correct endpoint.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope
xmlns:a="https://schemas.microsoft.com/exchange/2010/Autodiscover"

xmlns:wsa="http://www.w3.org/2005/08/addressing"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<a:RequestedServerVersion>Exchange2013</a:RequestedServerVersion>

<wsa:Action>https://schemas.microsoft.com/exchange/2010/Autodiscover/Autodis
cover/GetUserSettings</wsa:Action>

<wsa:To>https://mail.microsoft.com/autodiscover/autodiscover.svc</wsa:To>

</soap:Header>

<soap:Body>

<a:GetUserSettingsRequestMessage
xmlns:a="https://schemas.microsoft.com/exchange/2010/Autodiscover">

<a:Request>

<a:Users>

<a:User>

<a:Mailbox>[email protected]</a:Mailbox>

</a:User>

</a:Users>

<a:RequestedSettings>

<a:Setting>InternalEwsUrl</a:Setting>

<a:Setting>ExternalEwsUrl</a:Setting>

</a:RequestedSettings>

</a:Request>

</a:GetUserSettingsRequestMessage>

</soap:Body>

</soap:Envelope>

SOAP Autodiscover redirection response


The Autodiscover service may respond with one of two redirection responses: an HTTP
302 redirect, or a SOAP redirection response. If the response from the Exchange server is
an HTTP 302 redirect, the client application should validate that the redirection address
is acceptable and then follow the redirection response.

) Important

For criteria for validating a redirection response, see Autodiscover for Exchange.
If the Autodiscover service returns a redirection response, indicated by the ErrorCode
element of the UserResponse element, your client application should use the
RedirectTarget element to construct a new settings request that is sent to the server
specified in the redirection response. The following example shows a redirection
response from the server.

XML

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"
xmlns:a="http://www.w3.org/2005/08/addressing">

<s:Header>

<a:Action
s:mustUnderstand="1">https://schemas.microsoft.com/exchange/2010/

Autodiscover/Autodiscover/GetUserSettingsResponse</a:Action>

<h:ServerVersionInfo
xmlns:h="https://schemas.microsoft.com/exchange/2010/Autodiscover"

xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<h:MajorVersion>15</h:MajorVersion>

<h:MinorVersion>0</h:MinorVersion>

<h:MajorBuildNumber>682</h:MajorBuildNumber>

<h:MinorBuildNumber>1</h:MinorBuildNumber>

<h:Version>Exchange2013</h:Version>

</h:ServerVersionInfo>

</s:Header>

<s:Body>

<GetUserSettingsResponseMessage
xmlns="https://schemas.microsoft.com/exchange/2010/Autodiscover">

<Response xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<ErrorCode>NoError</ErrorCode>

<ErrorMessage />

<UserResponses>

<UserResponse>

<ErrorCode>RedirectAddress</ErrorCode>

<ErrorMessage>Redirection address.</ErrorMessage>

<RedirectTarget>[email protected]</RedirectTarget>

<UserSettingErrors />

<UserSettings />

</UserResponse>

</UserResponses>

</Response>

</GetUserSettingsResponseMessage>

</s:Body>

</s:Envelope>

After a redirection, the client uses the redirection URL to prepare another request. The
following code shows an example of the request that you create from the redirection
response.

XML
<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope
xmlns:a="https://schemas.microsoft.com/exchange/2010/Autodiscover"

xmlns:wsa="http://www.w3.org/2005/08/addressing"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<a:RequestedServerVersion>Exchange2013</a:RequestedServerVersion>

<wsa:Action>https://schemas.microsoft.com/exchange/2010/

Autodiscover/Autodiscover/GetUserSettings</wsa:Action>

<wsa:To>https://autodiscover.exchange.microsoft.com/autodiscover/autodiscove
r.svc</wsa:To>

</soap:Header>

<soap:Body>

<a:GetUserSettingsRequestMessage
xmlns:a="https://schemas.microsoft.com/exchange/2010/Autodiscover">

<a:Request>

<a:Users>

<a:User>

<a:Mailbox>[email protected]</a:Mailbox>

</a:User>

</a:Users>

<a:RequestedSettings>

<a:Setting>InternalEwsUrl</a:Setting>

<a:Setting>ExternalEwsUrl</a:Setting>

</a:RequestedSettings>

</a:Request>

</a:GetUserSettingsRequestMessage>

</soap:Body>

</soap:Envelope>

When the client application has been directed to the correct endpoint for the
Autodiscover service, the server will send a response with the ErrorCode element of
the UserResponse element set to NoError and containing the requested user settings.
Only the requested user settings, InternalEwsUrl and ExternalEwsUrl, are returned. The
following example shows the response from the server.

XML

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"

xmlns:a="http://www.w3.org/2005/08/addressing">

<s:Header>

<a:Action
s:mustUnderstand="1">https://schemas.microsoft.com/exchange/2010/

Autodiscover/Autodiscover/GetUserSettingsResponse</a:Action>

<h:ServerVersionInfo
xmlns:h="https://schemas.microsoft.com/exchange/2010/Autodiscover"

xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<h:MajorVersion>15</h:MajorVersion>

<h:MinorVersion>0</h:MinorVersion>

<h:MajorBuildNumber>160</h:MajorBuildNumber>

<h:MinorBuildNumber>4</h:MinorBuildNumber>

<h:Version>Exchange2013</h:Version>

</h:ServerVersionInfo>

</s:Header>

<s:Body>

<GetUserSettingsResponseMessage
xmlns="https://schemas.microsoft.com/exchange/2010/Autodiscover">

<Response xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<ErrorCode>NoError</ErrorCode>

<ErrorMessage />

<UserResponses>

<UserResponse>

<ErrorCode>NoError</ErrorCode>

<ErrorMessage>No error.</ErrorMessage>

<RedirectTarget i:nil="true" />

<UserSettingErrors />

<UserSettings>

<UserSetting i:type="StringSetting">

<Name>InternalEwsUrl</Name>

<Value>https://server.Contoso.com/ews/exchange.asmx</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>ExternalEwsUrl</Name>

<Value>https://server.Contoso.com/ews/exchange.asmx</Value>

</UserSetting>

</UserSettings>

</UserResponse>

</UserResponses>

</Response>

</GetUserSettingsResponseMessage>

</s:Body>

</s:Envelope>

Next steps
Finding the endpoint by following the Autodiscover process returns the requested
domain or user settings. For information about making a request for specific settings,
see the following articles:

Get domain settings from an Exchange server


Get user settings from Exchange by using Autodiscover

See also
Setting up your EWS application
Autodiscover for Exchange
Autodiscover web service reference for Exchange
EWS reference for Exchange
Get user settings from Exchange by
using Autodiscover
Article • 01/15/2020 • 5 minutes to read

Learn how to get user configuration settings from an Exchange server by using
Autodiscover.

Autodiscover simplifies application configuration by providing easy access to user


configuration information using only the user's email address and password. A number
of user configuration settings are available via Autodiscover, such as the user's display
name or external web service URL.

You can use one of the following development technologies to retrieve user settings
from the Autodiscover service:

The Get started with EWS Managed API client applications

The SOAP Autodiscover web service

The POX Autodiscover web service

The EWS Managed API provides an object-based interface for retrieving user settings. If
your client application uses managed code, we recommend that you use the EWS
Managed API. If you are using the EWS Managed API, determine whether the settings
that you need are available in the
Microsoft.Exchange.WebServices.Autodiscover.UserSettingName enumeration. If they
aren't, you might want to use the SOAP or POX Autodiscover services.

If you are using a web service, we suggest that you use the SOAP Autodiscover service,
because it supports a richer set of features than the POX Autodiscover service. If the
SOAP Autodiscover service isn't available, the POX Autodiscover service is a good
alternative.

Set up to get user settings


Before you get user settings by using the Autodiscover service, make sure that you have
access to the following:

If you are using the EWS Managed API or the POX-based Autodiscover service,
Exchange Online, Exchange Online as part of Office 365, or a server that is running
a version of Exchange starting with Exchange 2007 SP1.
If you are using the SOAP-based Autodiscover service, Exchange Online or a
version of Exchange starting with Exchange 2010.

7 Note

If you are using the EWS Managed API, you will need to provide a certificate
validation callback method in some circumstances. You might also need a
certificate validation callback method with some generated proxy libraries, such as
those created by Visual Studio.

Get user settings by using the EWS Managed


API
You can use the GetUserSettings method to retrieve configuration information for a
user, as shown in the following example. In this example, you can specify an array of
user settings to return (from those available in the UserSettingName enumeration),
and the method will follow redirection responses from the Exchange server.

C#

using System;

using System.Net;

using Microsoft.Exchange.WebServices.Autodiscover;

public static GetUserSettingsResponse GetUserSettings(

AutodiscoverService service,

string emailAddress,

int maxHops,

params UserSettingName[] settings)

Uri url = null;

GetUserSettingsResponse response = null;

for (int attempt = 0; attempt < maxHops; attempt++)

service.Url = url;

service.EnableScpLookup = (attempt < 2);

response = service.GetUserSettings(emailAddress, settings);

if (response.ErrorCode == AutodiscoverErrorCode.RedirectAddress)

url = new Uri(response.RedirectTarget);

else if (response.ErrorCode == AutodiscoverErrorCode.RedirectUrl)

url = new Uri(response.RedirectTarget);

else

return response;

throw new Exception("No suitable Autodiscover endpoint was found.");

You can parse the collection returned to access each key/value pair in the user settings
array. The following example shows how to parse through each returned element and
display the name and value of each key/value pair.

C#

// Display each retrieved value. The settings are part of a key/value pair.

// userresponse is a GetUserSettingsResonse object.

foreach (KeyValuePair<UserSettingName, Object> usersetting in


userresponse.Settings)

Console.WriteLine(usersetting.Key.ToString() + ": " +


usersetting.Value);

Alternatively, you can obtain the value of a specific setting. In the following example, the
UserDisplayName setting is to be displayed.

C#

// Display a specific setting, such as UserDisplayName.

Console.WriteLine(userresponse.Settings[UserSettingName.UserDisplayName]);

Get user settings by using SOAP Autodiscover


If you're not using the EWS Managed API, we recommend that you use the SOAP
Autodiscover web service. Only use the POX Autodiscover web service if the SOAP
Autodiscover web service fails or is not available.

To get user settings, use the GetUserSettings operation (SOAP) . The requested
settings are returned as UserSetting elements .

The following example shows a SOAP Autodiscover request to get user settings from the
server.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope
xmlns:a="https://schemas.microsoft.com/exchange/2010/Autodiscover"

xmlns:wsa="http://www.w3.org/2005/08/addressing"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<a:RequestedServerVersion>Exchange2013</a:RequestedServerVersion>

<wsa:Action>https://schemas.microsoft.com/exchange/2010/Autodiscover/Autodis
cover/GetUserSettings</wsa:Action>

<wsa:To>https://autodiscover.exchange.microsoft.com/autodiscover/autodiscove
r.svc</wsa:To>

</soap:Header>

<soap:Body>

<a:GetUserSettingsRequestMessage
xmlns:a="https://schemas.microsoft.com/exchange/2010/Autodiscover">

<a:Request>

<a:Users>

<a:User>

<a:Mailbox>[email protected]</a:Mailbox>

</a:User>

</a:Users>

<a:RequestedSettings>

<a:Setting>UserDisplayName</a:Setting>

<a:Setting>UserDN</a:Setting>

<a:Setting>UserDeploymentId</a:Setting>

<a:Setting>InternalMailboxServer</a:Setting>

<a:Setting>MailboxDN</a:Setting>

<a:Setting>PublicFolderServer</a:Setting>

<a:Setting>ActiveDirectoryServer</a:Setting>

<a:Setting>ExternalMailboxServer</a:Setting>

<a:Setting>EcpDeliveryReportUrlFragment</a:Setting>

<a:Setting>EcpPublishingUrlFragment</a:Setting>

<a:Setting>EcpTextMessagingUrlFragment</a:Setting>

<a:Setting>ExternalEwsUrl</a:Setting>

<a:Setting>CasVersion</a:Setting>

<a:Setting>EwsSupportedSchemas</a:Setting>

<a:Setting>GroupingInformation</a:Setting>

</a:RequestedSettings>

</a:Request>

</a:GetUserSettingsRequestMessage>

</soap:Body>

</soap:Envelope>

The following example shows the SOAP response that is returned by the server after it
parses the request from the client. The response contains only the settings that are
requested, if they exist.

XML

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"
xmlns:a="http://www.w3.org/2005/08/addressing">

<s:Header>

<a:Action
s:mustUnderstand="1">https://schemas.microsoft.com/exchange/2010/

Autodiscover/Autodiscover/GetUserSettingsResponse</a:Action>

<h:ServerVersionInfo
xmlns:h="https://schemas.microsoft.com/exchange/2010/Autodiscover"

xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<h:MajorVersion>15</h:MajorVersion>

<h:MinorVersion>0</h:MinorVersion>

<h:MajorBuildNumber>160</h:MajorBuildNumber>

<h:MinorBuildNumber>4</h:MinorBuildNumber>

<h:Version>Exchange2013</h:Version>

</h:ServerVersionInfo>

</s:Header>

<s:Body>

<GetUserSettingsResponseMessage
xmlns="https://schemas.microsoft.com/exchange/2010/Autodiscover">

<Response xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<ErrorCode>NoError</ErrorCode>

<ErrorMessage />

<UserResponses>

<UserResponse>

<ErrorCode>NoError</ErrorCode>

<ErrorMessage>No error.</ErrorMessage>

<RedirectTarget i:nil="true" />

<UserSettingErrors />

<UserSettings>

<UserSetting i:type="StringSetting">

<Name>UserDisplayName</Name>

<Value>Mara Whitley</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>UserDN</Name>

<Value>/o=microsoft/ou=Exchange Administrative Group


(FYDIBOHF23SPDLT)/cn=Recipients/cn=mara</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>UserDeploymentId</Name>

<Value>649d50b8-a1ce-4bac-8ace-2321 e463f701</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>CasVersion</Name>

<Value>15.01.0160.004</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>EwsSupportedSchemas</Name>

<Value>Exchange2007, Exchange2007_SP1, Exchange2010,


Exchange2010_SP1, Exchange2010_SP2, Exchange2013</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>InternalMailboxServer</Name>

<Value>mail.contoso.com</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>ActiveDirectoryServer</Name>

<Value>dc.contoso.com</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>MailboxDN</Name>

<Value>/o=microsoft/ou=Exchange Administrative Group

(FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=mail.contoso.com/cn=Contoso
Private MDB</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>PublicFolderServer</Name>

<Value>public.contoso.com</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>EcpDeliveryReportUrlFragment</Name>

<Value>PersonalSettings/DeliveryReport.aspx?
exsvurl=1&amp;amp;IsOWA=&amp;lt;IsOWA&amp;gt;&amp;amp;MsgID=&amp;lt;MsgID&am
p;gt;&amp;amp;Mbx=&amp;lt;Mbx&amp;gt;</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>EcpTextMessagingUrlFragment</Name>

<Value>?p=sms/textmessaging.slab&amp;amp;exsvurl=1</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>EcpPublishingUrlFragment</Name>

<Value>customize/calendarpublishing.slab?
exsvurl=1&amp;amp;FldID=&amp;lt;FldID&amp;gt;</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>ExternalEwsUrl</Name>

<Value>https://mail.contoso.com/EWS/Exchange.asmx</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>ExternalMailboxServer</Name>

<Value>mail.contoso.com</Value>

</UserSetting>

<UserSetting i:type="StringSetting">

<Name>GroupingInformation</Name>

<Value>CONTOSO-1</Value>

</UserSetting>

</UserSettings>

</UserResponse>

</UserResponses>

</Response>

</GetUserSettingsResponseMessage>

</s:Body>

</s:Envelope

Get user settings by using POX Autodiscover


Although we recommend that you use the SOAP Autodiscover web service, the POX
Autodiscover web service is a good backup option for those times when SOAP isn't
available. For example, Exchange 2007 does not support the SOAP Autodiscover web
service, so if you are targeting Exchange 2007, you have to use the POX Autodiscover
web service. Unlike the SOAP Autodiscover web service, the POX Autodiscover service
does not allow you to request specific settings. Instead, the server returns a full list of
available settings as child elements of the Protocol element .

The following example shows a POX Autodiscover request to get user settings from the
server. The following XML is sent to the server via an HTTP POST.

XML

<?xml version="1.0" encoding="utf-8"?>

<Autodiscover
xmlns="https://schemas.microsoft.com/exchange/autodiscover/outlook/requestsc
hema/2006">

<Request>

<EMailAddress>[email protected]</EMailAddress>

<AcceptableResponseSchema>https://schemas.microsoft.com/exchange/autodiscove
r/outlook/responseschema/2006a</AcceptableResponseSchema>

</Request>

</Autodiscover>

The following example shows the POX response that is returned by the server.

XML

<?xml version="1.0" encoding="utf-8"?>

<Autodiscover
xmlns="https://schemas.microsoft.com/exchange/autodiscover/responseschema/20
06">

<Response
xmlns="https://schemas.microsoft.com/exchange/autodiscover/outlook/responses
chema/2006a">

<User>

<DisplayName>Mara Whitley</DisplayName>

<LegacyDN>/o=First Organization/ou=Exchange Administrative Group


(FYDIBOHF23SPDLT)/cn=Recipients/cn=f5eeabead90d4b6fb51d6379474692cd-
Mara</LegacyDN>

<AutoDiscoverSMTPAddress>[email protected]</AutoDiscoverSMTPAddress>

<DeploymentId>50817eff-b925-4578-a0db-13bfc635e7a5</DeploymentId>

</User>

<Account>

<AccountType>email</AccountType>

<Action>settings</Action>

<MicrosoftOnline>False</MicrosoftOnline>

<Protocol>

<Type>EXCH</Type>

<Server>[email protected]</Server>

<ServerDN>/o=First Organization/ou=Exchange Administrative Group


(FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=5f76be3c-9138-4f66-85e0-
[email protected]</ServerDN>

<ServerVersion>73C08204</ServerVersion>

<MdbDN>/o=First Organization/ou=Exchange Administrative Group


(FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=5f76be3c-9138-4f66-85e0-
[email protected]/cn=Microsoft Private MDB</MdbDN>

<PublicFolderServer>public.contoso.com</PublicFolderServer>

<AD>dc.contoso.com</AD>

<ASUrl>https://mail.contoso.com/EWS/Exchange.asmx</ASUrl>

<EwsUrl>https://mail.contoso.com/EWS/Exchange.asmx</EwsUrl>

<EmwsUrl>https://mail.contoso.com/EWS/Exchange.asmx</EmwsUrl>

<EcpUrl>https://mail.contoso.com/ecp/</EcpUrl>

<EcpUrl-um>?
rfr=olk&amp;amp;p=customize/voicemail.aspx&amp;amp;exsvurl=1&amp;amp;realm=c
ontoso.com</EcpUrl-um>

<EcpUrl-aggr>?
rfr=olk&amp;amp;p=personalsettings/EmailSubscriptions.slab&amp;amp;exsvurl=1
&amp;amp;realm=contoso.com</EcpUrl-aggr>

<EcpUrl-mt>PersonalSettings/DeliveryReport.aspx?
rfr=olk&amp;amp;exsvurl=1&amp;amp;IsOWA=&amp;lt;IsOWA&amp;gt;&amp;amp;MsgID=
&amp;lt;MsgID&amp;gt;&amp;amp;Mbx=&amp;lt;Mbx&amp;gt;&amp;amp;realm=contoso.
com</EcpUrl-mt>

<EcpUrl-ret>?
rfr=olk&amp;amp;p=organize/retentionpolicytags.slab&amp;amp;exsvurl=1&amp;am
p;realm=contoso.com</EcpUrl-ret>

<EcpUrl-sms>?
rfr=olk&amp;amp;p=sms/textmessaging.slab&amp;amp;exsvurl=1&amp;amp;realm=con
toso.com</EcpUrl-sms>

<EcpUrl-publish>customize/calendarpublishing.slab?
rfr=olk&amp;amp;exsvurl=1&amp;amp;FldID=&amp;lt;FldID&amp;gt;&amp;amp;realm=
contoso.com</EcpUrl-publish>

<EcpUrl-photo>PersonalSettings/EditAccount.aspx?
rfr=olk&amp;amp;chgPhoto=1&amp;amp;exsvurl=1&amp;amp;realm=contoso.com</EcpU
rl-photo>

<EcpUrl-tm>?
rfr=olk&amp;amp;ftr=TeamMailbox&amp;amp;exsvurl=1&amp;amp;realm=contoso.com<
/EcpUrl-tm>

<EcpUrl-tmCreating>?
rfr=olk&amp;amp;ftr=TeamMailboxCreating&amp;amp;SPUrl=&amp;lt;SPUrl&amp;gt;&
amp;amp;Title=&amp;lt;Title&amp;gt;&amp;amp;SPTMAppUrl=&amp;lt;SPTMAppUrl&am
p;gt;&amp;amp;exsvurl=1&amp;amp;realm=contoso.com</EcpUrl-tmCreating>

<EcpUrl-tmEditing>?
rfr=olk&amp;amp;ftr=TeamMailboxEditing&amp;amp;Id=&amp;lt;Id&amp;gt;&amp;amp
;exsvurl=1&amp;amp;realm=contoso.com</EcpUrl-tmEditing>

<EcpUrl-extinstall>Extension/InstalledExtensions.slab?
rfr=olk&amp;amp;exsvurl=1&amp;amp;realm=contoso.com</EcpUrl-extinstall>

<OOFUrl>https://mail.contoso.com/EWS/Exchange.asmx</OOFUrl>

<UMUrl>https://mail.contoso.com/EWS/UM2007Legacy.asmx</UMUrl>

<OABUrl>https://mail.contoso.com/OAB/c21c7bc2-53b3-4ddc-ad89-
1219b486c37c/</OABUrl>

<ServerExclusiveConnect>off</ServerExclusiveConnect>

</Protocol>

<Protocol>

<Type>EXPR</Type>

<Server>mail.contoso.com</Server>

<SSL>Off</SSL>

<AuthPackage>Ntlm</AuthPackage>

<ServerExclusiveConnect>on</ServerExclusiveConnect>

<CertPrincipalName>None</CertPrincipalName>

</Protocol>

<Protocol>

<Type>WEB</Type>

<Internal>

<OWAUrl AuthenticationMethod="Basic,
Fba">https://mail.contoso.com/owa/</OWAUrl>

<Protocol>

<Type>EXCH</Type>

<ASUrl>https://mail.contoso.com/EWS/Exchange.asmx</ASUrl>

</Protocol>

</Internal>

</Protocol>

</Account>

</Response>

</Autodiscover>

Next steps
After you've retrieved the necessary configuration details for your user from the server,
you are ready to communicate with Exchange to do the things your application needs to
do. What you do next depends on how you communicate with Exchange and what you
want to accomplish. If you need some inspiration, and you're using EWS, you might
explore the Exchange 101 code samples for some ideas.

See also
Autodiscover for Exchange

Exchange Web Services (EWS) Managed API

SOAP Autodiscover web service reference for Exchange

POX Autodiscover web service reference for Exchange


Get domain settings from an Exchange
server
Article • 01/15/2020 • 4 minutes to read

Learn how to get domain settings from an Exchange server by using the Autodiscover
service.

You can retrieve configuration information for an email domain by using the
Autodiscover service. The Autodiscover service provides your application with a process
for connecting to the correct service endpoint for a specific domain.

You can use one of the following development technologies to access the Autodiscover
service:

The Exchange Web Services (EWS) Managed API

EWS

If you are using EWS, you can use the following methods to retrieve user settings:

The SOAP-based Autodiscover service

The XML (POX) Autodiscover service

An autogenerated proxy generated from the SOAP or XML Autodiscover service

For more information about these methods, see Autodiscover for Exchange.

The EWS Managed API provides an object-based interface for retrieving user settings. If
your client application uses managed code, we recommend that you use the EWS
Managed API. The EWS Managed API interface is better optimized for a simple object
model than the typical autogenerated web service proxy.

If you are using EWS, we suggest that you use the SOAP Autodiscover service, because it
supports a richer set of features than the POX Autodiscover service.

The Autodiscover service returns only the requested configuration settings. The
following table lists the domain configuration settings that the Autodiscover service can
return.

Table 1: Domain configuration settings

Configuration setting Description


Configuration setting Description

ExternalEwsUrl The external URL for EWS.

ExternalEwsVersion The version of the Exchange server that hosts the EWS URL.

Prerequisites for getting domain settings


Before you create an application that connects to the Autodiscover service to get
domain settings, make sure that you have access to the following:

Exchange Online, Exchange Online as part of Office 365, or a server running a


version of Exchange starting with Exchange 2007. If you are using the EWS SOAP-
based Autodiscover service, a server running a version of Exchange starting with
Exchange 2010.

An Exchange server that is configured to accept connections from your client


application. For information about how to configure your Exchange server, see
Controlling client application access to EWS in Exchange.

An account that is authorized to use EWS. For information about how to configure
an account, see Controlling client application access to EWS in Exchange.

7 Note

If you are using the EWS Managed API, you must provide a certificate validation
callback in some circumstances. You may also need a certificate validation callback
with some generated proxy libraries, such as those created by Visual Studio. For
more information, see Validate a server certificate for the EWS Managed API.

Core concepts for getting domain settings


Before you use Autodiscover to get domain settings, you should be familiar with the
concepts listed in the following table.

Concept Description

Autodiscover for Provides an overview of how the Autodiscover service works.


Exchange

Use Autodiscover to find Describes the process used by the Autodiscover service to redirect
connection points
your client application to the correct service endpoint.
If you are using the EWS Managed API, you use the
Microsoft.Exchange.WebServices.Data.ExchangeService class in the
Microsoft.Exchange.WebServices.Data namespace to manage your connection to EWS.
The code examples in this section assume that you reference the following namespaces
in your code:

System.Net

Microsoft.Exchange.WebServices.Data.ExchangeService

Get domain settings by using the EWS


Managed API
If you are using the EWS Managed API, you can use the
Microsoft.Exchange.WebServices.Data.AutodiscoverSettings.GetUserSettings method
of the Microsoft.Exchange.WebServices.Data.AutodiscoverService object to generate
the request that retrieves configuration information for a domain, as shown in the
following example. In this example, only some of the possible domain settings are
requested, and only the requested settings are returned from the server.

C#

AutodiscoverService autodiscoverService = new


AutodiscoverService("domain.contoso.com");

autodiscoverService.Credentials = new NetworkCredential("User1", "password",


"domain.contoso.com");

// Submit a request and get the settings. The response contains only the

// settings that are requested, if they exist.

GetDomainSettingsResponse domainresponse =
autodiscoverService.GetDomainSettings(

"domain",

ExchangeVersion.Exchang2013,

DomainSettingName.ExternalEwsUrl,

DomainSettingName.ExternalEwsVersion);

You can parse the collection returned to access each key/value pair. The following
example shows how to parse through each returned element and display the name and
value of each key/value pair.

C#

// Display each retrieved value. The settings are part of a key/value pair.

foreach (KeyValuePair<DomainSettingName, Object> domainsetting in


domainresponse.Settings)

Console.WriteLine(domainsetting.Key.ToString() + ": " +


domainsetting.Value.ToString());

Alternatively, you can obtain the value of a specific setting. In the following example, the
ExternalEwsUrl setting is to be displayed.

C#

// Display a specific setting, such as ExternalEwsUrl.

Console.WriteLine(domainresponse.Settings[DomainSettingName.ExternalEwsUrl])
;

Get user settings by using EWS SOAP


Autodiscover
The following example shows a SOAP XML request to get both domain settings from the
Autodiscover service.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope
xmlns:a="https://schemas.microsoft.com/exchange/2010/Autodiscover"

xmlns:wsa="http://www.w3.org/2005/08/addressing"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<a:RequestedServerVersion>Exchange2013</a:RequestedServerVersion>

<wsa:Action>https://schemas.microsoft.com/exchange/2010/Autodiscover/Autodis
cover/GetDomainSettings</wsa:Action>

<wsa:To>https://autodiscover.exchange.microsoft.com/autodiscover/autodiscove
r.svc</wsa:To>

</soap:Header>

<soap:Body>

<a:GetDomainSettingsRequestMessage
xmlns:a="https://schemas.microsoft.com/exchange/2010/Autodiscover">

<a:Request>

<a:Domains>

<a:Domain>domain</a:Domain>

</a:Domains>

<a:RequestedSettings>

<a:Setting>ExternalEwsUrl</a:Setting>

<a:Setting>ExternalEwsVersion</a:Setting>

</a:RequestedSettings>

<a:RequestedVersion>Exchange2013</a:RequestedVersion>

</a:Request>

</a:GetDomainSettingsRequestMessage>

</soap:Body>

</soap:Envelope>

The following example shows the XML response that is returned by the server after it
parses the request from the client.

XML

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"

xmlns:a="http://www.w3.org/2005/08/addressing">

<s:Header>

<a:Action
s:mustUnderstand="1">https://schemas.microsoft.com/exchange/2010/

Autodiscover/Autodiscover/GetDomainSettingsResponse</a:Action>

<h:ServerVersionInfo
xmlns:h="https://schemas.microsoft.com/exchange/2010/Autodiscover"

xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<h:MajorVersion>15</h:MajorVersion>

<h:MinorVersion>0</h:MinorVersion>

<h:MajorBuildNumber>160</h:MajorBuildNumber>

<h:MinorBuildNumber>4</h:MinorBuildNumber>

<h:Version>Exchange2013</h:Version>

</h:ServerVersionInfo>

</s:Header>

<s:Body>

<GetDomainSettingsResponseMessage
xmlns="https://schemas.microsoft.com/exchange/2010/Autodiscover">

<Response xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<ErrorCode>NoError</ErrorCode>

<ErrorMessage />

<DomainResponses>

<DomainResponse>

<ErrorCode>NoError</ErrorCode>

<ErrorMessage>No error.</ErrorMessage>

<DomainSettingErrors />

<DomainSettings>

<DomainSetting i:type="DomainStringSetting">

<Name>ExternalEwsUrl</Name>

<Value>https://failover.exchange.microsoft.com/ews/exchange.asmx</Value>

</DomainSetting>

<DomainSetting i:type="DomainStringSetting">

<Name>ExternalEwsVersion</Name>

<Value>15.00.0085.000</Value>

</DomainSetting>

</DomainSettings>

<RedirectTarget i:nil="true" />

</DomainResponse>

</DomainResponses>

</Response>

</GetDomainSettingsResponseMessage>

</s:Body>

</s:Envelope>

Next steps
Domain settings provide the basic information that your client needs to connect to EWS.
You can use this information to connect to EWS, or you can retrieve additional
configuration settings for an email account from the server. For more information, see
the following article:

Get user settings from Exchange by using Autodiscover

See also
Setting up your EWS application

Autodiscover web service reference for Exchange

EWS reference for Exchange


Refresh configuration information by
using Autodiscover
Article • 06/14/2022 • 3 minutes to read

Learn how and when to refresh configuration information for your Exchange connection
by using Autodiscover.

When your EWS application runs for the first time, Autodiscover provides a great way
for you to collect the information you need in order to connect to your user's Exchange
mailbox. But Autodiscover isn't just for first time use. Using Autodiscover on a regular
basis can help keep your application connected by enabling it to respond to changes in
the Exchange deployment.

Cache Autodiscover endpoint and EWS settings


While we recommend that you use Autodiscover regularly, how regularly you use it
requires some consideration. Ideally you can balance responding quickly to changes in
the environment against generating too much unnecessary network traffic. When your
application gets a successful Autodiscover response for the first time, you should save
the following information so that you do not have to repeat the Autodiscover process
every time you send an EWS request.

Table 1. Information to cache for Autodiscover requests

Setting to Valid Details


cache for…

Autodiscover As When you save the Autodiscover endpoint that returned a successful
endpoint long response, you do not have to repeat the process of generating a list of
as it Autodiscover endpoints and trying them until you get a successful
works response.

NOTE: The EWS Managed API does not support caching the
Autodiscover endpoint.
Setting to Valid Details
cache for…

EWS URL and One By saving the EWS URL and other related settings, you do not have to
any other week send a new Autodiscover request for each EWS request or if your
settings application restarts. However, even if an EWS URL works for your user, a
retrieved from server might be available that is more optimal.

the
Autodiscover For example, the user's mailbox might have moved to a new mailbox
response server, resulting in a new preferred EWS endpoint. We recommend that
you refresh your user settings by sending a new Autodiscover request
after one week has passed since your last Autodiscover request. This
time can be adjusted to meet the requirements of your application.

Refresh cached configuration information


Now that you have the information cached, let's examine how you can keep that cache
fresh. We recommend that you refresh your cached information when:

The information's validity period expires.

A Connection-related error occurs AND your cached information was last refreshed
over an hour ago.

To refresh your cached information, send an Autodiscover request to a cached


Autodiscover endpoint, and do the following:

If the request succeeds, compare the EWS endpoint in the response with the
cached EWS endpoint, and do the following:

If they are different, use the new EWS endpoint. If you're refreshing to recover
from an error, retry the failed request with the new endpoint.

If they are the same, continue to use the original EWS endpoint. If you're
refreshing to recover from an error, handle the error as appropriate.

If the request fails, start the Autodiscover process from the beginning. After you
get a successful response, replace the cached Autodiscover endpoint with the
Autodiscover endpoint that succeeded and continue to use the new EWS endpoint.
If you do not get a successful response, continue to use the original Autodiscover
endpoint and EWS endpoint. If you're refreshing to recover from an error, handle
the error as appropriate.

The following figure provides a visual representation of this process.


Figure 1. Process for refreshing configuration information by using Autodiscover

Connection-related errors
Refreshing your cached configuration information can help with some errors, but not all.

Table 2. Errors addressed by refreshing your cache

Error EWS Managed API Notes


implementation

DNS or network ServiceRemoteException Any error that indicates that the server could
failure errors
not be found or could not be reached might
be resolved by trying Autodiscover.

Example: Host name


could not be found. Your cached EWS endpoint might no longer
be valid, and Autodiscover might be able to
point you to the new server.

HTTP status errors


ServiceRemoteException HTTP status errors can happen for many
different reasons.

Example: 503 Service


Unavailable However, it's a good idea to try Autodiscover
to see if a new EWS endpoint is available for
the user.
Error EWS Managed API Notes
implementation

EWS error codes


ResponseCodeType
Most EWS error codes don't warrant
refreshing your configuration information.

Example:
ErrorConnectionFailed However, the following specifically indicate
that the configuration information needs to
be updated:

- ErrorConnectionFailed

- ErrorMailboxMoveInProgress

See also
Autodiscover for Exchange
Generate a list of Autodiscover endpoints
Get user settings from Exchange by using Autodiscover
Handling Autodiscover error messages
Article • 01/15/2020 • 5 minutes to read

Learn about the different types of Autodiscover errors and what to do with them.

Autodiscover enables your applications to retrieve configuration information


automatically, and it works great. However, things don't always go according to plan.
Let's look at the common errors that might occur and how you can handle them to
minimize the need to prompt your user to manually configure your client.

HTTP status errors


The first type of error you might encounter when sending Autodiscover requests is the
HTTP status. If the HTTP status in your response is anything other than 200 (OK), the
response payload doesn't contain the Autodiscover response you were looking for. For
simplicity, we can group non-200 status codes into three categories.

Table 1. HTTP status codes

Status Type of error To handle…


code

301 Redirect Resend your request to the URI contained in the "Location" HTTP
or error response header. For details, see Handling redirect errors.
302

401 Unauthorized Because the Autodiscover process involves trying multiple potential
error URLs, you could get this on one URL only to have the next one accept
your credentials. For this reason, you shouldn't consider a single 401
error to indicate that the credentials are invalid. However, if you receive
401 errors from multiple URLs, you might want to prompt the user to
reenter their password (if possible).

Any Invalid Consider the URL that returns any other non-200 status code to be
other Autodiscover invalid, and continue trying the next URL in your list.
non- endpoint
200 error
status

Autodiscover errors
Even if you get a 200 (OK) status code after sending an Autodiscover request, that
doesn't mean that the server sent the information you need. The 200 status only means
that you have an Autodiscover response, and that response might contain an error
within the payload. The location of the error information differs depending on whether
the format is SOAP or POX.

SOAP Autodiscover errors


For SOAP Autodiscover, the response can contain one or more ErrorCode (SOAP)
elements, in different places. Typically you can expect one as a child element of the
Response (SOAP) element, and one as a child of each UserResponse (SOAP)
element in the response. You might also encounter one as a child of a UserSettingError
(SOAP) element, if one is present. The context of the error depends on where the
ErrorCode element is located, as follows:

As a child element of the Response element, the ErrorCode element represents an


error that applies to the entire request.

As a child of the UserResponse element, it represents an error that applies just to


that specific user.

As a child of a UserSettingError element, it represents an error that applies to a


specific setting that was requested.

Let's take a look at an example of a response. In this example, the ErrorCode element
under the Response element has a value of "NoError", which indicates overall success.
However, the ErrorCode element under the UserResponse element has a value of
"RedirectAddress", which indicates that an error occurred for that particular user.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"

xmlns:a="http://www.w3.org/2005/08/addressing">

<s:Header>

<a:Action
s:mustUnderstand="1">https://schemas.microsoft.com/exchange/2010/Autodiscove
r/Autodiscover/GetUserSettingsResponse</a:Action>

<h:ServerVersionInfo
xmlns:h="https://schemas.microsoft.com/exchange/2010/Autodiscover"

xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<h:MajorVersion>14</h:MajorVersion>

<h:MinorVersion>3</h:MinorVersion>

<h:MajorBuildNumber>136</h:MajorBuildNumber>

<h:MinorBuildNumber>1</h:MinorBuildNumber>

<h:Version>Exchange2010_SP2</h:Version>

</h:ServerVersionInfo>

</s:Header>

<s:Body>

<GetUserSettingsResponseMessage
xmlns="https://schemas.microsoft.com/exchange/2010/Autodiscover">

<Response xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<ErrorCode>NoError</ErrorCode>

<ErrorMessage />

<UserResponses>

<UserResponse>

<ErrorCode>RedirectAddress</ErrorCode>

<ErrorMessage>Redirection address.</ErrorMessage>

<RedirectTarget>[email protected]</RedirectTarget>

<UserSettingErrors />

<UserSettings />

</UserResponse>

</UserResponses>

</Response>

</GetUserSettingsResponseMessage>

</s:Body>

</s:Envelope>

The ErrorCode (SOAP) article contains a full list of possible errors. Most of these
indicate an unrecoverable error, but a few warrant special handling.

Table 2. SOAP Autodisover ErrorCode values

ErrorCode To handle…
value

RedirectAddress Restarting Autodiscover with a new email address with the email address in the
RedirectTarget (SOAP) element.

RedirectUrl Resending your request to a new URL to the URL in the RedirectTarget
element.

ServerBusy Retry this URL after a small delay. You might wait a set amount of time or
simply move this URL to the end of your list of URLs to try. If you receive this
error multiple times from a URL, you should consider the URL to be invalid.

POX Autodiscover errors


The POX Autodiscover service reports errors a little differently. Non-recoverable errors
are contained in the Error (POX) element. The ErrorCode (POX) article contains a full
list of possible error codes.

Redirect errors are contained in the Action (POX) element. Any value of the Action
element other than "settings" indicates a redirect error.

Table 3. POX Autodisover ErrorCode values


Action To handle…
value

redirectAddr Restarting Autodiscover with a new email address with the email address in the
RedirectAddr (POX) element.

redirectUrl Resending your request to a new URL to the URL in the RedirectUrl (POX)
element.

In this example, the Action element has a value of "redirectAddr", which indicates that a
new request should be sent with the new email address contained in the RedirectAddr
element.

XML

<?xml version="1.0" encoding="utf-8"?>

<Autodiscover
xmlns="https://schemas.microsoft.com/exchange/autodiscover/responseschema/20
06">

<Response
xmlns="https://schemas.microsoft.com/exchange/autodiscover/outlook/responses
chema/2006a">

<Account>

<Action>redirectAddr</Action>

<RedirectAddr>[email protected]</RedirectAddr>

</Account>

</Response>

</Autodiscover>

Handling redirect errors


You can handle redirect error scenarios in two ways:

By restarting Autodiscover with a new email address.

By resending your request to a new URL.

Both scenarios require some validation before proceeding.

Restarting Autodiscover with a new email address


When you get a new email address in an Autodiscover redirect response, first verify that
the new email address that was provided in the redirect error response is not the same
address that you sent in the request that resulted in the error. If it is, you should not
restart Autodiscover and instead consider the URL that generated the response to be
invalid.
If the new email address is different, discard your existing list of potential Autodiscover
endpoint URLs and generate a new list based on the new email address.

Resending your request to a new URL


When you get a new URL in an Autodiscover redirect response, you should first validate
the URL as follows:

Verify that the URL is an HTTPS URL.

Verify that you have not received an error from this URL with the current email
address before.

If applicable to your application, inform the user of the redirection and get their
permission to follow the redirect.

Send a request to the URL and verify that the SSL certificate presented by the
server is valid.

If the URL passes validation, resend the request to this new URL.

See also
Autodiscover for Exchange

Find Autodiscover endpoints by using SCP lookup in Exchange

ErrorCode (SOAP)

ErrorCode (POX)
Improving performance when using
Autodiscover for Exchange
Article • 09/15/2021 • 2 minutes to read

Learn about ways to improve the performance of the Autodiscover process in your
application.

There are a lot of reasons to like Autodiscover. Configuring your application to connect
to Exchange with no user intervention is great! If you're reading this article, you
probably already know all the reasons to use and love Autodiscover, so we won't list
them here. Instead, we're going to talk about a potential downside: performance.

Autodiscover isn't inherently a slow process, but it's not inherently fast either. The
Autodiscover process involves a lot of network activity, and that introduces a lot of
potential for delays. The Autodiscover process has three phases; all three have the
potential to affect performance:

Defining the Autodiscover endpoint candidate pool — For applications running on


domain-joined computers, this can involve SCP lookups, which involves
communicating with Active Directory Domain Services (AD DS).

Trying each candidate — This requires an HTTP request/response to each


candidate endpoint.

Trying other alternatives — When the candidates in your Autodiscover endpoint


candidate pool don't produce results, you can do an unauthenticated GET request
(HTTP request/response) and a DNS lookup.

On the surface this might not seem like much. However, imagine a scenario where the
Autodiscover endpoint candidate pool is more than one or two URLs, and you don't find
a working one until the last URL in your pool. The delay can become a bit more
noticeable. So, what can you do?

Consider the need for SCP lookup


When SCP objects are present and configured well, they can speed up the Autodiscover
process. In other situations, however, they can slow it down. If SCP isn't used in your
environment, skip the entire SCP lookup portion of the Autodiscover process to save
time.
The EWS Managed API makes this easy: just set the
ExchangeService.EnableScpLookup property to false before calling the
ExchangeService.AutodiscoverUrl method. If you're using the AutodiscoverService
class, set the AutodiscoverService.EnableScpLookup property to false before calling
any of its methods.

Use Autodiscover less often


Autodiscover isn't designed to be used frequently use by applications. The intent behind
Autodiscover is for an application to use it to discover configuration information, and
then cache that information for a period of time. If you aren't caching configuration
information, consider adding caching to your application to reduce the number of times
you use Autodiscover.

Even if you are already caching, evaluate how long you cache configuration information.
The standard is to refresh Autodiscover information every 24 hours, but you might be
able to extend that time. You should test with your target environments and come up
with a "time-to-live" for your configuration that works for you.

Minimize requested data


If you're using the AutodiscoverService class in the EWS Managed API, or the
GetUserSettings operation (SOAP) operation via SOAP, you have direct control over
what settings are returned in the response. Although you can request quite a few
settings, chances are that your application only needs a handful of them. Every setting
that you request requires more processing on the server, which means more time
waiting for a response. Evaluate the settings you are requesting, and eliminate any that
you don't need.

If you're using the ExchangeService.AutodiscoverUrl method in the EWS Managed API,


you cannot change the settings you request. However, this method is already fairly
efficient; it only requests the ExternalEwsUrl and InternalEwsUrl settings from the
UserSettingName enumeration .

If you're using the POX Autodiscover service, you cannot request specific properties.

See also
Autodiscover for Exchange

Find Autodiscover endpoints by using SCP lookup in Exchange


Refresh configuration information by using Autodiscover

ExchangeService class

AutodiscoverService class
Outlook add-ins and EWS in Exchange
Article • 06/14/2022 • 4 minutes to read

Find information about Outlook add-ins and how they work with EWS in Exchange.

Outlook add-ins provide a single interface and programming model that uses web
standards to enable you to create a custom experience for your email users. You can
create mail apps that display contextual or helpful information in an HTML5 frame
hosted in Outlook; for example, a mail app can show a Bing map with an address
highlighted when an email message contains an address. Or when a user is composing a
message, a mail app can show additional information about the recipient, and insert a
standard greeting into the email at the touch of a button.

7 Note

"Outlook" in this article refers to the Outlook rich client, Outlook RT, Outlook Web
App, and OWA for Devices.

The mail apps interface is part of the JavaScript API for Office. You can use the API to
access information in Exchange to enable your mail app to:

Recognize entities , like addresses, phone numbers, task suggestions, or meeting


suggestions in an email.

Open and display existing messages and appointments in a separate view so


that users can cross-reference information in one or more messages.

Make EWS requests to the Exchange server that hosts the user's mailbox. A mail
app can, for example, get a list of folders so that the user can choose one to store
the message, or show all the items in a conversation, or mark an email message as
junk.

Get a token to uniquely identify an email account to enable single sign on on a


third-party service.

Get a token that enables a third-party service to make EWS requests on behalf of
the user, for example, to extract the attachments from an item, or to get an item
from the Exchange server for further processing.

You can use mail apps to customize the Outlook Web App experience for your users; if,
however, you want to customize the "look and feel" of Outlook Web App, see these
articles on TechNet:
Create a theme for Outlook Web App

Customize the Outlook Web App sign-in, language selection, and error pages

Your organization can install mail apps on an internal server to limit access to authorized
users, or you and other mail app developers can put mail apps on the Office Store for
sale to the general public. Anyone who is running Outlook can download, install, and
use mail apps from the marketplace.

If you want to learn more about creating mail apps, check out the Outlook add-ins
documentation or the Make an EWS request sample.

EWS and Outlook add-ins


You can use a subset of EWS operations on the Exchange server that hosts the account
that runs a mail app.

The mailbox.makeEwsRequestAsync function enables you to make EWS requests from


your mail app back to the server that hosts the user's mailbox. You create the SOAP
envelope and XML request, and the makeEwsRequestAsync function calls EWS with an
authentication token that identifies the mailbox and mail app that is making the request.
To help secure the user's mailbox, the Exchange server will reject any requests that do
not come from the mail app or from a mailbox that is not hosted on the server.

Like any other application, a mail app needs permissions to work. Your administrator
needs to:

Grant EWS access to the mail apps user.

Set "OAuthAuthentication" to true on the Client Access Server EWS directory.

You also need to make sure that your app requests the read/write mailbox permission in
the apps for Office permission model.

When these steps are complete, a subset of folder and item EWS operations are
available for the mail app to use.

Table 1. EWS folder and item operations that mail apps can use

Folder operations Item operations


Folder operations Item operations

CreateFolder operation
CopyItem operation

FindFolder operation
CreateItem operation

GetFolder operation
FindItem operation

UpdateFolder operation
FindConversation operation

GetConversationItems operation

GetItem operation

MarkAsJunk operation

MoveItem operation

SendItem operation

UpdateItem operation

Service callback tokens


Service callback tokens enable mail apps to pass an access token to a third-party service
so that the service can make EWS requests to the Exchange server that hosts the
mailbox. For example, a mail app can pass a service callback token to a third-party
service along with a list of attachment IDs for pictures attached to an email. The service
can then use the attachment IDs and the callback token to make an EWS request to the
user's Exchange server to get the attached pictures. Mail apps can also use the service
callback token with a list of item IDs to get email and appointment items from the
Exchange server.

The service callback token is an opaque token that the third-party service attaches to
the EWS request in a bearer authentication header. The token identifies the mail app
and the mailbox to help secure the EWS request. To learn how to use service callback
tokens, see the Outlook add-ins: Get attachments from an Exchange server sample.

See also
Controlling client application access to EWS in Exchange

Mailbox.makeEwsRequestAsync method (JavaScript API for Office)

Outlook add-ins

Mailbox.getUserIdentityTokenAsync method (JavaScript API for Office)

Authenticate an Outlook add-in by using Exchange identity tokens

Understanding Outlook add-in permissions

Set-WebServicesVirtualDirectory
Outlook add-ins: Make an EWS request

Outlook add-ins: Use a client identity token

Outlook add-ins: Get attachments from an Exchange server


Microsoft Graph REST APIs for mail,
calendars, and contacts
Article • 10/11/2021 • 2 minutes to read

Find information about the Microsoft Graph APIs that you can use to access mail,
calendars, and contacts in Office 365, Exchange Online, or Exchange Server in hybrid
deployments.

Office 365, Exchange Online, and Exchange Server in hybrid deployments provide a new
way to work with email, calendars, and contacts. The Microsoft Graph Mail, Calendar,
and Contact REST APIs provide a powerful, easy-to-use way to access and manipulate
Exchange data. These APIs are based on open standards: OAuth version 2.0 for
authentication, and OData version 4.0 and JSON for data abstraction. This provides the
following advantages:

Because these APIs require OAuth for authentication, your application does not
have to handle or store user credentials.

OAuth makes it possible to request tightly scoped permissions to user data. For
example, you might design your application to request permission and read only a
user's calendar.

Work with email and mail folders


You can use the Mail API to get, create, update, delete, move, copy, and send email. You
can also get, create, update, and delete mail folders.

Work with events, calendars, and calendar


groups
You can use the Calendar API to get, create, update, and delete events. You can also get,
create, update, and delete calendar groups and calendars.

Work with contacts and contact folders


You can use the Contacts API to get, create, update, and delete contacts in a user's
mailbox. You can also get contact folders.
Next steps
Head over to the Microsoft Graph documentation page to get more information about
the Mail, Calendar, and Contacts APIs, including guidance for setting up your
environment and getting started with the APIs.

Also be sure to check out the quick starts and code samples to see these APIs in action.

See also
Microsoft Graph documentation
On-premises requirements for the REST API
License information
Article • 09/15/2021 • 2 minutes to read

Notwithstanding any other terms that may be applicable to your use of the EWS
Content (defined below), the following restrictions apply to your use of documentation,
software code or other materials made available by Microsoft from this web site that are
associated with Microsoft Exchange Web Services Managed API, version 1.1 or later, or
Exchange Web Services in Exchange Server 2010 SP1 or later versions of the Exchange
Server product, including any pre-release or finalized versions thereof (collectively, "EWS
Content"): you may use the EWS Content solely in programs developed by you that
interoperate with Microsoft Exchange Server.
EWS client design overview for
Exchange
Article • 03/04/2022 • 6 minutes to read

Learn about the design considerations for developing with EWS for Exchange.

This article provides overview information about designing an Exchange Web Services
(EWS) application. You can use this information to determine whether EWS is the right
API for your application, and if so, what type of client implementation you should use.
This article also provides best practice information for designing applications that can
target Office 365, Exchange Online, and versions of Exchange starting with Exchange
2007, in one code base, and important decision points for targeting on-premises
Exchange servers versus targeting Exchange Online.

Is EWS the right API for your application?


Before you begin to design your application, it is important to consider whether EWS is
the right API for you. If you are developing against Exchange Server or Exchange Online,
EWS is the preferred client access technology. Client access development for versions of
Exchange starting with Exchange 2007 has primarily been focused on EWS. New client
access functionality that is implemented in Outlook uses EWS, including the Out of
Office (OOF) and Availability features introduced in Exchange 2007, and the MailTips
and Get Rooms functionality introduced in Exchange 2010. This represents a committed
investment in EWS for both internal and external partners who develop Exchange client
applications.

EWS is the primary client access API for your Exchange client applications. However, in
some cases, you might consider other Exchange APIs for client application development.
For example, Exchange ActiveSync provides the following advantages over EWS:

The XML structure has been tokenized to make Exchange ActiveSync a more
compact protocol.
Exchange ActiveSync contains a policy mechanism to control client access and to
provide other robust enterprise mobile messaging solutions.

7 Note

You need a license in order to develop Exchange ActiveSync clients. To learn about
the differences between Exchange ActiveSync and EWS, see Choosing between
Exchange ActiveSync and Exchange Web Services (EWS) .
MAPI RPC over HTTP is another programmability option for Exchange client
applications. However, MAPI RPC over HTTP does not provide an intuitive interface for
communicating between clients and the server.

For more information about Exchange development technologies, see Explore the EWS
Managed API, EWS, and web services in Exchange.

Options for EWS client development


Several options are available for developing against Exchange by using EWS. The best
option for you will depend on the development platform, tools, available
implementations, and application requirements for your organization. The following are
the four primary options that are available for building EWS client applications:

The EWS Managed API


The EWS Java API
The EWS autogenerated proxies
A custom EWS client API

EWS Managed API


The EWS Managed API is a custom web service client. It is the standard client access
API for .NET Framework applications.

The following are some of the benefits of using the EWS Managed API:

It provides an intuitive object model.


It abstracts the complexities of the service description in the WSDL and schema
files.
It includes client-side business logic.
It handles the web requests and responses and object serialization and
deserialization.
It is Microsoft-supported.

Note, however, that the EWS Managed API is not a complete solution. Some
functionality is not implemented in the EWS Managed API. Although the EWS Managed
API doesn't implement all EWS functionality, it might be the best choice for your client
application development, for the following reasons:

You can use the .NET Framework for development.


It implements Autodiscover in addition to most parts of the EWS object model.
It implements client-side business logic for working with EWS, in the
ExchangeService class.

You might choose to use the EWS web service API instead of the EWS Managed API for
any of the following reasons:

Your application does not use the .NET Framework.


You don't want to distribute the EWS Managed API assembly.
Your application uses features that aren't implemented in the EWS Managed API.

To more, see Get started with EWS Managed API client applications.

7 Note

The EWS Managed API is now available as an open source project on GitHub .
You can use the open source library to:

Contribute bug fixes and enhancements to the API.


Get fixes and enhancements before they are available in an official release.
Access the most comprehensive and up-to-date implementation of the API, to
use as a reference or to create new libraries on new platforms.

We welcome your contributions via GitHub.

EWS Java API


The EWS Java API is an open source project on GitHub that can be updated and
extended by the community. It is stylistically similar to the EWS Managed API and
uses EWS SOAP requests and responses over the wire. Although you can't access all
EWS SOAP operations by using the EWS Java API, with the recent creation of the
open source project, we are looking to the community to bridge this gap. Note that
Microsoft Support, with an appropriate support contract, will address any questions
related to the EWS SOAP protocol but not the EWS Java API itself. The EWS Java API is
available for download and community contribution on GitHub .

EWS autogenerated proxies


Autogenerated client APIs are generated from the EWS WSDL and XML schema
definitions. Client object model generators are available for many languages. In general,
the autogenerated object models manage object serialization and deserialization. They
do not include business logic and the autogeneration process often creates artifacts that
make the object model less intuitive to use. Exchange support covers the XML that is
sent and received by the client but not the object model.

Custom EWS client API


For some applications that use a small set of EWS functionality, you might create a
custom client API to communicate with Exchange. This enables you to consume fewer
system resources. This is useful for clients that run on memory-constrained devices, such
as clients running the .NET Micro Framework.

EWS client features


Regardless of the development option that you choose, you should consider how EWS
features are implemented in your client. Feature availability is based on the EWS schema
version that your application targets. Because EWS schemas are backward- and forward-
compatible, if you create an application that targets an earlier schema version, such as
Exchange Server 2007 SP1, your application will also work against a later schema
version, such as the Exchange Server 2013 SP1 service, as well as Exchange Online.

Because features and feature updates are driven by the schema, we recommend that
you use the earliest common code base that targets the EWS features that you want to
implement in your client application. Many applications can target the
Exchange2007_SP1 version, because the Exchange 2007 SP1 schema contains almost all
the core Exchange functionality for working with items and folders in the Exchange
store. We recommend that you maintain code forks for each EWS schema version. The
following are the schema versions that are currently available.

XML

<xs:simpleType name="ExchangeVersionType">

<xs:restriction base="xs:string">

<xs:enumeration value="Exchange2007" />

<xs:enumeration value="Exchange2007_SP1" />

<xs:enumeration value="Exchange2010" />

<xs:enumeration value="Exchange2010_SP1" />

<xs:enumeration value="Exchange2010_SP2" />

<xs:enumeration value="Exchange2013" />

<xs:enumeration value="Exchange2013_SP1" />

</xs:restriction>

</xs:simpleType>

The schema versions are maintained in the ExchangeVersionType simple type.


For information about the features that are available in each EWS schema version, see
EWS schema versions in Exchange.

In this section
Web service API feature availability in Exchange and the EWS Managed API
EWS schema versions in Exchange
Configuration options for EWS in Exchange
Comparing Exchange Online and Exchange on-premises client programming
EWS throttling in Exchange
Redistribution requirements for the EWS Managed API
Instrumenting client requests for EWS and REST in Exchange

See also
Start using web services in Exchange
Develop web service clients for Exchange
EWS application types
Web service API feature availability in
Exchange and the EWS Managed API
Article • 09/15/2021 • 3 minutes to read

Learn about which EWS and web service API features are available in each version of Exchange and
the EWS Managed API.

Exchange client applications often target many versions of Exchange. For this reason, you might
want to design your application such that you can turn EWS client features on and off based on the
version of Exchange that hosts your users' mailbox. This article provides information about which
service API features are available in different versions of Exchange and the EWS Managed API. Use
this information to design your application to apply broadly to customers running multiple
versions of Exchange.

For detailed information about the differences between versions of Exchange, review the EWS
schema files and the associated reference documentation .

API features by Exchange version


The Exchange web service APIs, including EWS and Autodiscover, are developed with multi-version
compatibility in mind. Therefore, an application that targets Exchange 2007 also works against
versions of Exchange starting with Exchange 2013, including Exchange Online and Exchange Online
as part of Office 365.

The following table indicates which API features are available in each version of Exchange and
versions of the EWS Managed API starting with version 2.0. Because your application might target
multiple versions of Exchange, it will be helpful for you to know which versions support the
features that your client implements. You can use the Autodiscover service to discover which
version of Exchange a client targets for a user so that you can turn features on and off depending
on whether they are available to your users.

Table 1. Web service feature availability in versions of Exchange and the EWS Managed API

API feature Exchange EWS Exchange Exchange Exchange Exchange Exchange Exchange
Online Managed 2013 2010 SP2 2010 SP1 2010 2007 SP1 2007
(Office API
365)

Ambiguous X X X X X X X X
name
resolution

Apps for X X X
Outlook
management
API feature Exchange EWS Exchange Exchange Exchange Exchange Exchange Exchange
Online Managed 2013 2010 SP2 2010 SP1 2010 2007 SP1 2007
(Office API
365)

Archive mailbox X X X X X
access

Autodiscover X X X X X X X X
(POX)

Autodiscover X X X X X
(SOAP)

Automatic X X X X X X X X
replies (OOF)

Availability X X X X X X X X

Availability X X X X X X
(Rooms)

Bulk transfer X X X X

Contact groups X X X X X X

Conversation X X X X X
management

DateTime X X X X
precision

Delegate X X X X X X X
management

Distribution list X X X X X X X X
expansion

Dumpster X X X X X X
access

eDiscovery
X X X

Enhanced time X X X X X X
zones

Folder X X X X X X X
permissions

Identifier X X X X X X X
conversion

Inbox X X X X X
management

Item and folder X X X X X X X X


access

API feature Exchange EWS Exchange Exchange Exchange Exchange Exchange Exchange
Online Managed 2013 2010 SP2 2010 SP1 2010 2007 SP1 2007
(Office API
365)

Mailbox events X X X X X X X X
(pull and push)

Mailbox events X X X X X
(streaming)

Mailtips X X X X X

Password X X X X
expiration

Personas
X X

Post items X X X X X X X

Public folder X X X X X X X
access

Retention X X X
policies

Search X X X X X X
(indexed)

Search (store)
X X X X X X X X

Synchronization X X X X X X X X

Unified Contact X X
Store

Unified X X X X X X X
Messaging Web
Service

Unified X X X X X X
Messaging
(EWS-based)

User X X X X X X
configuration
objects

User photos
X X

You can find more information about the web service features that are available in different
versions of Exchange by reading about the EWS operations , the Autodiscover service , and the
ExchangeService methods .

To learn more
If you want to go deeper to understand the specific differences between Exchange versions, you
can do any of the following:

Explore the EWS schema to investigate the differences between each version of EWS in
more detail.

Download EWSEditor . You can use EWSEditor to specify different target schema versions
and submit queries based on the target schema version.

See also
EWS client design overview for Exchange
Get started with EWS Managed API client applications
What's new in EWS and other web services in Exchange
EWS schema versions in Exchange
Article • 01/15/2020 • 6 minutes to read

Learn about the EWS schema and how to design your application to work with it, as well
as the features that are available with each schema version, and how the schema relates
to the Exchange service version.

The EWS schema defines the data structures that can be sent to and returned by
Exchange. Each new version of Exchange that contains a significant change to EWS
functionality will contain a new schema. EWS and the EWS schema are both backward,
and in some cases, forward compatible - applications designed against earlier versions
of EWS will work, in most cases, with later versions of EWS, and applications that target
later versions of EWS will work if the same functionality was included in an earlier
version. This article will help you understand the role of the EWS schema, how schema
versioning works, the relationship between the schema version and the service version,
and how to design your application to work with the EWS schema.

Role of the EWS schema


The EWS schema does the following:

Defines the feature set that is available to a client. A client can get the list of the
supported schema versions by using the SOAP Autodiscover service. The client can
then determine which features it can access, because each schema version
represents an EWS feature set. Each new schema released for EWS contains of the
schema entities from the previous version plus the schema definitions for any new
functionality. This way, EWS supports applications that target an earlier version of
EWS.

Provides a general description of the API contract. You can use this contract to
determine the data structures that can be sent to and received from Exchange.

Provides a versioning mechanism for sending requests. The Exchange server


contains all the supported EWS schema versions in its virtual directory.

Designing your application with schema


version in mind
Keep the following points in mind as you design your application to work with different
versions of the EWS schema:
Turn on/off functionality based on the schema version. You'll want to map client
functionality to the schema version and, in some cases, to the version of the
service. The following example will return a PropertySet based on the version of
the schema and service.

C#

private static PropertySet InitPropertySetByVersion(ExchangeService


service)

PropertySet props;

// The schema version to target to access the NormalizedBody


property

// is Exchange2013 or later. The server version to target to access


the

// NormalizedBody property on an email is 15 or later, which

// equates to Exchange 2013.

if (service.RequestedServerVersion >= ExchangeVersion.Exchange2013


&amp;&amp;

service.ServerInfo.MajorVersion >= 15)

props = new PropertySet(EmailMessageSchema.NormalizedBody);

else

props = new PropertySet(EmailMessageSchema.Body);

return props;

Version your requests with the earliest version of the EWS schema that supports
the functionality you want to use. This will make your client applicable to a larger
number of potential Exchange servers. This is less important if you're developing a
line-of-business application to target your organization's servers only, but is very
important if you're building an application for a wider Exchange audience.

Features by schema version


The schema versions that are available to a client are identified in the
ExchangeVersionType simple type located in the types.xsd schema. The
ExchangeVersionType is implemented by the RequestServerVersion element. The
RequestServerVersion element is sent in all EWS requests to indicate to the server which
version of the schema the client targets. This in turn identifies the feature set that is
available to the client.

Table 1: EWS features by product and schema version


Product Associated Features
version schema version

Exchange The latest schema Includes all the features in the current version of Exchange in
Online version. addition to any new features that are added for online clients.

Exchange Exchange2013_SP1 Includes all the features in Exchange 2013.

2013 SP1
The following features were introduced in Exchange 2013 SP1:

Mailbox hold policy


Propose new time
Read receipt updates for updating and deleting
items
IRM information update for conversations

Exchange Exchange2013 Includes all features introduced in Exchange 2007 and Exchange
2013 2010.

The following features were introduced in Exchange 2013:

Archiving
eDiscovery
Personas
Retention policies
Unified Contact Store
User photos

Exchange Exchange2010_SP2 Includes all the features introduced in Exchange 2010 SP1.

2010 SP2
The following features were introduced in Exchange 2010 SP2:

Get Password Expiration


DateTime precision
Updated property identifiers for contacts
New impersonation scenarios
Product Associated Features
version schema version

Exchange Exchange2010_SP1 Includes all the features introduced in Exchange 2010.

2010 SP1
The following features were introduced in Exchange 2010 SP1:

Create, retrieve and modify Inbox rules


Programmatic access to Archive Mailbox
Conversations actions
Firewall traversing notifications
Improved administration features
Improved mixed version support
Throttling protection support
Control of application access to EWS
Client certificate authentication support

Exchange Exchange2010 Includes all features introduced in Exchange 2007 SP1.

2010
The following features were introduced in the initial release
version of Exchange 2010:

Full Private Distribution List


User Configuration Objects
Folder Associated Items
Message tracking
Unified Messaging
SOAP Autodiscover
Enhanced Time Zone support
Room resource availability information
Indexed search
Dumpster access
MailTips information

Exchange Exchange2007_SP1 Includes all the features introduced in Exchange 2007.

2007 SP1
The following features were introduced in Exchange 2007 SP1:

Delegate management
Folder permissions
Public folders
Post items
ID conversion
Product Associated Features
version schema version

Exchange Exchange2007 The following features were introduced in the initial release
2007 version of Exchange 2007:
Full access to items, folders, and attachments (Create, Get,
Update, Delete)
Availability
Out of Office settings
Notifications
Synchronization
Name resolution
Distribution list (DL) expansion
Search

Relationship between the EWS schema and the


service version
The EWS schema version is related to the version of the EWS service that the server is
running. The naming pattern for the EWS schema is related to the on-premises versions
of Exchange. For example, the initial release of Exchange 2013 has a service version of
15.00.0516.032 and the schema name Exchange2013. Because the schema was updated
for Exchange 2013, both Exchange 2013 and Exchange Online with a service version of
15.00.0516.032 and later have the same version name for the latest schema. In earlier
versions of Exchange, the EWS schema was not updated with cumulative updates
(formerly called rollups). But because Exchange is updated more frequently to support
Exchange Online, cumulative updates now contain schema updates for EWS. The
schema file names, and the associated schema version name, are only updated with
service packs or major releases of Exchange on-premises.

While the EWS schema defines the contract, in some scenarios, the service version is the
only way for a client to determine how it is supposed to interact with the service. Service
behavior changes that aren't reflected in the schema can only be determined by the
service version returned in all EWS responses. For example, when public folders were
redesigned in Exchange 2013, the operations that are used to move and copy public
folders changed. If you designed a client to copy public folders in Exchange 2010, you
would need to update it to use different operations to get the same result in Exchange
2013.

How the EWS schema is updated


Exchange servers running versions of Exchange starting with Exchange 2007 include the
EWS schema in the virtual directory that hosts the EWS service. The current schema
version is always represented by the types.xsd and messages.xsd files. Figure 1 shows
how the messages.xsd schema is forked when a new version of the schema is
developed. Before new functionality is added, a copy of the original messages.xsd
schema is included and renamed to represent the previous version of the schema. The
messages.xsd file is then updated with the service description for the new version.

Figure 1. How the EWS schema is updated

Before the EWS schema is updated for a new version, the current version of the schema
is forked and renamed using the following convention:

<schemaname>-<majorserverversion><servicepack>.xsd

The original file name then represents the latest schema. All new features are added to
the latest schema, with the exception of updates and fixes to the earlier versions of the
schema.

See also
EWS schema versions in Exchange
Autodiscover for Exchange
Develop web service clients for Exchange
Configuration options for EWS in
Exchange
Article • 09/15/2021 • 2 minutes to read

Find information about configuration settings that your EWS client can access, and the
configurable Exchange settings that can affect your EWS client.

Many configuration settings can affect what your EWS client application can do. These
configuration settings are either:

Read-only or read-writeable from the client.

Accessed on the Exchange server that hosts your EWS service.

A client can access settings on Exchange Online, Exchange Online as part of Office 365,
and an on-premise Exchange server. All on-premise Exchange server settings are
available to Exchange administrators; however, not all of these settings are available to
Exchange Online tenant administrators. This article describes which configuration
settings clients, Exchange Server administrators, and Exchange Online tenant
administrators can access.

Configuration settings that clients can access


Your client application can get and set a number of configuration options from the
Exchange server. Configuration settings that all EWS applications need are provided by
the Autodiscover service. Other configuration settings are used for specific application
scenarios.

Table 1. Web service features that provide configuration options for EWS clients

Feature Description

Autodiscover The Autodiscover service provides your client applications with configuration
service information so that your client can automatically configure itself to communicate
with EWS.

Custom You can use one of several options to store custom configuration information in
configuration your mailbox: user configuration objects, custom items, or extended properties.
information
stored in a
mailbox
Feature Description

Delegate EWS provides CRUD operations for managing delegate access to a mailbox.
management Delegates are users who have been given permission to access another user's
mailbox.

You can use the delegate management operations to enable delegate


management by using EWS, or, if you're using the EWS Managed API, you can use
the following methods:

- ExchangeService.AddDelegates

- ExchangeService.GetDelegates

- ExchangeService.UpdateDelegates

- ExchangeService.RemoveDelegates

eDiscovery eDiscovery client applications can get search configuration information that
search includes an eDiscovery search query, a list of searchable mailboxes, and the
configuration identifier of in-place mailbox holds.

Folder Folder permissions limit what a user can do in a public folder, and in the case of
permissions delegate access, what a delegate can do in another user's folder. You can use
either the Folder.Bind method or the GetFolder operation to access the
permission set of every folder, including public folders, shared private folders, or
folders to which users have delegate access.

Mail tips, The GetServiceConfiguration operation provides read-only service


Unified configuration information for mail tips, Unified Messaging, and protection rules.
Messaging,
or protection
rules

Configuration settings that administrators can


access on the Exchange server
Most client application scenarios don't require changes to server configuration settings;
however, some scenarios do. For example, to enable a middle-tier application to act as a
user, you need to set Exchange Impersonation on the server. Note that some settings
can only be accessed on on-premise Exchange servers. If you are targeting Exchange
Online, your client application might need to work with the default settings.

Table 2. Exchange server configuration options that affect EWS clients

Feature Accessible from For more information, see…


Exchange Online?
Feature Accessible from For more information, see…
Exchange Online?

Virtual directory settings (including No Get-


authentication) WebServicesVirtualDirectory

Set-
WebServicesVirtualDirectory

Autodiscover No Get-
AutodiscoverVirtualDirectory
Set-
AutodiscoverVirtualDirectory

Compliance Yes Archiving

eDiscovery

Retention hold

Data loss prevention

Delegate management Yes Manage Permissions for


Recipients

Exchange Impersonation Yes Configure Exchange


Impersonation

Mail tips, Unified Messaging, or Yes MailTips

protection rules Unified Messaging Cmdlets

Outlook Protection Rules

Throttling No Throttling settings

User agent filtering Yes User agent filtering

See also
Get service configuration information by using EWS in Exchange
EWS client design overview for Exchange
Start using web services in Exchange
Develop web service clients for Exchange
Get service configuration information
by using EWS in Exchange
Article • 09/15/2021 • 2 minutes to read

Find out how to get service configuration information for UM, policy nudges, mail tips,
and protection rules from EWS in Exchange.

Does your EWS application work with Unified Messaging (UM), policy nudges, mail tips,
or protection rules? If so, your application will need to call the GetServiceConfiguration
operation to get the service configuration information that it needs. The
GetServiceConfiguration operation returns configuration information that is specific to
each of these EWS features.

7 Note

The EWS Managed API does not implement this functionality.

Table 1. Configuration information that the GetServiceConfiguration operation returns

EWS GetServiceConfiguration operation returns…


feature

UM A value that indicates whether UM is enabled.


A value that indicates whether play on phone is enabled.
The play on phone dial string.

Policy Policy nudges for display in your client.


nudges

Mail tips A value that indicates whether mail tips are enabled.
The maximum number of recipients per request.
The maximum message size.
The large audience threshold.
A value that indicates whether the number of external recipients is shown.
A list of internal domains.
A value that indicates whether policy tips are enabled.
The large audience cap threshold for indicating whether your mail is
considered to have a large number of recipients.

Protection Protection rules setup for your client.


rules A list of domains that are internal to your organization.
Code example: Get service configuration
information for mail tips by using EWS
The following code example uses the GetServiceConfiguration operation to request
service configuration information for mail tips. You can request additional service
configuration information by adding more ConfigurationName elements with
different values.

C#

private static void GetServiceConfiguration(ExchangeService service,


NetworkCredential creds)

// XML for the GetServiceConfiguration request SOAP envelope for mail tips
configuration information.

const string getServiceConfigurationRequest =

"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +

"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-
instance\"\n" +

"
xmlns:m=\"http://schemas.microsoft.com/exchange/services/2006/messages\"\n"
+

"
xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\" \n" +

"
xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +

" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n" +

" <soap:Header>\n" +

" <t:RequestServerVersion Version=\"Exchange2013\" />\n" +

" </soap:Header>\n" +

" <soap:Body>\n" +

" <m:GetServiceConfiguration>\n" +

" <m:ActingAs>\n" +

" <t:EmailAddress>[email protected]</t:EmailAddress>\n" +

" <t:RoutingType>SMTP</t:RoutingType>\n" +

" </m:ActingAs>\n" +

" <m:RequestedConfiguration>\n" +

" <m:ConfigurationName>MailTips</m:ConfigurationName>\n" +

" </m:RequestedConfiguration>\n" +

" </m:GetServiceConfiguration>\n" +

" </soap:Body>\n" +

"</soap:Envelope>";

// Encoded GetServiceConfiguration operation request.

byte[] payload =
System.Text.Encoding.UTF8.GetBytes(getServiceConfigurationRequest);

try

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(service.Url);

request.AllowAutoRedirect = false;

request.Credentials = creds;

request.Method = "POST";

request.ContentType = "text/xml";

Stream requestStream = request.GetRequestStream();

requestStream.Write(payload, 0, payload.Length);

requestStream.Close();

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

if (response.StatusCode == HttpStatusCode.OK)

Stream responseStream = response.GetResponseStream();

StreamReader reader = new StreamReader(responseStream);

string responseFromServer = reader.ReadToEnd();

Console.WriteLine("You will need to parse this response to get the


configuration information:\n\n" + responseFromServer);

reader.Close();

responseStream.Close();

else

throw new WebException(response.StatusDescription);

catch (WebException e)

Console.WriteLine(e.Message);
}

Next steps
After you request service configuration information, use the XmlDocument class to
load the response XML so that you can parse it. Then, depending on your scenario, you
can do one of the following:

Use the GetMailTips operation to get mail tips for client applications to display
to users.

If UM is enabled, learn about how to play mailbox items over your phone.

See also
Configuration options for EWS in Exchange
Setting up your EWS application
Develop web service clients for Exchange
Comparing Exchange Online and
Exchange on-premises client
programming
Article • 09/15/2021 • 5 minutes to read

Learn about the design considerations for creating an EWS Managed API or EWS client
application that works against Exchange Online and Exchange on-premises.

For the most part, clients and the web services in Exchange they target will work the
same way regardless of whether the target is an Exchange Online, Exchange Online as
part of Office 365, or Exchange on-premises server. There are, however, some
exceptions, and you'll want to make sure that your application can handle them. Use the
information in this article to help you design your client to target both Exchange Online
and Exchange on-premises.

Autodiscover client programming


considerations
Autodiscover provides configuration information for Exchange clients. A client
application can discover its configuration information in one of three ways, depending
on whether the client is targeting Exchange Online or Exchange on-premises.

Table 1. Autodiscover service types and Exchange applicability

Autodiscover service type Applies to

SOAP Autodiscover
Exchange Online and versions of Exchange on-premises starting
with Exchange 2010

POX Autodiscover Exchange Online and versions of Exchange on-premises starting


with Exchange 2007

Service connection point Versions of Exchange on-premises starting with Exchange 2007
(SCP) lookup

In addition to the client configuration information, that SOAP and POX Autodiscover
also return the Exchange service version and indicate whether the service is hosted by
Exchange Online. This information is returned in different elements, depending on the
type of Autodiscover you use.
Table 2. Autodiscover elements that return service version and Exchange Online
hosting information

Autodiscover XML element that contains XML element that indicates whether the
service type service version user has an Exchange Online account

SOAP Setting (SOAP) element with Setting (SOAP) element with the
Autodiscover the CasVersion text value. UserMSOnline text value.

POX ServerVersion (POX)


MicrosoftOnline

Autodiscover

Ensure that your client captures this information so that it can target the feature set that
is available on the Exchange server. This can be useful to determine whether your client
can expect different behavior based on whether the user's mailbox is located in an
Exchange Online or Exchange on-premises organization.

Testing and log files in applications that target


Exchange Online
Exchange Online does not provide access to the EWS protocol log files, EWS
performance counters, and EWS-related service events that are available on on-premises
Exchange servers. Access to these is useful, however, in discovering how your
application performs when it interacts with EWS. Make sure that you test your
application against a test Exchange on-premise server so that you can optimize its
performance. If possible, you can change the throttling settings on your test server to
match the throttling settings for Exchange Online, so you can evaluate how your
application will behave when it connects to Exchange Online.

 Tip

You can use the EWSRelentless tool to perform an EWS load test. You can use
this tool with a test server, the EWS protocol logs, EWS performance counters,
service events, and the EWS throttling settings to better understand how EWS
performs under load.

Throttling settings and Exchange Online


The default values for the EWS throttling settings are different for Exchange Online than
they are for Exchange on-premises. Also, you cannot change Exchange Online throttling
settings. You can use Exchange Management Shell cmdlets to discover the throttling
settings for Exchange on-premises; however, those cmdlets are not enabled for
Exchange Online.

Exchange Management Shell cmdlets and


configuration settings
A number of cmdlets can directly or indirectly affect the web service APIs in Exchange
Online and Exchange on-premises. Cmdlets are not available for the following in
Exchange Online:

Throttling settings

Virtual directory settings

Authentication settings

For details about the cmdlets that are available for Exchange Online, see PowerShell
cmdlets in Exchange Online . For more about cmdlets that are available for Exchange
on-premises, see Exchange 2013 cmdlets .

Client affinity and network load balancers


Most EWS communication does not require that the client participate in maintaining
affinity with Exchange. The subscriptions to mailbox events do require that the client
provide cookies and other information to maintain affinity with the Exchange server that
maintains the queue of mailbox events for a user. Exchange Server 2010 uses the
exchangecookie to maintain client affinity across the network load balancers. Exchange
Online and versions of Exchange on-premises starting with Exchange 2013 use the X-
AnchorMailbox header, X-PreferServerAffinity header, and X-BackEndOverrideCookie
cookie to maintain affinity for mailbox notifications.

Authentication
Clients can authenticate with Exchange Online by using either Basic or OAuth. Versions
of Exchange on-premises starting with Exchange 2013 use NTLM by default; however,
it's possible to configure Exchange on-premises to use Basic authentication as well.

Client latency diagnostics


Exchange Online collects client latency diagnostics if they are reported. This helps
Microsoft support troubleshoot connectivity issues with Exchange Online. Exchange on-
premises does not collect client latency diagnostics. If your client targets Exchange on-
premises, the client can't report latency diagnostics to the server.

Functionality in the EWS Managed API


The EWS Managed API exposes some functionality that is specific to Exchange on-
premises, such as service point connection lookup, and some functionality that is
specific to Exchange Online, such as client latency reporting. Note that it's possible for
some functionality to be implemented in Exchange Online before it is implemented in
the EWS Managed API.

The following EWS Managed API functionality is only applicable to Exchange Online:

Client latency reporting

Basic pre-authentication

The ability to request that the RequestId be returned in responses

API features in Exchange Online plans and


Exchange Server editions
Different feature sets might be available in different Office 365 and Exchange Online
plans, or in the standard and enterprise versions of Exchange Server. Be aware that
some API functionality might not be available to your client application depending on
the Exchange Online plan or Exchange Server edition that hosts a user's mailbox.

Because feature availability can change, we recommend that you check the Exchange
Online plans and Exchange Server editions to evaluate how feature availability might
affect your client. You can also design your client to check feature availability by using
the GetServiceConfiguration operation or by sending test requests for the operations
that implement the features. If the feature isn't available, the response from the server
will indicate as such.

Other considerations
You can do the following when targeting Exchange on-premises but not Exchange
Online:
Create a client that is installed on the Exchange server.

Install custom transport agents that can affect the delivery and content of
messages you create and send with EWS and other clients.

See also
EWS client design overview for Exchange
Comparing Exchange Online and Exchange Server 2013
Compare all Office 365 for business plans
EwsRelentless - EWS load generation tool
Web service API feature availability in Exchange and the EWS Managed API
EWS throttling in Exchange
EWS throttling in Exchange
Article • 02/11/2022 • 25 minutes to read

Learn about the throttling policies that affect EWS when you are using Exchange.

Provided by: Glen Scales; Michael Mainer, Microsoft Corporation

The article provides information about EWS throttling in Exchange Online, Exchange
Online as part of Office 365, and on-premises versions of Exchange starting with
Exchange 2010. Throttling in Exchange helps to ensure server reliability and uptime by
limiting the amount of server resources that a single user or application can consume.
Throttling is a reactive response to overuse of system resources that may affect service
reliability and functionality. Exchange constantly monitors the health of critical
infrastructure resources, such as mailbox databases. When high load factors are
detected that degrade the performance of these resources, EWS connections are
throttled proportionally based on the amount that each caller has contributed to this
high load condition. The result is that a user may be within their throttling limit and still
experience slowdowns until the health of the resource is back to operational levels.

Each client access protocol in Exchange, including EWS, has a throttling policy. When
you design applications that use EWS, it is important to account for throttling policies,
to help ensure application reliability and the health of your Exchange server. This article
identifies the different throttling policies and service limits for EWS, whether you are
targeting Exchange Online or versions of Exchange on-premises starting with Exchange
Server 2010. As applicable, this article also identifies differences in throttling policies in
different versions of Exchange.

) Important

Default throttling policy, access to throttling policy, and throttling policy


configuration differs between Exchange Online and Exchange on-premises. Specific
throttling setting values are only accurate for a specific version of Exchange.
Because setting values vary across versions, and because Exchange administrators
can change the default throttling policies for on-premises deployments, this article
does not provide the default setting values. It is more important for you to be
aware of the considerations for designing an application that functions within
throttling limits and reacts appropriately to throttling scenarios.

If you are an application developer, you need to factor throttling into your application
design. Different versions of Exchange have different default values for the EWS
throttling parameters. Client and service applications that are designed to access
different versions of Exchange will need to account for these settings, whether they be
default values, custom values set by an Exchange administrator, or, as for Exchange
Online, set by default and not discoverable. Because throttling parameter values cannot
be discovered programmatically, your client design specifications should include a plan
for the application to adapt to different potential throttling limits. When you design
multi-threaded applications that will access a large number of mailboxes, or when many
clients are accessing the same mailbox, consider the limits on concurrency that the
default policy applies to Exchange.

Throttling policies that affect EWS


The throttling polices in Exchange affect not only EWS, but also all client connections to
the Exchange server, including the protocols used by Office Outlook, Outlook Web App,
and Exchange ActiveSync.

The CPUStartPercent throttling policy can affect EWS performance when you are
running Exchange 2010. When the average CPU utilization of Exchange processes
running on the Client Access server — including, but not limited to, the EWS process —
exceeds the value specified by this policy, inbound requests will be delayed to reduce
CPU utilization. You cannot change the value of this policy, but knowing about it can
help you troubleshoot performance issues. The sampling logic the Client Access server
performs for this value is an average over a 10 second rolling window. This allows the
process to respond appropriately to quick spikes in CPU utilization. When this threshold
is exceeded, inbound connections to EWS are delayed. This delay is capped at 500
milliseconds (msecs) at a theoretical 100% CPU usage per EWS request. If a batch EWS
request to get 100 items is passed, the server will check the CPU usage 100 times (once
per item) for a maximum delay of 50 seconds. The delay time is linearly proportional to
CPU usage. At CPUStartPercent, the delay is 0 (a thread yield) and it increases linearly
up to 500 msec at 100% CPU usage. Because throttling policies apply to all Exchange
users, it's unlikely that CPU usage would exceed the CPUStartPercent limit on an
Exchange Client Access server, because individual users or applications cannot gain
enough CPU utilization to affect server operation.

The following table lists the throttling policy parameters that affect applications that use
EWS.

Table 1: Throttling policy parameters that affect EWS

Throttling policy parameter name Applies Description


to
Throttling policy parameter name Applies Description
to

DiscoveryMaxConcurrency Exchange Specifies the number of concurrent


2013 discovery search connections that a user
Exchange can have at the same time.
Online

DiscoveryMaxKeywords Exchange Specifies the maximum number of


2013 keywords that a user can include in a
Exchange discovery search.
Online

DiscoveryMaxKeywordsPerPage Exchange Specifies the number of keywords for


2013 which to show statistics.
Exchange
Online

DiscoveryMaxMailboxes Exchange Specifies the maximum number of source


2013 mailboxes that a user can include in a
Exchange discovery search.
Online

DiscoveryMaxMailboxesResultsOnly Exchange Specifies the maximum number of


2013 mailboxes you can search in an In-Place
Exchange eDiscovery search without being able to
Online view the statistics.

DiscoveryPreviewSearchResultsPageSize Exchange Specifies the number of messages


2013 returned in a eDiscovery search preview
Exchange response.
Online

EwsCutoffBalance Exchange Defines the resource consumption limits


2013 for EWS user before that user is
Exchange completely blocked from performing
Online operations on a specific component.

EwsMaxBurst Exchange Defines the amount of time that an EWS


2013 user can consume an elevated amount of
Exchange resources before being throttled. This is
Online measured in milliseconds. This value is set
separately for each component.

EwsRechargeRate Exchange Defines the rate at which an EWS user's


2013 budget is recharged (budget grows by)
Exchange during the budget time.
Online
Throttling policy parameter name Applies Description
to

EWSMaxSubscriptions Exchange Defines the maximum number of active


2010 push, pull, and streaming notification
Exchange subscriptions that a user can have on a
2013 specific Client Access server at one time.
Exchange This is budgeted differently for different
Online Exchange versions.

EWSFastSearchTimeoutInSeconds Exchange Defines the amount of time in seconds


2010 that fast searches made by using
Exchange Search in EWS continue before
they time out. Fast searches are searches
made by using an Advanced Query Syntax
(AQS) query string in a FindItem
operation .

EWSFindCountLimit Exchange Defines the maximum number of items


2010 from a FindItem operation or
Exchange FindFolder operation that can exist in
2013 memory on the Client Access server at
Exchange one time for one user. The default value
Online for this property is 1000. The fallback
value for this value is 1000. In Exchange
Online and on-premises versions of
Exchange starting with Exchange 2013,
this throttling policy cannot be queried or
configured by a cmdlet. In Exchange
Online and on-premises versions of
Exchange starting with Exchange 2013,
the EWSFindCountLimit for AQS search
and any Exchange search with a
restriction is 250 results. An Exchange
search without a restriction will return up
to 1000 results.

EWSPercentTimeInAD Exchange Defines the percentage of time per


2010 minute during which a specific user can
execute Active Directory requests.

EWSPercentTimeInCAS Exchange Defines the percentage of time per


2010 minute during which a specific user can
execute Client Access server code.

EWSPercentTimeInMailboxRPC Exchange Defines the percentage of time per


2010 minute during which a specific user can
execute mailbox RPC requests
Throttling policy parameter name Applies Description
to

EWSMaxConcurrency Exchange Defines the number of concurrent open


2010 connections that a specific user can have
Exchange against an Exchange server that is using
2013 EWS at one time. The default value for
Exchange Exchange 2010 is 10. The default value for
Online Exchange 2013 and Exchange Online is
27. This policy applies to all operations
except for streaming notifications.
Streaming notifications use the
HangingConnectionLimit to indicate the
number of open streaming event
connections that are available. For more
information, see What throttling values
do I need to take into consideration?.

MessageRateLimit Exchange Defines the number of messages per


2010 minute that can be submitted.
Exchange
2013
Exchange
Online

RecipientRateLimit Exchange Defines the limit to the number of


2010 recipients that a user can address in a 24-
Exchange hour period.
2013
Exchange
Online

ForwardeeLimit Exchange Defines the limit to the number of


2010 recipients for Inbox forward/redirect
Exchange actions in a 24-hour period.
2013
Exchange
Online

ConcurrentSyncCalls Exchange Defines the limit to the number of


2019 concurrent sync calls
Exchange (SyncFolderHierarchy, SyncFolderItems)
2016 for a user.
Exchange
Online

U Caution
Do not set throttling polices to null. This will set the policy to equal unlimited,
which indicates that a throttling policy isn't set.

Displaying the policies that apply to Exchange


mailboxes
Exchange on-premises provides Exchange Management Shell cmdlets that you can use
to set and get throttling policy. Exchange Online does not provide access to the
throttling policy cmdlets.

Use the following cmdlets to display throttling polices for an on-premises Exchange
Server deployment:

Get-ThrottlingPolicy — Gets the client throttling settings for one or more


throttling policies. For more information, see Get-ThrottlingPolicy on TechNet.

Get-ThrottlingPolicyAssociation — Enables you to view the relationship between


an object and its associated throttling policies. The object can be a user with a
mailbox, a user without a mailbox, or a contact. For more information, see Get-
ThrottlingPolicyAssociation on TechNet.

Use the following command to show the default throttling policy for Exchange 2010.

Get-ThrottlingPolicy | Where-Object {$_.IsDefault -eq "True"} | format-list

Use the following command to show the global throttling policy (which equates to the
default throttling policy in Exchange 2010) in Exchange 2013.

Get-ThrottlingPolicy | Where-Object {$_.ThrottlingPolicyScope -eq "Global"} |


format-list

Use the following command to show the throttling policy associated with a user in
Exchange 2010 or Exchange 2013. Replace the user name [email protected] with the
user name of the target user for whom you want to get throttling policy information.

Get-ThrottlingPolicyAssociation [email protected] | format-list

Running this command in Exchange Management Shell results in an output similar to


the following.

PowerShell

PS C:\>Get-ThrottlingPolicyAssociation [email protected]

RunspaceId : 72153d6-9dce-2fae-8dbd-5ca5f760g2df

ObjectId : john

ThrottlingPolicyId :

Name : john

Identity : FHXB-28178dom.contoso.com/Users/john

IsValid : True

NeedsToSuppressPii : False

ExchangeVersion : 0.10 (15.0.0.0)

DistinguishedName : CN=john,CN=Users,DC=FHXB-
28178dom,DC=contoso,DC=com

Guid : 2c10dab6-de28-1937-ad8g-535832613a08

7 Note

When the ThrottlingPolicyId property is blank, the default policy is applied to the
mailbox.

You can set throttling policy on an Exchange server by using the Set-ThrottlingPolicy
and Set-ThrottlingPolicyAssociation cmdlets. You can create and remove non-default
throttling policies by using the New-ThrottlingPolicy and Remove-ThrottlingPolicy
cmdlets.

 Tip

We recommend that you design your applications to adhere to the default


throttling policy. Only make changes to default throttling policies if your client
application design cannot accommodate the default policy. Be aware that less
restrictive throttling policies can negatively affect service reliability.

Throttling considerations for applications that


use EWS impersonation
Impersonation is an authorization method that enables a single account to access many
accounts. When a service account impersonates users, it acts as the users and therefore
assumes the rights that are assigned to those users. Log files record the access as the
impersonated user. Administrators use role-based access control (RBAC) to configure
impersonation via the Exchange Management Shell.

When impersonation is used, the budgets for all the throttling thresholds apply
differently depending on the version of Exchange. The budget is either calculated
against the account that is impersonated, or the service account. If your application is
multi-threaded and makes concurrent requests against multiple mailboxes, you should
consider how the throttling threshold will affect your application's performance. In
general, be aware of the following limits on service accounts when you create a service-
based application that uses impersonation to access all mailboxes:

When you use Impersonation, the service account has a separate budget for the
following policy parameters:
EWSMaxConcurrency
EWSPercentTimeInAD
EWSPercentTimeInCAS
EWSPercentTimeInMailboxRPC
EWSMaxSubscriptions
EWSFastSearchTimeoutInSeconds
EWSFindCountLimit

The EWSMaxConcurrency budget is shared for the service account and the
account being impersonated for all connections to versions of Exchange earlier
than Exchange 2010 Service Pack 2 (SP2) Update Rollup 4 (RU4). Starting with
Exchange 2010 SP2 RU4, and including Exchange Online, the service account
access uses a separate budget from the user EWSMaxConcurrency budget. For
more information about the update to the Exchange concurrent connection
throttling policy for EWS, see Description of Update Rollup 4 for Exchange Server
2010 Service Pack 2 .

EWS streaming notifications in versions of Exchange starting with Exchange 2010,


and including Exchange Online, have an additional cloned EWSMaxConcurrency
budget from all other EWS client connections. Streaming notification connections
are counted against a separate budget than all other EWS operations. The
streaming notification maximum concurrency budget is actually two different
budgets: one budget is for all service accounts, and one budget is for the account
being impersonated. Streaming notifications in Exchange Online and versions of
Exchange starting with Exchange 2013 use the HangingConnectionLimit to limit
the number of connections.

For example, let's assume that EWSMaxConcurrency is equal to five. A user can
have five open pull notification connections, while an service account can have five
concurrent pull notification connections against the user's mailbox at the same
time as the user.

The following table identifies how EWSMaxSubscriptions throttling budgets are


calculated between the service account and the account to impersonate.

Table 2: EWSMaxSubscriptions budget accounting


Exchange EWSMaxSubscriptions throttling budget accounting
version

Exchange Charged against the target mailbox.


Online

Exchange Charged against the target mailbox.


2013

Exchange Charged against the target mailbox.


2010 SP3

Exchange Charged against the calling account. Starting with Exchange 2010 SP2 RU4,
2010 SP2 the budget is charged against the target mailbox.

Exchange Charged against the calling account.


2010 SP1

Exchange Charged against the calling account.


2010

Because the EWSMaxSubscriptions throttling budget is charged against the


account being impersonated, there is no limit on the number of mailboxes a
service account can subscribe to and receive streaming notifications for, as long as
impersonation is being used. For the account being impersonated, you can't have
more than n concurrent requests per target mailbox, where n is the
EWSMaxSubscriptions value. If you were not using impersonation, the same
service account could not have more than n concurrent requests total. So, the
takeaway is that by using impersonation on a service account, you exponentially
increase the number of mailboxes you can service. For more information, see
Maintain affinity between a group of subscriptions and the Mailbox server in
Exchange.

The EWSPercentTimeInMailboxRPC, EWSPercentTimeInCAS, and


EWSPercentTimeInAD policy parameters refer to actions performed by a single
thread. When an application performs multiple concurrent operations, you should
account for the cumulative effect of these operations on the user resource budget.

Throttling implications for EWS batch requests


EWS enables you to batch multiple item requests into a single request that is executed
by the Client Access server. This allows for greater efficiency and performance. When an
Exchange server executes a batched request, it checks the user's budget after the
execution of each item within the batch. If the application is over budget, the processing
of the next item in the batch is delayed until the budget for that user has recharged. To
ensure that applications that use batch operations run successfully, limit the number of
item requests that can be included in a single batch, and divide large batches across
multiple smaller batches to increase the reliability of the results. The effect that a batch
operation has on particular throttling thresholds depends on the type of the request,
the size of the items to be processed (for example in UploadItems or ExportItems
operations) and the mailbox content. Throttling policies affect batch operations by
causing the request to take longer to process. The caller will therefore have to wait
longer for the response, and, because EWS limits the execution time of a batch request
to one minute, the call could time out.

To determine the optimum batch size for an application, perform unit testing using
various input sets to ensure that the application does not encounter any errors in a
production environment.

Throttling policy parameters that affect EWS


search operations
Search operations in EWS can require large amounts of time and resources, depending
on how the search is run and what information is requested. To control resource usage
during searches, two policy parameters take effect: EWSFastSearchTimeoutInSeconds
and EWSFindCountLimit.

The EWSFastSearchTimeoutInSeconds policy parameter specifies the amount of time, in


seconds, that EWS fast searches (also known as content indexing search) run before they
time out. A fast search is a search made by using an Advanced Query Syntax (AQS)
query string in a FindItem operation .

You can search an Exchange mailbox folder in two ways:

By using an Exchange store search, which performs a sequential scan of all


messages in the target search scope.

By using the Exchange Search service (content indexing).

Both of these types of searches can result in timeouts. When possible, use the Exchange
Search service because these searches are often targeted against mailbox indexes and
use AQS queries. The following example shows how to perform an AQS search of the
Inbox by using EWS and the Exchange Search service.

C#

ItemView iv = new ItemView(1000);

FindItemsResults<Item> fiitems =
service.FindItems(WellKnownFolderName.Inbox, "subject:football", iv);

If you can't use an AQS search, avoid using overly complex search filters. Also try to
avoid creating search filters based on computed values if the query involves extended
MAPI properties. AQS search was introduced in Exchange 2010.

7 Note

The first time you run a complex Exchange store search query, it runs very slowly
and may time out. After that, the query will respond more quickly. For more
information about the backend Exchange server processes that occur during
Exchange store search queries, see Understanding the Performance Impact of
High Item Counts and Restricted Views on TechNet. Using a SearchFilter creates
a dynamic restriction that helps similar queries in the future, but because these
restrictions are dynamic in nature, they are not permanent or reliable, and are
deleted after a maximum of three days.

The EWSFindCountLimit policy parameter specifies the maximum number of items from
the results of a FindItem or FindFolder operation that can exist in memory on a Client
Access server at the same time for one user. Every item or folder that EWS processes in a
FindItem or FindFolder request is counted against the budget specified in the
EWSFindCountLimit element. When the response is sent back to the requester, the find
count charge for the current call is released. The response the server returns to a
requester when the budget is exceeded is based on the RequestServerVersion element
value and whether the requester specified paging. When the value of the
RequestServerVersion element indicates Exchange 2010 or an earlier version of
Exchange, the server sends a failure response with error code ErrorServerBusy. If the
value of the RequestServerVersion element indicates a version of Exchange starting with
Exchange 2010 SP1 or Exchange Online, and the client is using paging, EWS may return
a partial result set instead of an error. Your application should expect that EWS might
not return all items. If the value of the IncludesLastItemInRange element is false, the
application should make another FindItem or FindFolder request with the new offset
and continue until the IncludesLastItemInRange element returns true.

When you use a FindItem or FindFolder operation, it is important to use paging. The
EWS Managed API enforces the use of paging, but if you are using other methods, such
as EWS proxy objects or raw SOAP, you need to explicitly set paging. The following
example shows how to use paging in the EWS Managed API.

C#
ItemView iv = new ItemView(1000);

FindItemsResults<Item> fiFindItemResults =
service.FindItems(WellKnownFolderName.Inbox, iv);

7 Note

The default policy in Exchange limits the page size to 1000 items. Setting the page
size to a value that is greater than this number has no practical effect.

Applications should also account for the fact that the EWSFindCountLimit throttling
parameter value may result in a partial result set being returned for applications that
make concurrent requests. The following example shows how to use the MoreAvailable
property in the EWS Managed API to ensure that all results are included in a query.

C#

ItemView iv = new ItemView(1000);

service.TraceEnabled = false;

FindItemsResults<Item> fiResults = null;

Do

fiResults = service.FindItems(WellKnownFolderName.Inbox, iv);

PropertySet itItemPropSet = new PropertySet(BasePropertySet.IdOnly) {


EmailMessageSchema.Body };

//Process Items in Result Set


iv.Offset += fiResults.Items.Count;

while (fiResults.MoreAvailable == true);

Throttling policies and concurrency


Concurrency refers to the number of connections from a specific user. A connection is
held from the moment a request is received until a response is sent to the requester. If
users try to make more concurrent requests than their policy allows, the new connection
attempt fails. However, the existing connections remain valid. Throttling policies can
affect concurrency in a number of different ways.

The EWSMaxConcurrency throttling policy parameter sets the number of concurrent


connections that a specific user can have against an Exchange server at one time. To
determine the maximum number of concurrent connections to allow, consider the
connections that Outlook clients will use. Outlook 2007 and Outlook 2010 use EWS to
access availability and Out of Office (OOF) information. Mac Outlook 2011 uses EWS for
all client access functionality. Depending on the number of Outlook clients that are
actively connecting to a user's mailbox, the number of concurrent connections available
for a user might be limited. Also, if your application has to connect to multiple
mailboxes simultaneously while using a single security context, it is important to take
the value of the EWSMaxConcurrency policy into account. For more information about
using a single security context with concurrent connections, see Throttling
considerations for applications that use EWS impersonation earlier in this article.

Applications that concurrently connect to multiple mailboxes have to be able to track


resource usage on the client side. Because EWS operations are request/response-based,
you can ensure that your applications function well within the EWSMaxConcurrency
threshold by tracking the number of connections that occur between the start of a
request and when the response is received and ensuring that no more than ten open
requests occur concurrently.

The EWSFindCountLimit policy parameter specifies the maximum result size a FindItem
or FindFolder operation can use on a Client Access server at the same time for one user.
If an application (or potentially multiple applications) makes two concurrent EWS
FindItem requests that return 100 items each for a specific user, the
EWSFindCountLimit charge against that specific user's budget will be 200. When the
first request returns, the budget drops to 100, and when the second request returns, the
budget drops to zero. If the same application were to make two simultaneous requests
for 1000 items, the budget value would be 2000 items, which exceeds the
EWSFindCountLimit value. If the user's budget for items drops below zero, the next
request results in an error until the user's budget recharges to one or more.

Throttling considerations for EWS notification


applications
If you are building EWS notification applications that make use of either push, pull, or
streaming notifications, you should consider the implications of the
EWSMaxSubscriptions and the EWSMaxConcurrency throttling policies, and the
HangingConnectionLimit.

The EWSMaxSubscriptions policy parameter specifies the maximum number of active


push, pull, and streaming subscriptions that a user can have on a specific Client Access
server at the same time. Different versions of Exchange have different default values for
this parameter. A user can subscribe to all folders in a mailbox by using the
SubscribeToAllFolders property - this uses a single subscription against the
EWSMaxSubscriptions budget. Users can subscribe to individual folders, with each
folder subscription counting towards the EWSMaxSubscriptions budget, up to the limit
set by the value of the EWSMaxSubscriptions parameter (for example, users can
subscribe to 20 calendar folders in different mailboxes if EWSMaxSubscriptions is set to
20).

For information about impersonation and the EWSMaxSubscriptions parameter, see


Throttling considerations for applications that use EWS impersonation earlier in this
article.

The EWSMaxConcurrency policy parameter can also be an issue for EWS notifications;
for example:

When EWS increments the connection count for the owner of the subscription
while the notification is being generated by a push subscription.

When an application is designed to listen to multiple users' mailboxes, and users


receive simultaneous notifications for an instance of a message that is sent to a
distribution list.

If the notification application is multi-threaded and makes simultaneous connection


requests to get more information about a particular message that was received by a
user account, the EWSMaxConcurrency policy limit can be exceeded. To account for
this, consider monitoring the concurrent connections in your application, including
those that might be used by the server, and implementing request queuing on the
client.

The HangingConnectionLimit is only applicable to streaming notifications. This limit is


set in the web.config file, which means that an Exchange administrator can set this value
on an on-premises Exchange server, but Exchange Online mailboxes must use the
default value for this limit, which is 10 for Exchange Online, Exchange 2019, Exchange
2016 and 3 for Exchange 2013. To learn more, see What throttling values do I need to
take into consideration?.

Throttling policy and application performance


The following three parameters of the PercentTimeIn throttling policy affect the amount
of time an EWS application can consume on a Client Access server:

EWSPercentTimeInAD
EWSPercentTimeInCAS
EWSPercentTimeInMailboxRPC

The values specified in the PercentTimeIn policy parameters indicate the amount of
time that one thread making one request is allocated. For example, assuming a
EWSPercentTimeInCAS value of 90, if a process makes two concurrent requests that
spend 54 seconds each running code on the Client Access server, the process uses 108
seconds in a 60 second window. This represents an EWSPercentTimeInCAS parameter
value of 180 percent.

7 Note

The EWSPercentTimeInCAS parameter value is an overlapping superset of the


EWSPercentTimeInAD and EWSPercentTimeInMailboxRPC parameter values. This
means that the expenditure in Client Access server processing time will always be
larger than the expenditures in EWSPercentTimeInAD and
EWSPercentTimeInMailboxRPC. This is because for the Exchange component to
make an Active Directory or RPC call, it must already be running Client Access
server code. In addition, the expenditure in processing time for
EWSPercentTimeInCAS doesn't stop while LDAP or RPC calls are being made.
Although the request might be synchronously waiting for a response from Active
Directory Domain Services (AD DS) or the Exchange store, the process is still
consuming a thread on the server, and therefore the thread should continue to be
charged for that usage.

The amount of CPU time an application may take in a 60-second period might exceed
these throttling limits; therefore, it is important to consider the volume and type of
requests that are being made. For example, a large batch of ResolveNames operations
that are made simultaneously can exceed the EWSPercentTimeInAD policy parameter
value. The policy values that are contained in the default throttling policy are designed
to allow most EWS applications to function without issue; however, when multi-
threaded high-volume applications place a large volume of requests on one particular
Client Access server, this can create problems. To avoid this, consider limiting the size of
batches that are going to execute against the server.

Throttling policies and applications that send a


large volume of email
The default throttling policies include three rate limit policy parameters that can affect
applications that use EWS to send a large volume of messages or send messages in
large batches in a short period of time.

7 Note

In general, we recommend that you do not use EWS to send bulk email. Use an
SMTP host that specializes in bulk mail services to submit frequent large bulk email
messages.

The MessageRateLimit policy parameter specifies the number of messages per minute
that can be submitted by any Exchange client, including EWS. By default, this policy is
set to 30 messages per minute in Exchange Online (it's unlimited in Exchange Server).
For ordinary users in Exchange Online, this rate limit is generally sufficient. However,
applications that send large batches of email messages, for example as part of an
invoicing program, can run into problems. When this policy limit is exceeded, message
delivery for the mailbox is delayed. Specifically, messages will appear in the Outbox or
Drafts folder for longer periods of time when a user or application submits a larger
number of messages than the value specified by the MessageRateLimit parameter. Be
sure to consider this when you are developing a delivery tracking system, especially if
your application uses a mailbox that users connect to via Outlook. When deferred items
are stored in the Outbox or drafts folder, users might interpret that as an error.

The RecipientRateLimit policy parameter specifies the limit on the number of recipients
that a user can address in a 24-hour period. For example, if this value is set to 500, it
means that a single Exchange mailbox account can send messages to no more than 500
recipients each day. This limit applies to messages to recipients that are inside and
outside the organization. This default limit might cause problems for some line-of-
business applications that do end-of-month invoice runs and need to send messages to
more than this number of recipients. You can use external services that enable batch
processing of messages or separate on-premises outbound relay solutions to work
around this limitation.

The ForwardeeLimit policy parameter specifies the maximum number of recipients that
messages can be forwarded or redirected to by means of Inbox rules. This parameter
doesn't limit the number of messages that can be forwarded or redirected to the
recipients.

Errors generated when throttling limits are


exceeded
When throttling polices are exceeded, EWS generates one of the errors listed in the
following table.

Table 3: Throttling limit errors

Error Throttling policy parameter Description


Error Throttling policy parameter Description

ErrorExceededConnectionCount EWSMaxConcurrency Indicates that there are


more concurrent requests
against the server than are
allowed by a user's policy.

ErrorExceededSubscriptionCount EWSMaxSubscriptions Indicates that a user's


throttling policy maximum
subscription count has been
exceeded.

ErrorExceededFindCountLimit EWSFindCountLimit Indicates that a search


operation call has exceeded
the total number of items
that can be returned.

ErrorServerBusy EWSPercentTimeInMailboxRPC
Occurs when the server is
EWSPercentTimeInCAS
busy. The
EWSPercentTimeInAD BackOffMilliseconds value
returned with
ErrorServerBusy errors
indicates to the client the
amount of time it should
wait until it should resubmit
the request that caused the
response that returned this
error code.

The following table lists the HTTP status codes that are returned by throttling errors.

Table 4: HTTP status codes returned by throttling errors

HTTP Description
status
code

HTTP Indicates that EWS requests are queuing with IIS. The client should delay sending
503 additional requests until a later time.

HTTP Indicates an internal server error with the ErrorServerBusy error code. This indicates that
500 the client should delay sending additional requests until a later time. The response may
contain a back off hint called BackOffMilliseconds. If present, the value of
BackOffMilliseconds should be used as the duration until the client resubmits a request.

HTTP Contains an EWS schema-based error response with an ErrorInternalServerError error


200 code. An inner ErrorServerBusy error code may be present. This indicates that the client
should delay sending additional requests until a later time.
See also
Exchange Workload Management
New-ThrottlingPolicy cmdlet
Understanding Client Throttling Policies
ThrottlingPolicy Class
Throttling Policies and the EWSFindCountLimit
Budget Snapshots in the IIS Logs
Effects of Throttling on Your Deployment in Exchange 2010 SP1
Throttling Policy Associations in Exchange 2010 SP1
Throttling Policies and CPUStartPercent
Impersonation and EWS in Exchange
Redistribution requirements for the EWS
Managed API
Article • 09/15/2021 • 2 minutes to read

Find out how you can redistribute the EWS Managed API assemblies with your
application.

As you design your EWS Managed API application, you'll also want to consider how you
will release it to your users.

Redistributing your EWS Managed API


application
Unless your application is located on the Exchange server, you will need to redistribute
the EWS Managed API assemblies. The EWS Managed API download contains two
assemblies that you can redistribute: Microsoft.Exchange.WebServices.dll and
Microsoft.Exchange.WebServices.Auth.dll. Keep the following information in mind when
you design how you will release your EWS Managed API application:

The EWS Managed API was designed such that you can download it and distribute
it with your application that targets an Exchange server. Alternatively, your
application can download the EWS Managed API.

You can use the EWS Managed API to communicate with an Exchange server
running Exchange Online, Exchange Online as part of Office 365, or an on-
premises version of Exchange starting with Exchange Server 2007.

In versions of the EWS Managed API starting with version 2.1, you can install the
API in the Global Assembly Cache (GAC). The MSI will automatically add the DLL to
the GAC and will be accessible on per computer basis, not on a per user basis.

The license terms are included in the EWS Managed API download. Review the terms for
the authoritative information about what you can do with the EWS Managed API.

See also
EWS client design overview for Exchange

EWS Managed API (download)


Instrumenting client requests for EWS
and REST in Exchange
Article • 09/15/2021 • 3 minutes to read

Learn about the HTTP headers in EWS and REST requests and responses that can help
you monitor and troubleshoot your Exchange application.

Has this ever happened to you? A user of your application reports an unexpected error.
You want to investigate, but you can't reproduce it. The error has disappeared for the
user, and you're left with very little actionable data. Frustrating, isn't it? Let's look at how
you can proactively prepare for this scenario and hopefully avoid frustration in the
future.

Add instrumentation to requests


We recommend that you add additional HTTP headers to your requests to facilitate
troubleshooting. You should keep a record of this information somewhere (for example,
in a log file) so that you can retrieve it later if you need to. This is helpful when
examining network traffic, and is also helpful if you contact Microsoft support for
assistance.

Table 1. Request headers for troubleshooting

HTTP header EWS Managed API equivalent Notes


(EWS)

User-Agent ExchangeService.UserAgent
Set this to a unique value that
identifies your client application.

Using the same value for all requests


that your application sends allows
Microsoft to help troubleshoot call
failures, should they arise.
HTTP header EWS Managed API equivalent Notes
(EWS)

client- ExchangeService.ClientRequestId
Set this to a different unique value
request-id for every request your application
sends.

We recommend that you use a


GUID. This unique identifier is
intended to be used to correlate
activities between two systems in
the event that something goes
wrong.

return-client- ExchangeService.ReturnClientRequestId Set this to true to signal to the


request-id Exchange server that it should return
the value of your client-request-id in
the corresponding response.

You can use this to correlate


requests and responses in network
traces or EWS Managed API traces.

X- ExchangeService.SendClientLatencies
Used to report EWS latencies to
ClientStatistics Microsoft if your application is
accessing Exchange Online or
Exchange Online as part of Office
365.

Log information from responses


Just as your client can add additional instrumentation to the requests it sends, Exchange
adds additional instrumentation to the responses in the form of HTTP headers. Your
client should capture this information to go along with the request instrumentation
information.

7 Note

If you are using the EWS Managed API, there is no direct equivalent for the HTTP
headers. However, all HTTP response headers can be accessed via the
ExchangeService.HttpResponseHeaders property.

Table 2. HTTP response headers

HTTP header Description


HTTP header Description

request-id A server-generated ID for the request that corresponds to this response.

client-request- The value of the client-request-id header in the request.

id
This header is only present if the request contains the return-client-request-id
header with a value of true.

X-FEServer The FQDN of the Client Access server that processed the request.

X- The FQDN of the mailbox server that processed the request.


TargetBEServer

X-DiagInfo Additional diagnostic information, depending on the request.

x-ms- This header is only applicable if OAuth authentication is used in the request.

diagnostics
It contains an explicit error code that specifies why an OAuth authentication
failed.

It takes the following format: errorId;reason="reason"error_type="error type"

The reason field is a human-readable description of the error.

The errorId field is an integer, and the error_type field is the string
representation of that integer, as follows:

2000000: invalid_signature
2000001: invalid_token
2000002: token_expired
2000003: invalid_resource
2000004: invalid_tenant
2000005: invalid_user
2000006: invalid_client
2000007: internal_error
2000008: invalid_grant

Report EWS latency to Microsoft


If your application uses the EWS Managed API or EWS to connect to Exchange Online,
you can report latency in EWS requests directly to Microsoft. The information is passed
via the X-ClientStatistics request header. If you are using the EWS Managed API, all you
have to do is set the ExchangeService.SendClientLatencies property to true. If you are
using EWS, you'll need to measure the time between issuing a request and receiving a
response, then add the X-ClientStatistics header to the next EWS request your
application sends, using the following format.
X-ClientStatistics: MessageId=<value of request-id header>,ResponseTime=<time in

milliseconds>,SoapAction=<EWS operation>

We maintain reports for these latencies and use them to continuously improve EWS
services in Exchange Online.

Next steps
After you've added client instrumentation to your application, you're better prepared if
something goes wrong. If that happens, you can use your instrumentation data to
troubleshoot your application.

See also
EWS client design overview for Exchange
Trace requests and responses to troubleshoot EWS Managed API applications
Tools and resources for troubleshooting EWS applications for Exchange
Develop web service clients for
Exchange
Article • 09/14/2022 • 2 minutes to read

Find information to help you develop EWS and web service client applications for
Exchange.

The articles in this section explain how to use EWS and web services in your Exchange
client applications for Exchange Online, Exchange Online as part of Office 365, and on-
premises versions of Exchange starting with Exchange 2013, and provide examples that
show you how to perform specific tasks.

In this section
Archiving in EWS in Exchange

Attachments and EWS in Exchange

Calendars and EWS in Exchange

Delegate access and EWS in Exchange

Distribution groups and EWS in Exchange

eDiscovery in EWS in Exchange

Email and EWS in Exchange

Folders and items in EWS in Exchange

Identifiers in Exchange

Impersonation and EWS in Exchange

Inbox management and EWS in Exchange

Notification subscriptions, mailbox events, and EWS in Exchange

People and contacts in EWS in Exchange

Persistent application settings in EWS in Exchange

Properties and extended properties in EWS in Exchange


Property sets and response shapes in EWS in Exchange

Public folder access with EWS in Exchange

Search and EWS in Exchange

Mailbox synchronization and EWS in Exchange

Time zones and EWS in Exchange

Tools and resources for troubleshooting EWS applications for Exchange

Verifying the results of an EWS or EWS Managed API call

See also
Explore the EWS Managed API, EWS, and web services in Exchange
Start using web services in Exchange
EWS client design overview for Exchange
Web services reference for Exchange
Archiving in EWS in Exchange
Article • 09/15/2021 • 2 minutes to read

Learn about archiving in EWS in Exchange.

Archive mailboxes are secondary mailboxes that are associated with a user. Archive
mailboxes are typically used to manage email storage limits. For example, older email
items might periodically be moved from the Inbox to the archive mailbox.

Exchange Online, Exchange Online as part of Office 365, and Exchange Server 2013
introduce two new Exchange Web Services (EWS) operations that you can use to archive
a set of mail items from a primary mailbox. Archiving Inbox items in this way preserves
the folder hierarchy of the items. In addition, archive mailboxes can now be stored either
locally on a client, or remotely, in a way that is mostly opaque to a user, by using a
folder path to point to the contents of the archive.

Archiving operations in EWS


The following table lists the archiving operations that were introduced in Exchange
2013.

Operation name Description

ArchiveItem
Moves an item from the primary mailbox to the archive mailbox.

CreateFolderPath
Creates a URI that points to the storage location for the archive mailbox.

See also
Develop web service clients for Exchange

Start using web services in Exchange

EWS client design overview for Exchange


Attachments and EWS in Exchange
Article • 09/14/2022 • 3 minutes to read

Learn about attachments and how your EWS Managed API or EWS in Exchange client
represents them.

Usually, attachments are associated with email items, but in fact, all EWS items — email
messages, calendar items, contacts, tasks — can include attachments.

Types of attachments
EWS categorizes attachments into two groups: file attachments and item attachments.

Item attachments: Strongly-typed EWS items, such as email messages and


calendar items, that are attached to another strongly-typed EWS item. Any
strongly-typed item that can be created by using the EWS Managed API or EWS
can be used as an item attachment. The content of an item attachment is the
strongly-typed item, which provides easy access to all its properties. Item
attachments can have their own item attachments, so a hierarchy of item
attachments (or nesting of attachments) is possible.

File attachments: Any file, such as a .txt, .jpg, .zip, .pdf, or even a .msg file. A file
attachment only has a few properties, one of which is the base-64 encoded
content of the file.

Reference attachments: Any attachment that is referenced by a file provider, such


as a file located in the cloud. An attachment can be from multiple providers.

When you add or retrieve attachments from an item, you'll do it differently depending
on whether it's a file attachment or an item attachment. For example, to add a file
attachment to an item, you can just pass in the location of the file. To add an existing
item as an item attachment, you actually have to copy the properties or the MIME
content of the existing item to a new item attachment; you can't just bind to the existing
item. So distinguishing between the two types of attachments is important. More details
about the differences between item attachments and file attachments are discussed in
the articles In this section.

How are attachments represented


programmatically?
Attachments are stored in a collection on the EWS item. The attachments collection is
made up of file attachments and/or item attachments. Metadata about the attachment
collection is available when you get an item by using the EWS Managed API Item.Bind
method or the EWS GetItem operation, but additional calls are required to actually
retrieve the contents of the attachments.

Table 1. Item metadata about attachments

Metadata entity EWS Managed API EWS element


property

Attachment indicator (does not flag inline Item.HasAttachments


HasAttachments
attachments)

Attachment collection Item.Attachments


Attachments

Attachment ID Attachment.Id
AttachmentId

Table 2. Attachment entities

Attachment type EWS Managed API class EWS element

File attachment FileAttachment


FileAttachment

Item attachment ItemAttachment


ItemAttachment

ItemAttachment<TItem>

Reference ReferenceAttachmentType complexType ReferenceAttachment


attachment (EWS)

Inline attachments
Inline attachments are a special breed of attachment. Both file attachments and item
attachments can be inline attachments. An inline attachment appears as part of the
body content and retains its position relative to the rest of the content in the item.

An attachment is an inline attachment if the EWS Managed API IsInline property or


the EWS IsInline element is set to true. Inline attachments use the following optional
properties and elements to identify the location of an inline attachment:

EWS Managed API — ContentId or ContentLocation properties.

EWS — ContentId or ContentLocation element.

Note that the EWS Managed API HasAttachments property and the EWS
HasAttachments element do not reflect the existence of inline attachments, and that's
why inline attachments are also called hidden attachments. So if you set the EWS
Managed API IsInline property or the EWS IsInline element to true, and the item has
no other attachments, HasAttachments will be set to false. If your client uses
HasAttachments to populate an attachment indicator or icon on an email, be aware that
the icon will not appear for emails with inline attachments.

In this section
Add attachments by using EWS in Exchange

Get attachments by using EWS in Exchange

Delete attachments by using EWS in Exchange

See also
Develop web service clients for Exchange

Folders and items in EWS in Exchange

Email and EWS in Exchange


Add attachments by using EWS in
Exchange
Article • 01/15/2020 • 13 minutes to read

Learn how to create new items with attachments, or add attachments to existing items
by using the EWS Managed API or EWS in Exchange.

You can add file attachments or item attachments to new or existing items by using the
EWS Managed API or EWS. If you are using the EWS Managed API, you use the same
method to add attachments to new or existing items; however, the method changes if
you're using a file or item attachment. Conversely, if you are using EWS, you use the
same operation to add either a file or item attachment to an item, but the operation
changes if you're adding the attachment to a new or existing item.

Table 1. EWS Managed API methods and EWS operations for adding attachments

Task EWS Managed API method EWS operation

Add a file attachment to a AttachmentCollection.AddFileAttachment


CreateItem for a
new or existing email new email
CreateAttachment
to add to an
existing email

Add an item attachment to AttachmentCollection.AddItemAttachment CreateItem for a


a new or existing email new email
CreateAttachment
to add to an
existing email

Create an email with file and item attachments


by using the EWS Managed API
The following code example shows how to create an email with multiple file
attachments and an item attachment by:

1. Using the EmailMessage object to create an email message.

2. Using the AttachmentCollection.AddFileAttachment and


AttachmentCollection.AddItemAttachment methods to add attachments to the
message.
3. Using the EmailMessage.SendAndSaveCopy method to send the message to the
recipients and save the message in the Sent Items folder.

This code example shows the four ways in which a file attachment can be added to an
item by using the EWS Managed API:

By using a fully qualified file location.

By using a fully qualified file location and a new attachment name.

By using a byte array.

By using a stream.

Note that the item attachment in this example is created at the same time as the email
message. To add an existing email message as an item attachment, see Add an existing
item to a new email by using the MimeContent and the EWS Managed API.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

C#

public static void CreateEmailWithAttachments(ExchangeService service)

// Create an email message and set properties on the message.

EmailMessage message = new EmailMessage(service);

// Set properties on the email message.

message.Subject = "Message with Attachments";

message.Body = "This message contains four file attachments

and one message item attachment.";

message.ToRecipients.Add("[email protected]");

message.ToRecipients.Add("[email protected]");

// Add a file attachment by using the fully qualified location of the


file.

message.Attachments.AddFileAttachment("C:\\temp\\FileAttachment.txt");

// Add a file attachment by using the fully qualified string name,

// and specify the name of the attachment as it will appear in the


email.

// The new name of the file attachment is SecondAttachment.txt.

message.Attachments.AddFileAttachment("SecondAttachment.txt",
"C:\\temp\\FileAttachment2.txt");
// Add a file attachment by using a byte array.

// In this example, theBytes is the byte array that represents the


content of the image file to attach.

byte[] theBytes = File.ReadAllBytes("C:\\Temp\\Tulips.jpg");

// The byte array file attachment is named ThirdAttachment.jpg.

message.Attachments.AddFileAttachment("ThirdAttachment.jpg", theBytes);

// Add a file attachment by using a stream.

FileStream theStream = new FileStream("C:\\temp\\FileAttachment4.txt",


FileMode.OpenOrCreate);

// The streamed file attachment is named FourthAttachment.txt.


message.Attachments.AddFileAttachment("FourthAttachment.txt",
theStream);

// Add an email message as an item attachment and set properties on the


item.

ItemAttachment<EmailMessage> itemAttachment =
message.Attachments.AddItemAttachment<EmailMessage>();

itemAttachment.Name = "Attached Message Item";

itemAttachment.Item.Subject = "Message Item Subject";

itemAttachment.Item.Body = "Message Item Body";

itemAttachment.Item.ToRecipients.Add("[email protected]");

itemAttachment.Item.ToRecipients.Add("[email protected]");

// Send the mail and save a copy in the Sent Items folder.

// This method results in a CreateItem and SendItem call to EWS.

message.SendAndSaveCopy();

Create an email with file and item attachments


by using EWS
The following code example shows how to use the CreateItem operation to create an
email message with four file attachments and one item attachment. This is also one of
the XML requests that the EWS Managed API sends when you create an email with file
and item attachments.

Note that the item attachment in this example is created at the same time as the email
message. To add an existing email message as an item attachment, see Add an existing
item to a new email by using the MimeContent and the EWS Managed API.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SaveOnly">

<m:Items>

<t:Message>

<t:Subject>Message with Attachments</t:Subject>

<t:Body BodyType="HTML">This message contains four file


attachments

and one message item attachment.</t:Body>

<t:Attachments>

<t:FileAttachment>

<t:Name>FileAttachment.txt</t:Name>

<t:IsInline>false</t:IsInline>

<t:IsContactPhoto>false</t:IsContactPhoto>
<t:Content>VGhpcyBpcyBhIGZpbGUgYXR0YWNobWVudC4=</t:Content>

</t:FileAttachment>

<t:FileAttachment>

<t:Name>SecondAttachment.txt</t:Name>

<t:IsInline>false</t:IsInline>

<t:IsContactPhoto>false</t:IsContactPhoto>
<t:Content>VGhpcyBpcyB0aGUgc2Vjb25kIGZpbGUgYXR0YWNobWVudC4=
</t:Content>

</t:FileAttachment>

<t:FileAttachment>

<t:Name>ThirdAttachment.jpg</t:Name>

<t:IsInline>false</t:IsInline>

<t:IsContactPhoto>false</t:IsContactPhoto>
<t:Content>nAoAXNIZMVEZs5GKhdzRcLH/9k=</t:Content>

</t:FileAttachment>

<t:FileAttachment>

<t:Name>FourthAttachment.txt</t:Name>

<t:IsInline>false</t:IsInline>

<t:IsContactPhoto>false</t:IsContactPhoto>
<t:Content>obWVudC4=…</t:Content>

</t:FileAttachment>

<t:ItemAttachment>

<t:Name>Attached Message Item</t:Name>

<t:IsInline>false</t:IsInline>

<t:Message>

<t:Subject>Message Item Subject</t:Subject>

<t:Body BodyType="HTML">Message Item Body</t:Body>

<t:ToRecipients>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</t:ItemAttachment>

</t:Attachments>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError, which indicates that the email and
the attachments were created successfully. The ItemId of the newly created message
and the AttachmentId values for each of the attachments is also included in the
response. The values of some attributes have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="939"

MinorBuildNumber="12"

Version="V2_11"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:CreateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:Message>
<t:ItemId Id="upV4AAA="

ChangeKey="CQAAABYAAAAFI5DJmZv+TLtyLOLIF1S5AAAXuktU"
/>

<t:Attachments>

<t:FileAttachment>

<t:AttachmentId Id="6ts3NuI=" />

</t:FileAttachment>

<t:FileAttachment>

<t:AttachmentId Id="gOIZx1I=" />

</t:FileAttachment>

<t:FileAttachment>

<t:AttachmentId Id="esRan5I=" />

</t:FileAttachment>

<t:FileAttachment>

<t:AttachmentId Id="t7sU6s=" />

</t:FileAttachment>

<t:ItemAttachment>

<t:AttachmentId Id="XgDCggM=" />

</t:ItemAttachment>

</t:Attachments>

</t:Message>

</m:Items>

</m:CreateItemResponseMessage>

</m:ResponseMessages>

</m:CreateItemResponse>

</s:Body>

</s:Envelope>

To send this newly created message, call the SendItem operation.

Add an existing item to a new email by using


the MimeContent and the EWS Managed API
To add an existing item as an item attachment to another item, you need to create a
new item attachment and copy the content of the existing item to the new item. There
are two ways to do this:

1. If you're working with email messages specifically, you can copy the value of the
MimeContent property from the email into the newly created item attachment.
You will lose some properties during this process, such as follow up flags and
categories, but it works great for standard email messages.

2. If you need full fidelity for all item types, you can bind to an existing item and copy
all the properties and extended properties into the new attachment.

The following code example shows the first approach, copying the MimeContent into
the new item attachment. Following this example is a procedure that shows how you
can modify the code to use the second approach.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server, and that the itemId is the ItemId of the
item to attach.

C#

public static void CreateEmailExistingItem(ExchangeService service, ItemId


itemId)

// This method results in a GetItem call to EWS.

EmailMessage msgToAttach = EmailMessage.Bind(service,itemId,

new PropertySet(ItemSchema.MimeContent, ItemSchema.Subject));

// Create an email message and set properties on the message.

EmailMessage message = new EmailMessage(service);

message.Subject = "Message with Item Attachment (MimeContent)";

message.Body = "The attachment to this message was created by copying

the MimeContent from the original message and adding it to a new


item attachment.";

message.ToRecipients.Add("[email protected]");

// Add an email message item attachment and set properties on the item.

ItemAttachment<EmailMessage> itemAttachment =
message.Attachments.AddItemAttachment<EmailMessage>();

itemAttachment.Item.MimeContent = msgToAttach.MimeContent;

itemAttachment.Name = msgToAttach.Subject;

// Send the mail and save a copy in the Sent Items folder.

// This method results in a CreateItem and SendItem call to EWS.

message.SendAndSaveCopy();

To modify this example to copy each of the properties on the existing item into the new
item attachment, do the following:

1. Change the property set to include PropertySet.FirstClassProperties and any


additional properties or extended properties you need.

C#

// Add additional properties to the PropertySet.

EmailMessage msgToAttach = EmailMessage.Bind(service, itemId, new


PropertySet(PropertySet.FirstClassProperties));

2. Remove the following line, because you do not need the MimeContent property.

C#

itemAttachment.Item.MimeContent = msgToAttach.MimeContent;

3. Repeat this line for each property to copy from the existing item to the new
attachment. Do not copy the ItemId into the new item attachment because that's a
read-only property.

C#

itemAttachment.Item.Subject = msgToAttach.Subject;

4. Set the PidTagMessageFlags (0x0E070003) property on the attachment to Sent.

C#
ExtendedPropertyDefinition sent = new ExtendedPropertyDefinition(3591,
MapiPropertyType.Integer);

msgToAttach.Item.SetExtendedProperty(sent, "1");

Add an existing item to a new email by using


the MimeContent and EWS
There are two ways to add an existing item to a new item:

1. If you're working with email messages specifically, you can copy the value of the
MimeContent element from the email into the newly created item attachment.
You will lose some properties during this process, such as follow up flags and
categories, but it works great for standard email messages.

2. If you need full fidelity for all item types, you can bind to an existing item and copy
all the properties and extended properties into the new attachment.

The following code example shows how to use the MimeContent element to copy the
content of the original item into the MimeContent value of the new item attachment.
The example uses the following operations:

1. GetItem — To get the MimeContent and Subject of the message that will
become the item attachment on the new message.

2. CreateItem — To create the new email message.

3. CreateAttachment — To create the new attachment, using the MimeContent and


Subject retrieved by the GetItem operation.

4. SendItem — To send and save the message.

The example starts by retrieving the MimeContent and the Subject of the existing item.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:MimeContent" />

<t:FieldURI FieldURI="item:Subject" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="jCrTAAA=" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The server responds to the GetItem request with a GetItemResponse message that
includes a ResponseCode value of NoError, which indicates that the email was
retrieved successfully, and the MimeContent and Subject of the email.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="944"

MinorBuildNumber="11"

Version="V2_12"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:Message>
<t:MimeContent CharacterSet="UTF-8">tDQe/Eo=…</t:MimeContent>

<t:ItemId Id="jCrTAAA="

ChangeKey="CQAAABYAAAAFI5DJmZv+TLtyLOLIF1S5AAAZi+7u"
/>

<t:Subject>Play tennis?</t:Subject>

</t:Message>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

Next, call the CreateItem operation to create the new email.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SaveOnly">

<m:Items>

<t:Message>

<t:Subject>Message with Item Attachment (MimeContent)</t:Subject>

<t:Body BodyType="HTML">The attachment to this message was created


by copying the MimeContent from the original message and adding it to a new
item attachment.</t:Body>

<t:ToRecipients>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError, which indicates that the email was
created successfully.

Next, create the new item attachment by using the MimeContent and Subject retrieved
by the GetItem operation. The value of the ParentItemId element is populated by
using the ItemId value returned in the CreateItem response.

XML
<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

</soap:Header>

<soap:Body>

<m:CreateAttachment>

<m:ParentItemId Id="jDKsAAA=" />

<m:Attachments>

<t:ItemAttachment>

<t:Name>Play tennis?</t:Name>

<t:IsInline>false</t:IsInline>

<t:Message>

<t:MimeContent CharacterSet="UTF-8">tDQe/Eo=…</t:MimeContent>

</t:Message>

</t:ItemAttachment>

</m:Attachments>

</m:CreateAttachment>

</soap:Body>

</soap:Envelope>

The server responds to the CreateAttachment request with a


CreateAttachmentResponse message that includes a ResponseCode value of
NoError, which indicates that the attachment was created successfully, and the
AttachmentId of the newly created attachment.

Now that the new message has been created, and the item was attached, you can send
this newly created message by calling the SendItem operation.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

</soap:Header>

<soap:Body>

<m:SendItem SaveItemToFolder="true">

<m:ItemIds>

<t:ItemId Id="jDKsAAA="

ChangeKey="CQAAABYAAAAFI5DJmZv+TLtyLOLIF1S5AAAZi/q/" />

</m:ItemIds>

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="sentitems" />

</m:SavedItemFolderId>

</m:SendItem>

</soap:Body>

</soap:Envelope>

The server responds to the SendItem request with a SendItemResponse message that
includes a ResponseCode value of NoError, which indicates that the email was sent
successfully.

Create an email with an inline attachment by


using the EWS Managed API
The following code example shows how to create an email with an inline attachment by:

1. Using the EmailMessage object to create an email message.

2. Setting the EmailMessage.Body property to an HTML body that includes an


inline attachment.

3. Using the AttachmentCollection.AddFileAttachment method to add the


attachment to the message.

4. Using the EmailMessage.SendAndSaveCopy method to send the message to the


recipient and save the message in the Sent Items folder.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

C#

public static void CreateEmailWithInlineAttachment(ExchangeService service)

// Create the HTML body with the content identifier of the attachment.

string html = @"<html>

<head>

</head>

<body>

<img width=100 height=100 id=""1""


src=""cid:Party.jpg"">

</body>

</html>";

// Create the email message.

EmailMessage message = new EmailMessage(service);

message.Subject = "Inline Attachment";

message.Body = new MessageBody(BodyType.HTML, html);

message.ToRecipients.Add("[email protected]");

// Add the attachment to the local copy of the email message.

string file = @"C:\Temp\Party.jpg";

message.Attachments.AddFileAttachment("Party.jpg", file);

message.Attachments[0].IsInline = true;

message.Attachments[0].ContentId = "Party.jpg";

// Send the mail and save a copy in the Sent Items folder.

// This method results in a CreateItem and SendItem call to EWS.

message.SendAndSaveCopy();

Create an email with an inline attachment by


using EWS
The following code example shows how to use the CreateItem operation to create an
email message with an inline file attachment. The BodyType attribute of the Body
element indicates that the content is in HTML format and includes the image source.
This is also one of the XML requests that the EWS Managed API sends when you use the
EWS Managed API to create an email with an inline attachment.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SaveOnly">

<m:Items>

<t:Message>

<t:Subject>Inline Attachment</t:Subject>

<t:Body BodyType="HTML">

&amp;lt;html&amp;gt;

&amp;lt;head&amp;gt;

&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;img width=100 height=100 id="1"


src="cid:Party.jpg"&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
</t:Body>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError, which indicates that the email was
created successfully, and the ItemId of the newly created message.

To send this newly created message, call the SendItem operation.

Add an attachment to an existing email by


using the EWS Managed API
The following code example shows how to add an attachment to an existing email by:

1. Using the EmailMessage.Bind method to bind to an existing email message.

2. Adding a file attachment to the message by using the AddFileAttachment method.

3. Saving the updates by calling the EmailMessage.Update method.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

XML

public static void AddAttachmentToExisting(ExchangeService service, ItemId


itemId)

// This method results in a GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, itemId);

message.Attachments.AddFileAttachment("C:\\temp\\FileAttachment.txt");

// This method results in a CreateAttachment call to EWS.

message.Update(ConflictResolutionMode.AlwaysOverwrite);

Add an attachment to an existing email by


using EWS
The following code example shows how to use the CreateAttachment operation to
add a file attachment to an existing email message. This is also one of the XML requests
that the EWS Managed API sends when you use the EWS Managed API to add an
attachment to an existing email.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Central Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:CreateAttachment>

<m:ParentItemId Id="uqE2AAA=" />

<m:Attachments>

<t:FileAttachment>

<t:Name>FileAttachment.txt</t:Name>

<t:Content>VGhpcyBpcyBhIGZpbGUgYXR0YWNobWVudC4=</t:Content>

</t:FileAttachment>

</m:Attachments>

</m:CreateAttachment>

</soap:Body>

</soap:Envelope>

The server responds to the CreateAttachment request with a


CreateAttachmentResponse message that includes a ResponseCode value of
NoError, which indicates that the attachment was created successfully, and the
AttachmentId of the newly created attachment.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="939"

MinorBuildNumber="12"

Version="V2_11"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:CreateAttachmentResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:CreateAttachmentResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Attachments>

<t:FileAttachment>

<t:AttachmentId Id="yRLhCh8="

RootItemId="uqE2AAA="

RootItemChangeKey="CQAAABYAAAAFI5DJmZv+TLtyLOLIF1S5AAAXulcf" />

</t:FileAttachment>

</m:Attachments>

</m:CreateAttachmentResponseMessage>

</m:ResponseMessages>

</m:CreateAttachmentResponse>

</s:Body>

</s:Envelope>

See also
Attachments and EWS in Exchange

Add attachments by using EWS in Exchange

Delete attachments by using EWS in Exchange

Get attachments by using EWS in Exchange

Send email messages by using EWS in Exchange


Get attachments by using EWS in
Exchange
Article • 01/15/2020 • 5 minutes to read

Learn how to get attachments from EWS items by using the EWS Managed API or EWS
in Exchange.

You can get attachments from an item by using the EWS Managed API or EWS. Because
the initial call to get an item only includes metadata about the attachment collection on
the item, retrieving attachments is always a two-step process. First, retrieve the item.
Next, retrieve the attachment.

Table 1. EWS Managed API methods and EWS operations for adding attachments

Task EWS Managed API method EWS operation

Get item Item.Bind followed by GetItem followed by


attachments ItemAttachment.Load
GetAttachment

Get file Item.Bind followed by GetItem followed by


attachments FileAttachment.Load
GetAttachment

Get attachments from an email by using the


EWS Managed API
The following code example shows how to get an EmailMessage object by using the
Bind method, then iterate through the attachment collection and call the
FileAttachment.Load or ItemAttachment.Load method on each attachment as
appropriate. Each file attachment is saved to the C:\temp\ folder, and each item
attachment is loaded into memory. For information about how to save an item
attachment, see Save an attached email by using the EWS Managed API.

This example assumes that service is a valid ExchangeService object, that itemId is the
ItemId of the message from which attachments will be retrieved, and that the user has
been authenticated to an Exchange server.

C#

public static void GetAttachmentsFromEmail(ExchangeService service, ItemId


itemId)

// Bind to an existing message item and retrieve the attachments


collection.

// This method results in an GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, itemId, new


PropertySet(ItemSchema.Attachments));

// Iterate through the attachments collection and load each attachment.

foreach (Attachment attachment in message.Attachments)

if (attachment is FileAttachment)

FileAttachment fileAttachment = attachment as FileAttachment;

// Load the attachment into a file.

// This call results in a GetAttachment call to EWS.

fileAttachment.Load("C:\\temp\\" + fileAttachment.Name);

Console.WriteLine("File attachment name: " +


fileAttachment.Name);

else // Attachment is an item attachment.

ItemAttachment itemAttachment = attachment as ItemAttachment;

// Load attachment into memory and write out the subject.

// This does not save the file like it does with a file
attachment.

// This call results in a GetAttachment call to EWS.

itemAttachment.Load();

Console.WriteLine("Item attachment name: " +


itemAttachment.Name);

Get an attachment from an email by using EWS


To get attachments by using EWS, you first need to retrieve the message and the
attachment collection to get the AttachmentId (GetAttachment and
DeleteAttachment) of the attachment to retrieve. After you have one or more
AttachmentId values to retrieve, call the GetAttachment operation to load all the
properties for the attachment.

The following code example shows how to use the GetItem operation to get an email
message and the collection of attachments on the message. This is also the first XML
request that the EWS Managed API sends when you use the EWS Managed API to get all
attachments from an email. The values of some attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange207_SP1" />

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Attachments" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="ERu/AAA=" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The server responds to the GetItem request with a GetItemResponse message that
includes a ResponseCode value of NoError, which indicates that the email was
retrieved successfully, and the AttachmentId values of the existing attachments.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="939"

MinorBuildNumber="12"

Version="V2_11"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:Message>
<t:ItemId Id="ERu/AAA="

ChangeKey="CQAAABYAAAAFI5DJmZv+TLtyLOLIF1S5AAAYEMnd"
/>

<t:Attachments>

<t:FileAttachment>

<t:AttachmentId Id="5zTzlqU=" />

<t:Name>FileAttachment.txt</t:Name>

<t:Size>212</t:Size>

<t:LastModifiedTime>2014-05-
14T17:59:30</t:LastModifiedTime>

<t:IsInline>false</t:IsInline>

<t:IsContactPhoto>false</t:IsContactPhoto>

</t:FileAttachment>

<t:ItemAttachment>

<t:AttachmentId Id="Ktum21o=" />

<t:Name>Attached Message Item</t:Name>

<t:Size>3063</t:Size>

<t:LastModifiedTime>2014-05-
14T17:59:30</t:LastModifiedTime>

<t:IsInline>false</t:IsInline>

</t:ItemAttachment>

</t:Attachments>

</t:Message>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

Now that you have the AttachmentId values, call GetAttachment on each
attachment you want to retrieve.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:GetAttachment>

<m:AttachmentIds>
<t:AttachmentId Id="5zTzlqU=" />

</m:AttachmentIds>

</m:GetAttachment>

</soap:Body>

</soap:Envelope>

When retrieving an item attachment, the server responds to the GetAttachment request
with a GetAttachmentResponse message that includes a ResponseCode value of
NoError, which indicates that the attachment was retrieved successfully, and all the
elements for the attached item, which in this case is an email message.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="939"

MinorBuildNumber="12"

Version="V2_11"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetAttachmentResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetAttachmentResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Attachments>

<t:ItemAttachment>

<t:AttachmentId Id="Ktum21o=" />


<t:Name>Attached Message Item</t:Name>

<t:Message>

<t:ItemClass>IPM.Note</t:ItemClass>

<t:Subject>Message Item Subject</t:Subject>

<t:Body BodyType="HTML">&amp;lt;meta http-equiv="Content-


Type"

content="text/html; charset=utf-8"&amp;gt;Message Item


Body</t:Body>

<t:Size>2859</t:Size>

<t:IsSubmitted>false</t:IsSubmitted>

<t:IsDraft>true</t:IsDraft>

<t:IsFromMe>false</t:IsFromMe>

<t:IsResend>false</t:IsResend>

<t:IsUnmodified>false</t:IsUnmodified>

<t:DateTimeCreated>2014-05-14T17:59:37Z</t:DateTimeCreated>

<t:ResponseObjects>

<t:ForwardItem />

</t:ResponseObjects>

<t:DisplayCc />

<t:DisplayTo>primary; emaildelegate</t:DisplayTo>

<t:HasAttachments>false</t:HasAttachments>

<t:Culture>en</t:Culture>

<t:EffectiveRights>

<t:CreateAssociated>false</t:CreateAssociated>

<t:CreateContents>false</t:CreateContents>

<t:CreateHierarchy>false</t:CreateHierarchy>

<t:Delete>true</t:Delete>

<t:Modify>true</t:Modify>

<t:Read>true</t:Read>

</t:EffectiveRights>

<t:LastModifiedName>primary</t:LastModifiedName>

<t:LastModifiedTime>2014-05-
14T17:59:30Z</t:LastModifiedTime>

<t:IsAssociated>false</t:IsAssociated>

<t:WebClientReadFormQueryString>?
ItemID=AAMk3D&amp;amp;exvsurl=1&amp;amp;viewmodel=

ReadMessageItem</t:WebClientReadFormQueryString>

<t:ConversationId Id="AAQkADIwM2ZlM2ZlLWMwYjctNDg2N/Rc+d0="
/>

<t:ToRecipients>

<t:Mailbox>

<t:Name>primary</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>Mailbox</t:MailboxType>

</t:Mailbox>

<t:Mailbox>

<t:Name>emaildelegate</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>Mailbox</t:MailboxType>

</t:Mailbox>

</t:ToRecipients>

<t:IsReadReceiptRequested>false</t:IsReadReceiptRequested>

<t:ConversationIndex>AQHPb55BxR5Fm0Arx0yY4xbL9Fz53Q==
</t:ConversationIndex>

<t:ConversationTopic>Message Item
Subject</t:ConversationTopic>

<t:IsRead>true</t:IsRead>

</t:Message>

</t:ItemAttachment>

</m:Attachments>

</m:GetAttachmentResponseMessage>

</m:ResponseMessages>

</m:GetAttachmentResponse>

</s:Body>

</s:Envelope>

When retrieving a file attachment, the server responds to the GetAttachment request
with a GetAttachmentResponse message that includes a ResponseCode value of
NoError, which indicates that the attachment was retrieved successfully, and all the
elements of the file attachment.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="939"

MinorBuildNumber="12"

Version="V2_11"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetAttachmentResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetAttachmentResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Attachments>

<t:FileAttachment>

<t:AttachmentId Id="5zTzlqU=" />


<t:Name>FileAttachment.txt</t:Name>

<t:Content>VGhpcyBpcyBhIGZpbGUgYXR0YWNobWVudC4=</t:Content>

</t:FileAttachment>

</m:Attachments>

</m:GetAttachmentResponseMessage>

</m:ResponseMessages>

</m:GetAttachmentResponse>

</s:Body>

</s:Envelope>

Save an attached email by using the EWS


Managed API
In order to save the contents of an email attachment using the EWS Managed API, you
need to save the MimeContent to a file. In doing so, you will lose any extended
properties set on the item, such as follow-up flags and categories. This example saves
the email attachment to the to the C:\temp\ folder.

Note that you cannot move or copy the item attachment to another folder because the
item attachment is not a strongly-typed item, so if you're trying to move an attachment
to a different folder, use the following code example and then import the file into a
different folder.

C#

public static void SaveEmailAttachment(ExchangeService service, ItemId


itemId)

// Bind to an existing message item and retrieve the attachments


collection.

// This method results in an GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, itemId, new


PropertySet(ItemSchema.Attachments));

foreach (Attachment attachment in message.Attachments)

if (attachment is ItemAttachment)

ItemAttachment itemAttachment = attachment as ItemAttachment;

itemAttachment.Load(ItemSchema.MimeContent);

string fileName = "C:\\Temp\\" + itemAttachment.Item.Subject +


".eml";

// Write the bytes of the attachment into a file.

File.WriteAllBytes(fileName,
itemAttachment.Item.MimeContent.Content);

Console.WriteLine("Email attachment name: "+


itemAttachment.Item.Subject + ".eml");

See also
Attachments and EWS in Exchange

Add attachments by using EWS in Exchange

Delete attachments by using EWS in Exchange


Delete attachments by using EWS in
Exchange
Article • 09/15/2021 • 5 minutes to read

Learn how to delete attachments from items by using the EWS Managed API or EWS in
Exchange.

You have a number of options when it comes to deleting file and item attachments from
items by using the EWS Managed API. You can delete all the attachments from the
message, delete by a file name, or delete by position in the collection. For each of these
options, there is an AttachmentCollection method.

Conversely, with EWS, no matter whether you're deleting all attachments from an item
or just one, the sequence of operations is same. Unlike the EWS Managed API, EWS
does not include separate operations to delete based on name or position in the
attachments array.

Table 1. EWS Managed API methods and EWS operations for deleting attachments

Task EWS Managed API method EWS operation

Delete all attachments from Item.Bind , followed by GetItem followed


an item. AttachmentCollection.Clear , followed by by
EmailMessage.Update
DeleteAttachment

Delete an attachment from Item.Bind , followed by GetItem followed


an item by name. AttachmentCollection.Remove , followed by
by EmailMessage.Update
DeleteAttachment

Delete an attachment from Item.Bind , followed by GetItem followed


an item by position in the AttachmentCollection.RemoveAt , by
collection. followed by EmailMessage.Update
DeleteAttachment

Delete all attachments from an email by using


the EWS Managed API
The following code example shows how to delete all attachments from an email by:

1. Using the EmailMessage.Bind method to bind to an existing email message and


retrieve the collection of Attachments .
2. Using the AttachmentCollection.Clear method to delete all the attachments from
the email.

3. Using the EmailMessage.Update method to save the changes.

This example assumes that service is a valid ExchangeService object, itemId is the
ItemId of the message from which attachments will be deleted, and that the user has
been authenticated to an Exchange server.

C#

public static void DeleteAllAttachments(ExchangeService service, ItemId


itemId)

// Bind to an existing message by using its item ID and requesting its


attachments collection.

// This method results in a GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, itemId, new


PropertySet(ItemSchema.Attachments));

// Delete all attachments from the message.

message.Attachments.Clear();

// Save the updated message.

// This method results in an DeleteAttachment call to EWS.

message.Update(ConflictResolutionMode.AlwaysOverwrite);

Delete an attachment by name from an email


by using the EWS Managed API
The following code example shows how delete an attachment by name by:

1. Using the EmailMessage.Bind method to bind to an existing email message and


retrieve the collection of Attachments .

2. Using the AttachmentCollection.Remove method to delete an attachment


named FileAttachment.txt.

3. Using the EmailMessage.Update method to save the changes.

This example assumes that service is a valid ExchangeService object, itemId is the
ItemId of the message from which the attachment will be deleted, and that the user
has been authenticated to an Exchange server.

C#
public static void DeleteNamedAttachments(ExchangeService service, ItemId
itemId)

// Bind to an existing message by using its item ID and requesting its


attachments collection.

// This method results in a GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, itemId, new


PropertySet(ItemSchema.Attachments));

// Iterate through the attachments collection and delete the attachment


named "FileAttachment.txt," if it exists.

foreach (Attachment attachment in message.Attachments)

if (attachment.Name == "FileAttachment.txt")

message.Attachments.Remove(attachment);

break;

// Save the updated message.

// This method results in an DeleteAttachment call to EWS.

message.Update(ConflictResolutionMode.AlwaysOverwrite);

Delete attachments by position by using the


EWS Managed API
The following code example shows how to delete an attachment by position by:

1. Using the EmailMessage.Bind method to bind to an existing email message and


retrieve the collection of Attachments and the EmailMessage.HasAttachments
property.

2. Using the AttachmentCollection.Remove method to delete the first attachment


in the collection.

3. Using the EmailMessage.Update method to save the changes.

This example assumes that service is a valid ExchangeService object, itemId is the
ItemId of the message from which the attachment will be deleted, and that the user
has been authenticated to an Exchange server.

C#

public static void DeleteAttachmentByPosition(ExchangeService service,


ItemId itemId)

// Bind to an existing message by using its item ID and requesting the


HasAttachments property and the attachments collection.

// This method results in a GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, itemId, new


PropertySet(EmailMessageSchema.HasAttachments, ItemSchema.Attachments));

// Remove attachments using the zero-based index position of the


attachment in the attachments collection.

if (message.HasAttachments)

message.Attachments.RemoveAt(0);

// Save the updated message.

// This method results in an DeleteAttachment call to EWS.

message.Update(ConflictResolutionMode.AlwaysOverwrite);

Delete attachments from an item by using EWS


To delete attachments by using EWS, you first need to retrieve the message and the
attachment collection to determine the AttachmentId (GetAttachment and
DeleteAttachment) of the attachment to delete. After you have one or more
AttachmentId values to delete, call the DeleteAttachment operation to remove the
specified attachments from the message.

The following code example shows how to use the GetItem operation to get an email
message and the collection of attachments on the message. This is also the first XML
request that the EWS Managed API sends when you use the EWS Managed API to delete
all attachments from an email. The values of some attributes are shortened for
readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Central Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Attachments" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="uqE1AAA=" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The server responds to the GetItem request with a GetItemResponse message that
includes a ResponseCode value of NoError, which indicates that the email was
retrieved successfully, and the AttachmentId values of the existing attachments.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="939"

MinorBuildNumber="12"

Version="V2_11"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:Message>
<t:ItemId Id="uqE1AAA="

ChangeKey="CQAAABYAAAAFI5DJmZv+TLtyLOLIF1S5AAAXulcd"
/>

<t:Attachments>

<t:FileAttachment>

<t:AttachmentId Id="IpHLObE=" />

<t:Name>FileAttachment.txt</t:Name>

</t:FileAttachment>

<t:FileAttachment>

<t:AttachmentId Id="QuHSSmY=" />

<t:Name>SecondAttachment.txt</t:Name>

</t:FileAttachment>

<t:FileAttachment>

<t:AttachmentId Id="qf2KoPo=" />

<t:Name>ThirdAttachment.jpg</t:Name>

</t:FileAttachment>

<t:FileAttachment>

<t:AttachmentId Id="NFQMnMc=" />

<t:Name>FourthAttachment.txt</t:Name>

</t:FileAttachment>

<t:ItemAttachment>

<t:AttachmentId Id="jJvbLXQ=" />

<t:Name>Attached Message Item</t:Name>

</t:ItemAttachment>

</t:Attachments>

</t:Message>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

After you determine which attachment to delete, call the DeleteAttachment operation
and include the AttachmentId values of the attachments to delete.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Central Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:DeleteAttachment>

<m:AttachmentIds>
<t:AttachmentId Id="IpHLObE=" />

<t:AttachmentId Id="QuHSSmY=" />

<t:AttachmentId Id="qf2KoPo=" />

<t:AttachmentId Id="NFQMnMc=" />

<t:AttachmentId Id="jJvbLXQ=" />

</m:AttachmentIds>

</m:DeleteAttachment>

</soap:Body>

</soap:Envelope>

The server responds to the DeleteAttachment request with a


DeleteAttachmentResponse message that includes a ResponseCode value of
NoError for each DeleteAttachmentResponseMessage , which indicates that each
attachment was deleted successfully. The values of some attributes are shortened for
readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="939"

MinorBuildNumber="12"

Version="V2_11"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:DeleteAttachmentResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:DeleteAttachmentResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootItemId RootItemId="uqE1AAA=" RootItemChangeKey="AAAXulck"


/>

</m:DeleteAttachmentResponseMessage>

<m:DeleteAttachmentResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootItemId RootItemId="uqE1AAA=" RootItemChangeKey="AAAXulck"


/>

</m:DeleteAttachmentResponseMessage>

<m:DeleteAttachmentResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootItemId RootItemId="uqE1AAA=" RootItemChangeKey="AAAXulck"


/>

</m:DeleteAttachmentResponseMessage>

<m:DeleteAttachmentResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootItemId RootItemId="uqE1AAA=" RootItemChangeKey="AAAXulck"


/>

</m:DeleteAttachmentResponseMessage>

<m:DeleteAttachmentResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootItemId RootItemId="uqE1AAA=" RootItemChangeKey="AAAXulck"


/>

</m:DeleteAttachmentResponseMessage>

</m:ResponseMessages>

</m:DeleteAttachmentResponse>

</s:Body>

</s:Envelope>

See also
Attachments and EWS in Exchange

Add attachments by using EWS in Exchange

Get attachments by using EWS in Exchange


Calendars and EWS in Exchange
Article • 09/14/2022 • 4 minutes to read

Learn about calendars, calendar folders and items, appointments, and meetings in
Exchange.

You're probably familiar with many of the calendar features in email clients like Outlook,
which enable you to track appointments, schedule meetings, check people's availability,
invite attendees, and change or cancel meetings.

Calendar-related features in Exchange are a little different than what you see in a client
like Outlook. Instead of displaying information, EWS in Exchange enables you to do
things like create, store, send, or change information. To use EWS to work with
calendars, you'll need to be familiar with concepts such as information storage, time,
recurrence, and message flow. More specifically, you'll need to be familiar with the
following:

Calendar folders, calendar items, and calendar views

Meeting requests, responses, scheduling, attendees, resources, rooms, and


availability

Time durations, time zones, and start and end times of meetings and
appointments

Recurring series, recurrence patterns, exceptions, and single instance appointments


and meetings

Fortunately, EWS and the EWS Managed API provide a rich set of operations and
methods that enable you to perform a wide range of calendar-related tasks. For
example, using the EWS Managed API, you can create a meeting and send invitations to
attendees with just a few lines of code, as shown in the following example.

C#

Appointment meeting = new Appointment(service);

// Set the properties on the meeting object to create the


meeting.

meeting.Subject = "Team building exercise";

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(2);

meeting.Location = "Conference Room 12";

meeting.RequiredAttendees.Add("[email protected]");

meeting.RequiredAttendees.Add("[email protected]");

meeting.OptionalAttendees.Add("[email protected]");

meeting.ReminderMinutesBeforeStart = 60;

// Send the meeting request

meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy);

Calendar folders and calendar items


Calendar folders contain calendar items. Calendar folders have a folder class of
IPF.Appointment, and can include only the items defined by the ItemClass EWS
Managed API property, which is associated with an Appointment Class object, or the
EWS CalendarItemType element.

Items in a Calendar folder are a little different from items in other folders in a mailbox
because occurrences in a recurring series and exceptions to a recurring series are not
actual items in the mailbox, but rather are stored internally as attachments to a recurring
master. Therefore, in order to retrieve all appointments in a given date range, you need
to use a calendar view. To learn more about retrieving appointments and calendar views,
see Get appointments and meetings by using EWS in Exchange.

Meetings and appointments


The essential difference between meetings and appointments is that meetings have
attendees, and appointments don't. Internally, Exchange uses the same object for both
meetings and appointments. You use the EWS Managed API Appointment class or the
EWS CalendarItem element to work with meetings and appointments.

Both appointments and meetings can be single instances or part of a recurring series,
but because appointments don't include attendees, rooms, or resources, they do not
require a message to be sent.

Because meetings include sending and responding to requests and updates, they
involve more than just accessing items in a Calendar folder. They also have an
associated workflow. Meetings must be scheduled when attendees are available, and
can also involve reserving a meeting room, or resources such as a projector or other
equipment.

The meeting workflow typically involves the following steps:

1. A meeting is created and populated with information such as start and end time,
location, and a message body.
2. A list of prospective attendees, resources, and rooms is created.
3. The availability status of attendees is checked.
4. A meeting request is sent to attendees.
5. Attendees reply to the meeting with their intention to attend or not. Attendees
may also propose a new time for the meeting.
6. Meetings can be canceled or updated, which typically trigger new messages to be
sent to attendees.

Calendars and time


Time-related functionality is integral to calendaring. Appointments and meetings have
start and end times, durations, and other time-related properties, such as the time at
which a message is created, sent, and received. Existing appointments and meetings can
be retrieved from a Calendar folder based on a start and end time. Recurring series have
beginnings and ends. And meetings occur within a given time zone, which is
increasingly important in a global economy.

Times are stored internally on an Exchange server in Coordinated Universal Time (UTC).
Exchange converts them to local time zone based on client settings. DateTime
properties are scoped to the computer's local time zone.

Recurring series
A recurring series of appointments or meetings is comprised of a recurring master, a set
of occurrence items, and optionally, a set of exception items. Recurrence information is
stored on the recurring master item. The RecurringMasterItemId EWS element is
associated with occurrences and exceptions in a series, or you can use the
Appointment.BindToRecurringMaster EWS Managed API method to get the recurring
master. Using an instance of a series, you can find all the elements and information
associated with the series.

Note that recurrence properties exist on all calendar items, but they are populated only
on recurring master items. In addition to an index of all occurrences in a series, the
recurring master has a reference to modified and deleted occurrences and the
recurrence pattern of a series (for example, daily, weekly, monthly, or yearly).

In this section
Create appointments and meetings by using EWS in Exchange 2013

Create all-day events by using EWS in Exchange


Get appointments and meetings by using EWS in Exchange

Update appointments and meetings by using EWS in Exchange

Delete appointments and cancel meetings by using EWS in Exchange

Get room lists by using EWS in Exchange

Get free/busy information by using EWS in Exchange

Propose a new meeting time by using EWS in Exchange

Process calendar items in batches in Exchange

Recurrence patterns and EWS

See also
Develop web service clients for Exchange
Start using web services in Exchange
EWS client design overview for Exchange
Create appointments and meetings by
using EWS in Exchange 2013
Article • 01/15/2020 • 6 minutes to read

Learn how to create appointments and meetings by using the EWS Managed API or
EWS in Exchange.

The essential difference between meetings and appointments is that meetings have
attendees, and appointments don't. Both appointments and meetings can be single
instances or part of a recurring series, but because appointments don't include
attendees, rooms, or resources, they do not require a message to be sent. Internally,
Exchange uses the same object for both meetings and appointments. You use the EWS
Managed API Appointment class or the EWS [CalendarItem]
(https://msdn.microsoft.com/library/Title Topic ID Project Name Writer Editor Publish
Preview.aspx) element to work with meetings and appointments.

Table 1. EWS Managed API methods and EWS operations for working with
appointments and meetings

EWS Managed API method EWS operation

Appointment.Save
CreateItem operation (calendar item)

Item.Bind
GetItem operation (calendar item)

Create an appointment by using the EWS


Managed API
The following code example shows how to use the Appointment object to create an
appointment, the Save method to save it to your calendar folder, and the Item.Bind
method to verify that the appointment was created.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

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));
Console.WriteLine("\nAppointment created: " + item.Subject + "\n");

After setting the properties on the appointment object, you save the appointment to the
calendar folder by using the appointment object's Save method.

Note that in the verification step, you use the item Id associated with the appointment
to verify that the appointment is in the calendar folder. As a best practice, limit the
properties returned by the server to only what you need — in this case, the
appointment's subject.

Create an appointment by using EWS


The request and response XML in the following examples correspond to calls made by
the EWS Managed API code in Create an appointment by using the EWS Managed API.
The request and response XML that verifies that the appointment items are in the
calendar folder are shown as well.

The following example shows the request XML when you use the CreateItem
operation to create an appointment.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:CreateItem SendMeetingInvitations="SendToNone">

<m:Items>

<t:CalendarItem>

<t:Subject>Tennis lesson</t:Subject>

<t:Body BodyType="HTML">Focus on backhand this week.</t:Body>

<t:ReminderDueBy>2013-09-19T14:37:10.732-07:00</t:ReminderDueBy>

<t:Start>2013-09-21T19:00:00.000Z</t:Start>

<t:End>2013-09-21T20:00:00.000Z</t:End>

<t:Location>Tennis club</t:Location>

<t:MeetingTimeZone TimeZoneName="Pacific Standard Time" />

</t:CalendarItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The following example shows the response XML that is returned by the CreateItem
operation.

7 Note

The ItemId and ChangeKey attributes have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="775" MinorBuildNumber="7" Version="V2_4"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:CreateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

</m:CreateItemResponseMessage>

</m:ResponseMessages>

</m:CreateItemResponse>

</s:Body>

</s:Envelope>

The following example shows the request XML that is generated when you use the
GetItem operation to verify that the appointment was created.

7 Note

The ItemId and ChangeKey attributes have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The following example shows the response XML that is returned by the GetItem
operation.

7 Note

The ItemId and ChangeKey attributes have been shortened for readability.

XML
<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="775" MinorBuildNumber="7" Version="V2_4"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:Subject>Tennis lesson</t:Subject>

</t:CalendarItem>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

Create a meeting by using the EWS Managed


API
When you create a meeting, in addition to saving an item to the calendar folder, you
also typically want to send meeting requests to attendees. The following code example
shows how to create a meeting and send meeting requests.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

Appointment meeting = new Appointment(service);

// Set the properties on the meeting object to create the meeting.

meeting.Subject = "Team building exercise";

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("[email protected]");

meeting.RequiredAttendees.Add("[email protected]");

meeting.OptionalAttendees.Add("[email protected]");

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(ItemSchema.Subject));
Console.WriteLine("\nMeeting created: " + item.Subject + "\n");

After setting the properties on the Appointment object, save the meeting to your
calendar folder by using the Save method. When you set the SendInvitationsMode
enumeration value to SendOnlyToAll or SendToAllAndSaveCopy, invitations are sent to
attendees.

Use the item Id associated with the meeting to verify that it was saved in the calendar
folder. As a best practice, limit the properties returned by the server to only what you
need - in this case, the meeting's subject.

Create a meeting by using EWS


The request and response XML in the following examples correspond to calls made by
the EWS Managed API code in Create a meeting by using the EWS Managed API. The
request and response XML that verifies that the meeting items are in the calendar folder
are shown as well.

The following example shows the request XML when you use the CreateItem
operation to create a meeting.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:CreateItem SendMeetingInvitations="SendToAllAndSaveCopy">

<m:Items>

<t:CalendarItem>

<t:Subject>Team building exercise</t:Subject>

<t:Body BodyType="HTML">Let's learn to really work as a team and


then have lunch!</t:Body>

<t:ReminderMinutesBeforeStart>60</t:ReminderMinutesBeforeStart>

<t:Start>2013-09-21T16:00:00.000Z</t:Start>

<t:End>2013-09-21T20:00:00.000Z</t:End>

<t:Location>Conference Room 12</t:Location>

<t:RequiredAttendees>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

</t:RequiredAttendees>

<t:OptionalAttendees>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

</t:OptionalAttendees>

<t:MeetingTimeZone TimeZoneName="Pacific Standard Time" />

</t:CalendarItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The following example shows the response XML that is returned by the CreateItem
operation.

7 Note

The ItemId and ChangeKey attributes have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="775" MinorBuildNumber="7" Version="V2_4"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:CreateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

</m:CreateItemResponseMessage>

</m:ResponseMessages>

</m:CreateItemResponse>

</s:Body>

</s:Envelope>

The following example shows the request XML that is generated by the GetItem
operation when you verify that the meeting was created.

7 Note

The ItemId and ChangeKey attributes have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The following example shows the response XML that is returned by the GetItem
operation.

7 Note

The ItemId and ChangeKey attributes have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="775" MinorBuildNumber="7" Version="V2_4"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:Subject>Team building exercise</t:Subject>

</t:CalendarItem>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

See also
Calendars and EWS in Exchange
Get appointments and meetings by using EWS in Exchange
Update appointments and meetings by using EWS in Exchange
Delete appointments and cancel meetings by using EWS in Exchange
Propose a new meeting time by using EWS in Exchange
Create all-day events by using EWS in
Exchange
Article • 02/11/2022 • 3 minutes to read

Learn how to create all-day events by using the EWS Managed API or EWS in Exchange.

All-day events provide a way to represent something that happens for an entire day or
multiple days—for example, a holiday, or vacation days. Creating all-day events with the
EWS Managed API or EWS is a snap. It's just like creating appointments, but with a few
small changes.

Setting start and end times


By definition, all-day events start at midnight on a specific day, and end 24 hours (or a
multiple of 24 hours) later. However, the EWS Managed API and EWS allow you to
specify times other than midnight when creating all day events. This can lead to
unintended behavior if you're not aware of how these times get translated on the server.

When a request is received to create a new all-day event with non-midnight (in the time
zone of the request or appointment) start and/or end times, those times get adjusted to
midnight in the appropriate time zone according to the following rules:

Non-midnight start times are adjusted to the midnight prior to the time specified.
For example, 1:00 PM on June 6 gets adjusted to 12:00 AM on June 6.
Non-midnight end times are adjusted to the midnight after the time specified. For
example, 1:00 PM on June 6 gets adjusted to 12:00 AM on June 7.

So the all-day event that you create is always inclusive of the start and end time that you
specify, but might claim additional time on the user's calendar due to the shift to
midnight. Because the server will adjust the start and end time to midnight, we
recommend that you specify your start and end time at midnight to avoid any
unintended changes to the times.

It's also important to consider time zones when creating all-day events. Because the
Exchange server enforces a midnight start and end time in the time zone of the request
or appointment, viewing that all-day event in a client configured for a different time
zone can yield unexpected results. Depending on the client, it might appear as an all-
day event with extra days that you did not intend to include, or it might not appear as
an all-day event altogether. Because of this, we recommend that you use the user's
preferred time zone whenever possible when you create all-day events.
Create an all-day event by using the EWS
Managed API
The following example shows how to use the EWS Managed API to create an all-day
event, starting on the date specified by the startDate parameter and lasting for the
number of days specified by the numDays parameter. Note that the appointment will be
created in the time zone specified by the ExchangeService.TimeZone property. This
example assumes that the ExchangeService object passed in the service parameter has
been initialized with valid values for the Credentials and Url properties.

C#

static void CreateAllDayAppointment(ExchangeService service, DateTime


startDate, int numDays)
{

// Best practice is to set the start date to midnight

// on the first day of the all-day event.

DateTime startDateMidnight = startDate.Date;

// The end date should be midnight on the first day

// after the event.

DateTime endDateMidnight = startDateMidnight.AddDays(numDays);

Appointment allDayEvent = new Appointment(service);

// Set IsAllDayEvent to true.


allDayEvent.IsAllDayEvent = true;

// Set other properties.

allDayEvent.Subject = "Vacation";

allDayEvent.LegacyFreeBusyStatus = LegacyFreeBusyStatus.OOF;

allDayEvent.Start = startDateMidnight;

allDayEvent.End = endDateMidnight;

// Save the appointment.

try

allDayEvent.Save(WellKnownFolderName.Calendar,
SendInvitationsMode.SendToNone);

Console.WriteLine("All day event created.");

catch (Exception ex)

Console.WriteLine("Error saving all day event: {0}", ex.Message);

Create an all-day event by using EWS


The following example shows an EWS CreateItem operation request to create an all-
day event. The appointment is created in the Eastern time zone, as indicated by the
TimeZoneContext element. Notice that the time portion of the values of the Start
and End elements are both 04:00Z, which converts to midnight in the Eastern time
zone during daylight saving time.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Eastern Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:CreateItem SendMeetingInvitations="SendToNone">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="calendar" />

</m:SavedItemFolderId>

<m:Items>

<t:CalendarItem>

<t:Subject>Vacation</t:Subject>

<t:Start>2014-06-09T04:00:00.000Z</t:Start>

<t:End>2014-06-10T04:00:00.000Z</t:End>

<t:IsAllDayEvent>true</t:IsAllDayEvent>

<t:LegacyFreeBusyStatus>OOF</t:LegacyFreeBusyStatus>

</t:CalendarItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

See also- Calendars and EWS in Exchange


Create appointments and meetings by using EWS in Exchange 2013
Time zones and EWS in Exchange
Get appointments and meetings by
using EWS in Exchange
Article • 01/15/2020 • 4 minutes to read

Learn how to get appointments and meetings by using the EWS Managed API or EWS in
Exchange.

You can retrieve appointments and meetings from a calendar folder by using the
CalendarFolder.FindAppointments EWS Managed API method or the FindItem EWS
operation.

Get appointments by using the EWS Managed


API
The following code example shows how to use the EWS Managed API to retrieve a
user's appointments that fall between a specified start and end time.

C#

// Initialize values for the start and end times, and the number of
appointments to retrieve.

DateTime startDate = DateTime.Now;

DateTime endDate = startDate.AddDays(30);

const int NUM_APPTS = 5;

// Initialize the calendar folder object with only the folder


ID.

CalendarFolder calendar = CalendarFolder.Bind(service,


WellKnownFolderName.Calendar, new PropertySet());

// Set the start and end time and number of appointments to


retrieve.

CalendarView cView = new CalendarView(startDate, endDate,


NUM_APPTS);

// Limit the properties returned to the appointment's subject,


start time, and end time.

cView.PropertySet = new PropertySet(AppointmentSchema.Subject,


AppointmentSchema.Start, AppointmentSchema.End);

// Retrieve a collection of appointments by using the calendar


view.

FindItemsResults<Appointment> appointments =
calendar.FindAppointments(cView);
Console.WriteLine("\nThe first " + NUM_APPTS + " appointments on
your calendar from " + startDate.Date.ToShortDateString() +

" to " + endDate.Date.ToShortDateString() + "


are: \n");

foreach (Appointment a in appointments)

Console.Write("Subject: " + a.Subject.ToString() + " ");

Console.Write("Start: " + a.Start.ToString() + " ");

Console.Write("End: " + a.End.ToString());

Console.WriteLine();

The following is the output from the code example.

text

The first five appointments on your calendar from 8/21/2013 to 9/20/2013


are:

Subject: Contoso devs team meeting Start: 8/21/2013 12:30:00 PM End:


8/21/2013 1:00:00 PM

Subject: Daily status meeting Start: 8/21/2013 1:00:00 PM End: 8/21/2013


2:00:00 PM

Subject: Lunch with sales team Start: 8/21/2013 2:30:00 PM End: 8/21/2013
3:30:00 PM

Subject: Tennis at the club Start: 8/22/2013 11:00:00 AM End: 8/22/2013


12:00:00 PM

Subject: Online training webcast: 8/22/2013 2:00:00 PM End: 8/22/2013


3:00:00 PM

Get appointments by using EWS


The following XML shows a GetFolder operation request to return a folder ID for the
FindItem operation.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:GetFolder>

<m:FolderShape>

<t:BaseShape>IdOnly</t:BaseShape>

</m:FolderShape>

<m:FolderIds>

<t:DistinguishedFolderId Id="calendar" />

</m:FolderIds>

</m:GetFolder>

</soap:Body>

</soap:Envelope>

The following XML shows the GetFolder response. Note that the FolderID and
ChangeKey attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="731" MinorBuildNumber="10" Version="V2_3"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetFolderResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetFolderResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Folders>

<t:CalendarFolder>

<t:FolderId Id="AAMk" ChangeKey="AgAA" />

</t:CalendarFolder>

</m:Folders>

</m:GetFolderResponseMessage>

</m:ResponseMessages>

</m:GetFolderResponse>

</s:Body>

</s:Envelope>

The following XML shows the FindItem request used to return the requested
appointments. Note that the FolderID and ChangeKey attributes are shortened for
readability.
XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:FindItem Traversal="Shallow">

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="calendar:Start" />

<t:FieldURI FieldURI="calendar:End" />

</t:AdditionalProperties>

</m:ItemShape>

<m:CalendarView MaxEntriesReturned="5" StartDate="2013-08-


21T17:30:24.127Z" EndDate="2013-09-20T17:30:24.127Z" />

<m:ParentFolderIds>

<t:FolderId Id="AAMk" ChangeKey="AgAA" />

</m:ParentFolderIds>

</m:FindItem>

</soap:Body>

</soap:Envelope>

The following XML shows the FindItem response. Note that the ItemID and ChangeKey
attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="731" MinorBuildNumber="10" Version="V2_3"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:FindItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:FindItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootFolder TotalItemsInView="33"
IncludesLastItemInRange="false">

<t:Items>

<t:CalendarItem>

<t:ItemId Id="AAMk" ChangeKey="DwAA" />

<t:Subject>Contoso devs team meeting</t:Subject>

<t:Start>2013-08-21T19:30:00Z</t:Start>

<t:End>2013-08-21T20:00:00Z</t:End>

</t:CalendarItem>

<t:CalendarItem>

<t:ItemId Id="AAMk" ChangeKey="DwAA" />

<t:Subject>Daily status meeting</t:Subject>

<t:Start>2013-08-21T20:00:00Z</t:Start>

<t:End>2013-08-21T21:00:00Z</t:End>

</t:CalendarItem>

<t:CalendarItem>

<t:ItemId Id="AAMk" ChangeKey="DwAA" />

<t:Subject>Lunch with sales team</t:Subject>

<t:Start>2013-08-21T21:30:00Z</t:Start>

<t:End>2013-08-21T22:30:00Z</t:End>

</t:CalendarItem>

<t:CalendarItem>

<t:ItemId Id="AAMk" ChangeKey="DwAA" />

<t:Subject>Tennis at the club</t:Subject>

<t:Start>2013-08-22T18:00:00Z</t:Start>

<t:End>2013-08-22T19:00:00Z</t:End>

</t:CalendarItem>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAA" />

<t:Subject>Online training webcast</t:Subject>

<t:Start>2013-08-22T21:00:00Z</t:Start>

<t:End>2013-08-22T22:00:00Z</t:End>

</t:CalendarItem>

</t:Items>

</m:RootFolder>

</m:FindItemResponseMessage>

</m:ResponseMessages>

</m:FindItemResponse>

</s:Body>

</s:Envelope>

Recurring meetings and the calendar view


The calendar folder is a little different from other folders in a mailbox because
occurrences in a recurring series and exceptions to a recurring series are not actual
items in the mailbox, but rather are stored internally as attachments to a recurring
master. This means that although you can create an EWS request that returns values
between a set of start and end values by using one of the EWS Managed API FindItems
overload methods, such as ExchangeService.FindItems or the EWS FindItem
operation, EWS would not look through the attachment table of every calendar item to
find exceptions and occurrences.

Instead, what you really want to do is something akin to applying a Dataview onto a
union of two SQL tables, using a CalendarView object. Note that for performance
reasons, we recommend that you use the PropertySet property to limit the size of the
response by indicating the number of appointments or meetings you want returned, as
well as the specific properties you want.

See also
Calendars and EWS in Exchange
Create appointments and meetings by using EWS in Exchange 2013
Update appointments and meetings by using EWS in Exchange
Delete appointments and cancel meetings by using EWS in Exchange
Develop web service clients for Exchange
Update appointments and meetings by
using EWS in Exchange
Article • 03/04/2022 • 5 minutes to read

Learn how to update appointments and meetings by using the EWS Managed API or
EWS in Exchange.

The essential difference between meetings and appointments is that meetings have
attendees, and appointments don't. Both appointments and meetings can be single
instances or part of a recurring series, but because appointments don't include
attendees, rooms, or resources, they do not require a message to be sent. Internally,
Exchange uses the same object for both meetings and appointments. You use the EWS
Managed API Appointment class or the EWS CalendarItem element to work with
meetings and appointments.

Table 1. EWS Managed API method and EWS operations for updating appointments
and meetings

EWS Managed API method Corresponding EWS operations

Appointment.Update
UpdateItem

UpdateItemResponse

Update an appointment by using the EWS


Managed API
The following code example shows how to use the Appointment object to update
properties associated with an appointment and the Update method to save the
appointment to your calendar folder.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service. The local variable appointmentId
is an identifier associated with an existing appointment.

C#

// Instantiate an appointment object by binding to it by using the ItemId.

// As a best practice, limit the properties returned to only the ones you
need.

Appointment appointment = Appointment.Bind(service, appointmentId, new


PropertySet(AppointmentSchema.Subject, AppointmentSchema.Start,
AppointmentSchema.End));

string oldSubject = appointment.Subject;

// Update properties on the appointment with a new subject, start time, and
end time.

appointment.Subject = appointment.Subject + " moved one hour later and to


the day after " + appointment.Start.DayOfWeek + "!";

appointment.Start.AddHours(25);

appointment.End.AddHours(25);

// Unless explicitly specified, the default is to use SendToAllAndSaveCopy.

// This can convert an appointment into a meeting. To avoid this,

// explicitly set SendToNone on non-meetings.

SendInvitationsOrCancellationsMode mode = appointment.IsMeeting ?

SendInvitationsOrCancellationsMode.SendToAllAndSaveCopy :
SendInvitationsOrCancellationsMode.SendToNone;

// Send the update request to the Exchange server.

appointment.Update(ConflictResolutionMode.AlwaysOverwrite, mode);

// Verify the update.

Console.WriteLine("Subject for the appointment was \"" + oldSubject + "\".


The new subject is \"" + appointment.Subject + "\"");

Update an appointment by using EWS


The request and response XML in the following examples correspond to calls made by
the EWS Managed API code in Update an appointment by using the EWS Managed API.

The following example shows the request XML when you use the UpdateItem
operation to update an appointment.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:UpdateItem MessageDisposition="SaveOnly"
ConflictResolution="AlwaysOverwrite"
SendMeetingInvitationsOrCancellations="SendToNone">

<m:ItemChanges>

<t:ItemChange>

<t:ItemId Id="AAMkA" ChangeKey="DwAAAB" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:CalendarItem>

<t:Subject>Tennis Lesson moved one hour later and to the day


after Wednesday!</t:Subject>

</t:CalendarItem>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

</m:ItemChanges>

</m:UpdateItem>

</soap:Body>

</soap:Envelope>

The following example shows the XML that is returned in response to an UpdateItem
request. The ItemId and ChangeKey attributes have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="815" MinorBuildNumber="6" Version="V2_7"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:UpdateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exc

hange/services/2006/types">

<m:ResponseMessages>

<m:UpdateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAAB" />

</t:CalendarItem>

</m:Items>

<m:ConflictResults>

<t:Count>0</t:Count>

</m:ConflictResults>

</m:UpdateItemResponseMessage>

</m:ResponseMessages>

</m:UpdateItemResponse>

</s:Body>

</s:Envelope>

Update a meeting by using the EWS Managed


API
When you update a meeting, in addition to saving the modified appointment item to
the calendar folder, you also typically want to send updated meeting requests to
attendees. The following code example shows how to update a meeting and send
meeting requests.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service. The local variable meetingId is an
identifier that is associated with an existing appointment.

C#

// Instantiate an appointment object by binding to it using the ItemId.

// As a best practice, limit the properties returned to only the Appointment


ID.

Appointment meeting = Appointment.Bind(service, meetingId, new


PropertySet(AppointmentSchema.Subject,

AppointmentSchema.Location,

AppointmentSchema.RequiredAttendees,

AppointmentSchema.Resources));

string oldSubject = meeting.Subject;

// Update properties on the appointment with a new subject, location, an


additional required attendee, and a resource.

meeting.Subject = "Team building exercise has moved!";

meeting.Location = "4567 Contoso Way, Redmond, OH 33333, USA";

meeting.RequiredAttendees.Add("[email protected]");

meeting.Resources.Add("[email protected]");

// Send the update request to the Exchange server.

meeting.Update(ConflictResolutionMode.AlwaysOverwrite,
SendInvitationsOrCancellationsMode.SendToAllAndSaveCopy);

// Verify the update.

Console.WriteLine("Subject for the meeting was \"" + oldSubject + "\". The


new subject is \"" + meeting.Subject + "\"");

After setting the properties on the Appointment object, save the meeting to your
calendar folder and send updated meeting requests by using the Update method.

You can pass in one of two enumeration values as parameters when you call the
Update method:

ConflictResolutionMode enumeration — Determines how conflicting states


between client and server are handled.
SendInvitationsOrCancellationsMode enumeration — Affects the sending and
saving of meeting update requests.

When you set the ConflictResolutionMode enumeration value to AlwaysOverwrite,


your version of the meeting will always be saved to the calendar folder.

Update a meeting by using EWS


The request and response XML in the following examples correspond to calls made by
the EWS Managed API code in Update a meeting by using the EWS Managed API.

The following example shows the request XML when you use the UpdateItem
operation to update a meeting.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:UpdateItem MessageDisposition="SaveOnly"
ConflictResolution="AlwaysOverwrite"
SendMeetingInvitationsOrCancellations="SendToAllAndSaveCopy">

<m:ItemChanges>

<t:ItemChange>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:CalendarItem>

<t:Subject>Team building exercise has moved!</t:Subject>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:Location" />

<t:CalendarItem>

<t:Location>4567 Contoso Way, Redmond, OH 33333,


USA</t:Location>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:RequiredAttendees" />

<t:CalendarItem>

<t:RequiredAttendees>

<t:Attendee>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

</t:RequiredAttendees>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:Resources" />

<t:CalendarItem>

<t:Resources>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

</t:Resources>

</t:CalendarItem>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

</m:ItemChanges>

</m:UpdateItem>

</soap:Body>

</soap:Envelope>

The following example shows the XML that is returned in response to an UpdateItem
request. The ChangeKey and ItemId attributes have been shortened for readability.

XML
<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="815" MinorBuildNumber="6" Version="V2_7"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:UpdateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:UpdateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

<m:ConflictResults>

<t:Count>0</t:Count>

</m:ConflictResults>

</m:UpdateItemResponseMessage>

</m:ResponseMessages>

</m:UpdateItemResponse>

</s:Body>

</s:Envelope>

See also
Calendars and EWS in Exchange
Create appointments and meetings by using EWS in Exchange 2013
Get appointments and meetings by using EWS in Exchange
Delete appointments and cancel meetings by using EWS in Exchange
Propose a new meeting time by using EWS in Exchange
Delete appointments and cancel
meetings by using EWS in Exchange
Article • 03/04/2022 • 8 minutes to read

Learn how to delete appointments and meetings by using the EWS Managed API or
EWS in Exchange.

The essential difference between meetings and appointments is that meetings have
attendees, and appointments don't. Both appointments and meetings can be single
instances or part of a recurring series, but because appointments don't include
attendees, rooms, or resources, they do not require a message to be sent. Internally,
Exchange uses the same object for both meetings and appointments. You use the EWS
Managed API Appointment class or the EWS [CalendarItem]
(https://msdn.microsoft.com/library/Title Topic ID Project Name Writer Editor Publish
Preview.aspx) element to work with meetings and appointments.

Table 1. EWS Managed API methods and EWS operations for deleting appointments
and meetings

EWS Managed API method EWS Operation What it does

Appointment.Delete
DeleteItem
Deletes an appointment.

Appointment.Delete
CreateItem (calendar item)
Deletes a meeting.

Note that when you delete an appointment by using EWS, you use the DeleteItem
operation, but when you delete a meeting, you use the CreateItem operation. This might
seem counterintuitive, but it is because you have to create a meeting response object to
send meeting cancellation messages to attendees.

Delete an appointment by using the EWS


Managed API
The following code example shows how to use the Delete method to delete an
appointment from your calendar folder, and the ExchangeService.FindItems method
to verify that the appointment was deleted by looking for it in the Deleted Items folder.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service. The local variable appointmentId
is an identifier associated with an existing appointment.
C#

// Instantiate an appointment object by binding to it by using the ItemId.

// As a best practice, limit the properties returned to only the ones you
need.

Appointment appointment = Appointment.Bind(service, appointmentId, new


PropertySet());

// Delete the appointment. Note that the item ID will change when the item
is moved to the Deleted Items folder.

appointment.Delete(DeleteMode.MoveToDeletedItems);

// Verify that the appointment has been deleted by looking for a matching
subject in the Deleted Items folder's first entry.

ItemView itemView = new ItemView(1);

itemView.Traversal = ItemTraversal.Shallow;

// Just retrieve the properties you need.

itemView.PropertySet = new PropertySet(ItemSchema.Id,


ItemSchema.ParentFolderId, ItemSchema.Subject);

// Note that the FindItems method results in a call to EWS.

FindItemsResults<Item> deletedItems =
service.FindItems(WellKnownFolderName.DeletedItems, itemView);

Item deletedItem = deletedItems.First();

Folder parentFolder = Folder.Bind(service, deletedItem.ParentFolderId, new


PropertySet(FolderSchema.DisplayName));

Console.WriteLine("The appointment " + "\"" + deletedItem.Subject + "\"" + "


is now in the " + parentFolder.DisplayName + " folder.");

This example shows a simple way to verify that the appointment was deleted, by
verifying that the subject of the first item in the Deleted Items folder matches that of the
deleted appointment. How you choose to verify that your appointment was deleted will
vary based the needs of your application.

As you can see, deleting an appointment is straightforward and pretty much what you
might expect. Note when you create your verification step that the appointment item in
the Deleted Items folder has a different ItemId than the appointment item in the
calendar folder. The item is copied and deleted rather than simply moved to the Deleted
Items folder.

Delete an appointment by using EWS


The request and response XML in the following examples correspond to calls made by
the EWS Managed API code in Delete an appointment by using the EWS Managed API.
The request and response XML that verifies that the appointment item is in the Deleted
Items folder is shown as well.

The following example shows the request XML for the DeleteItem operation to delete an
appointment.
XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:DeleteItem DeleteType="MoveToDeletedItems"
SendMeetingCancellations="SendToAllAndSaveCopy">

<m:ItemIds>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</m:ItemIds>

</m:DeleteItem>

</soap:Body>

</soap:Envelope>

The following example shows the response XML that is returned by the DeleteItem
operation. The ItemId and ChangeKey attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="800" MinorBuildNumber="5" Version="V2_6"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:DeleteItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:DeleteItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

</m:DeleteItemResponseMessage>

</m:ResponseMessages>

</m:DeleteItemResponse>

</s:Body>

</s:Envelope>

The following example shows the request XML for the FindItem operation that
retrieves the first item in the Deleted Items folder in order to compare the item's subject
with that of the deleted appointment object.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages

" xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:FindItem Traversal="Shallow">

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:ItemId" />

<t:FieldURI FieldURI="item:ParentFolderId" />

<t:FieldURI FieldURI="item:Subject" />

</t:AdditionalProperties>

</m:ItemShape>

<m:IndexedPageItemView MaxEntriesReturned="1" Offset="0"


BasePoint="Beginning" />

<m:ParentFolderIds>

<t:DistinguishedFolderId Id="deleteditems" />

</m:ParentFolderIds>

</m:FindItem>

</soap:Body>

</soap:Envelope>

The following example shows the response XML that is returned by the FindItem
operation during the verification step.

7 Note

The ItemId and ChangeKey attributes are shortened for readability.

XML
<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="800" MinorBuildNumber="5" Version="V2_6"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:FindItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:FindItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootFolder IndexedPagingOffset="1" TotalItemsInView="10748"


IncludesLastItemInRange="false">

<t:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA=" ChangeKey="DwAAA" />

<t:ParentFolderId Id="AAMkA" ChangeKey="AQAAA" />

<t:Subject>Tennis lesson</t:Subject>

</t:CalendarItem>

</t:Items>

</m:RootFolder>

</m:FindItemResponseMessage>

</m:ResponseMessages>

</m:FindItemResponse>

</s:Body>

</s:Envelope>

Delete a meeting by using the EWS Managed


API
When you delete a meeting, in addition to removing the appointment item from the
calendar folder, you might also want to send meeting cancellations to attendees. You
can use the following three methods to cancel a meeting:

Appointment.Delete
Appointment.CancelMeeting
CancelMeetingMessage

The method that you choose depends on the level of detail you need to provide in your
cancellation message. Appointment.CancelMeeting makes it easy to update the
cancellation message by passing an updated message as a parameter.
CancelMeetingMessage allows you to modify properties on your message before
sending a cancellation, so you can do things like request a receipt.

The code examples in this section show the different ways to delete a meeting and send
meeting cancellations. The examples assume that you have authenticated to an
Exchange server and have acquired an ExchangeService object named service. The
local variable meetingId is an identifier associated with an existing meeting where the
target user is the meeting organizer.

The following code example shows how to delete a meeting by using the
Appointment.Delete method.

C#

// Instantiate an appointment object for the meeting by binding to it using


the ItemId.

// As a best practice, limit the properties returned to only the Appointment


ID.

Appointment meeting = Appointment.Bind(service, meetingId, new


PropertySet());

// Delete the meeting by using the Delete method.

meeting.Delete(DeleteMode.MoveToDeletedItems,
SendCancellationsMode.SendToAllAndSaveCopy);

// Verify that the meeting has been deleted by looking for a matching
subject in the Deleted Items folder's first entry.

ItemView itemView = new ItemView(1);

itemView.Traversal = ItemTraversal.Shallow;

// Just retrieve the properties you need.

itemView.PropertySet = new PropertySet(ItemSchema.Id,


ItemSchema.ParentFolderId, ItemSchema.Subject);

// Note that the FindItems method results in a call to EWS.

FindItemsResults<Item> deletedItems =
service.FindItems(WellKnownFolderName.DeletedItems, itemView);

Item deletedItem = deletedItems.First();

Folder parentFolder = Folder.Bind(service, deletedItem.ParentFolderId, new


PropertySet(FolderSchema.DisplayName));

Console.WriteLine("The meeting " + "\"" + deletedItem.Subject + "\"" + " is


now in the " + parentFolder.DisplayName + " folder.");

The following code example shows how to delete a meeting by using the
CancelMeeting method.

C#

// Instantiate an appointment object by binding to it using the ItemId.

// As a best practice, limit the properties returned to only the Appointment


ID.

Appointment meeting = Appointment.Bind(service, meetingId, new


PropertySet());

// Delete the meeting by using the CancelMeeting method.

meeting.CancelMeeting("The outdoor meeting has been cancelled due to


hailstorms.");

The following code example shows how to delete a meeting by using the
Appointment.CreateCancelMeetingMessage method.

C#

// Instantiate an appointment object by binding to it using the ItemId.

// As a best practice, limit the properties returned to only the Appointment


ID.

Appointment meeting = Appointment.Bind(service, meetingId, new


PropertySet());

// Delete the meeting by using the CreateCancelMeetingMessage method.

CancelMeetingMessage cancelMessage = meeting.CreateCancelMeetingMessage();

cancelMessage.Body = new MessageBody("The outdoor meeting has been canceled


due to hailstorms.");

cancelMessage.IsReadReceiptRequested = true;

cancelMessage.SendAndSaveCopy();

Delete a meeting by using EWS


The request and response XML in the following examples correspond to calls made by
the EWS Managed API code in Delete a meeting by using the EWS Managed API by
using the Appointment.Delete method.

The following example shows the request XML when you use the CreateItem
operation to send cancellation messages to attendees and delete a meeting.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SendAndSaveCopy">

<m:Items>

<t:CancelCalendarItem>

<t:ReferenceItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:NewBodyContent BodyType="HTML">The outdoor meeting has been


canceled due to hailstorms.</t:NewBodyContent>

</t:CancelCalendarItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The following example shows the XML that is returned in response to a CreateItem
operation request used to delete a meeting.

7 Note

The ItemId and ChangeKey attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="800" MinorBuildNumber="5" Version="V2_6"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:CreateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

</m:CreateItemResponseMessage>

</m:ResponseMessages>

</m:CreateItemResponse>

</s:Body>

</s:Envelope>

The following example shows the request XML for the FindItem operation that
retrieves the first item in the Deleted Items folder in order to compare the item's subject
with that of the deleted appointment object.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:FindItem Traversal="Shallow">

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:ItemId" />

<t:FieldURI FieldURI="item:ParentFolderId" />

<t:FieldURI FieldURI="item:Subject" />

</t:AdditionalProperties>

</m:ItemShape>

<m:IndexedPageItemView MaxEntriesReturned="1" Offset="0"


BasePoint="Beginning" />

<m:ParentFolderIds>

<t:DistinguishedFolderId Id="deleteditems" />

</m:ParentFolderIds>

</m:FindItem>

</soap:Body>

</soap:Envelope>

The following example shows the XML that is returned by the FindItem operation
during the verification step.

7 Note

The Id and ChangeKey attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="800" MinorBuildNumber="5" Version="V2_6"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:FindItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:FindItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootFolder IndexedPagingOffset="1" TotalItemsInView="10750"


IncludesLastItemInRange="false">

<t:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:ParentFolderId Id="AAMkA" ChangeKey="AQAAA" />

<t:Subject>Team building exercise</t:Subject>

</t:CalendarItem>

</t:Items>

</m:RootFolder>

</m:FindItemResponseMessage>

</m:ResponseMessages>

</m:FindItemResponse>

</s:Body>

</s:Envelope>

See also
Calendars and EWS in Exchange
Create appointments and meetings by using EWS in Exchange 2013
Get appointments and meetings by using EWS in Exchange
Update appointments and meetings by using EWS in Exchange
Propose a new meeting time by using EWS in Exchange
Propose a new meeting time by using EWS in Exchange
Get room lists by using EWS in
Exchange
Article • 01/15/2020 • 3 minutes to read

Learn how to get a list of all the room lists in your organization or a single room list
from an Exchange server by using the EWS Managed API or EWS.

You can use the EWS Managed API or EWS to get information about rooms and how the
rooms are grouped in your organization. Room lists don't exist by default; your
administrator needs to create and organize them. Typically, they're organized by
location or department, as shown in the following example.

Contoso room list names and email addresses

Name of room list Email address of room list

Building 11 room list [email protected]

Health Science Building Conference Room List [email protected]

Accounting Floor Meeting Rooms [email protected]

Each room in a room list has a name and email address associated with it.

Contoso room names and email addresses

Name of room Email address of room

Conf Room 11/101 (8) AV [email protected]

HS Demonstration Lab (100) [email protected]

Accounting 305 WB [email protected]

You can get a list that contains all room lists by using either the
ExchangeService.GetRoomLists EWS Managed API method or the GetRoomLists
EWS operation.

You can retrieve a single room list that contains all the rooms for a location or
department by supplying its email address by using the GetRooms EWS Managed API
method or the GetRooms EWS operation. When you have a collection of rooms
associated with a room list, you can then search through the collection to identify the
room or rooms you want, either by email address, or by looking for key words in the
name, such as "AV", or "Lab".
Get all room lists by using the EWS Managed
API
The following example shows how to get a list that contains all the room lists in your
organization by using the GetRoomLists method.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

// Return all the room lists in the organization.

// This method call results in a GetRoomLists call to EWS.

EmailAddressCollection myRoomLists = service.GetRoomLists();

// Display the room lists.

foreach (EmailAddress address in myRoomLists)

Console.WriteLine("Email Address: {0} Mailbox Type: {1}",


address.Address, address.MailboxType);

Get all room lists by using EWS


The following example shows how to get a collection of all your organization's
RoomLists by using the GetRoomLists operation. This is also the XML request that
the EWS Managed API sends when you use the EWS Managed API to get all room lists.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

</soap:Header>

<soap:Body>

<m:GetRoomLists />

</soap:Body>

</soap:Envelope>

The server responds to the GetRoomLists request with a GetRoomListsResponse


message that contains the room lists for your organization.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="868" MinorBuildNumber="8" Version="V2_9"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetRoomListsResponse ResponseClass="Success"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseCode>NoError</m:ResponseCode>
<m:RoomLists>

<t:Address>

<t:Name>Contoso Building 1 Room List</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>PublicDL</t:MailboxType>

</t:Address>

<t:Address>

<t:Name>Contoso Building 2 Room List</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>PublicDL</t:MailboxType>

</t:Address>

<t:Address>

<t:Name>Contoso Building 3 Room List</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>PublicDL</t:MailboxType>

</t:Address>

</m:RoomLists>

</m:GetRoomListsResponse>

</s:Body>

</s:Envelope>

Get all the rooms in a room list by using the


EWS Managed API
The following example shows how to get a collection of rooms in a room list by using
the GetRooms method.

C#

EmailAddress myRoomList = "[email protected]";

// This method call results in a GetRooms call to EWS.

System.Collections.ObjectModel.Collection<EmailAddress> myRoomAddresses =
service.GetRooms(myRoomList);

// Display the individual rooms.

foreach (EmailAddress address in myRoomAddresses)

Console.WriteLine("Email Address: {0}", address.Address);

Get all the rooms in a room list by using EWS


The following example shows how to get a list of rooms in a RoomList by using the
GetRooms operation. This is also the XML request that the EWS Managed API sends
when you use the EWS Managed API to get all the rooms in a room list.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

</soap:Header>

<soap:Body>

<m:GetRooms>

<m:RoomList>

<t:EmailAddress>[email protected]</t:EmailAddress>

</m:RoomList>

</m:GetRooms>

</soap:Body>

</soap:Envelope>

The server responds to the GetRooms request with a GetRoomsResponse message


that contains the rooms in the room list.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="873" MinorBuildNumber="9"

Version="V2_9"
xmlns:h="http://scemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetRoomsResponse ResponseClass="Success"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="http://scemas.microsoft.com/exchange/services/2006/types">

<m:ResponseCode>NoError</m:ResponseCode>
<m:Rooms>

<t:Room>

<t:Id>

<t:Name>Conf Room 3/101 (16) AV</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>Mailbox</t:MailboxType>

</t:Id>

</t:Room>

<t:Room>

<t:Id>

<t:Name>Conf Room 3/102 (8) AV</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>Mailbox</t:MailboxType>

</t:Id>

</t:Room>

<t:Room>

<t:Id>

<t:Name>Conf Room 3/103 (14) AV RoundTable</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>Mailbox</t:MailboxType>

</t:Id>

</t:Room>

</m:Rooms>

</m:GetRoomsResponse>

</s:Body>

</s:Envelope>

See also
Calendars and EWS in Exchange

Get free/busy information by using EWS in Exchange

Create and Manage Room Mailboxes


Get free/busy information by using EWS
in Exchange
Article • 01/15/2020 • 4 minutes to read

Learn how to get free/busy information and suggested meeting times by using the EWS
Managed API or EWS in Exchange.

Using the EWS Managed API or EWS to programmatically create a meeting and send
out meeting requests is great, but finding a time that works for all your attendees is
often a challenge. If you have to manually check to see when everyone is available, it
defeats the purpose of automating the task. Fortunately, the
ExchangeService.GetUserAvailability EWS Managed API method and the
GetUserAvailability EWS operation come to your rescue. You can use this method or
operation to query an Exchange server to find the best time to schedule a meeting or
just get free/busy information for attendees. You can get the free/busy information for a
list of attendees, or have your Exchange server find a meeting time for you, or both

Figure 1 illustrates the problem and the solution.

Figure 1. Requesting availability information from an Exchange server


Get suggested meeting times and free/busy
information by using the EWS Managed API
You can get both a list of suggested meeting times and all the scheduled event times for
your attendees when you use an AvailabilityData enumeration value of
FreeBusyAndSuggestions in your ExchangeService.GetUserAvailability method call, as
shown in the following example.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

private static void GetSuggestedMeetingTimesAndFreeBusyInfo(ExchangeService


service)

// Create a collection of attendees.

List<AttendeeInfo> attendees = new List<AttendeeInfo>();

attendees.Add(new AttendeeInfo()

SmtpAddress = "[email protected]",

AttendeeType = MeetingAttendeeType.Organizer

});

attendees.Add(new AttendeeInfo()

SmtpAddress = "[email protected]",

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 = 2;

// Note that 60 minutes is the default value for MeetingDuration, but


setting it explicitly for demonstration purposes.

availabilityOptions.MeetingDuration = 60;

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.Meet
ingDuration)).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++;

Get suggested meeting times and free/busy


information by using EWS
You can get both a list of suggested meeting times and all the scheduled event times for
your attendees by using the GetUserAvailability operation, as shown in the following
example. This is also the XML request that the EWS Managed API sends when you use
the EWS Managed API to get suggested meeting times.
XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Name="(UTC-08:00) Pacific Time (US &amp;amp;
Canada)" Id="Pacific Standard Time">

<t:Periods>

<t:Period Bias="P0DT8H0M0.0S" Name="Standard" Id="Std" />

<t:Period Bias="P0DT7H0M0.0S" Name="Daylight" Id="Dlt/1" />

<t:Period Bias="P0DT7H0M0.0S" Name="Daylight" Id="Dlt/2007" />

</t:Periods>

<t:TransitionsGroups>

<t:TransitionsGroup Id="0">

<t:RecurringDayTransition>

<t:To Kind="Period">Dlt/1</t:To>

<t:TimeOffset>P0DT2H0M0.0S</t:TimeOffset>

<t:Month>4</t:Month>

<t:DayOfWeek>Sunday</t:DayOfWeek>

<t:Occurrence>1</t:Occurrence>

</t:RecurringDayTransition>

<t:RecurringDayTransition>

<t:To Kind="Period">Std</t:To>

<t:TimeOffset>P0DT2H0M0.0S</t:TimeOffset>

<t:Month>10</t:Month>

<t:DayOfWeek>Sunday</t:DayOfWeek>

<t:Occurrence>-1</t:Occurrence>

</t:RecurringDayTransition>

</t:TransitionsGroup>

<t:TransitionsGroup Id="1">

<t:RecurringDayTransition>

<t:To Kind="Period">Dlt/2007</t:To>

<t:TimeOffset>P0DT2H0M0.0S</t:TimeOffset>

<t:Month>3</t:Month>

<t:DayOfWeek>Sunday</t:DayOfWeek>

<t:Occurrence>2</t:Occurrence>

</t:RecurringDayTransition>

<t:RecurringDayTransition>

<t:To Kind="Period">Std</t:To>

<t:TimeOffset>P0DT2H0M0.0S</t:TimeOffset>

<t:Month>11</t:Month>

<t:DayOfWeek>Sunday</t:DayOfWeek>

<t:Occurrence>1</t:Occurrence>

</t:RecurringDayTransition>

</t:TransitionsGroup>

</t:TransitionsGroups>

<t:Transitions>

<t:Transition>

<t:To Kind="Group">0</t:To>

</t:Transition>

<t:AbsoluteDateTransition>

<t:To Kind="Group">1</t:To>

<t:DateTime>2007-01-01T08:00:00.000Z</t:DateTime>

</t:AbsoluteDateTransition>

</t:Transitions>

</t:TimeZoneDefinition>

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:GetUserAvailabilityRequest>

<m:MailboxDataArray>

<t:MailboxData>

<t:Email>

<t:Address>[email protected]</t:Address>

</t:Email>

<t:AttendeeType>Organizer</t:AttendeeType>

<t:ExcludeConflicts>false</t:ExcludeConflicts>
</t:MailboxData>

<t:MailboxData>

<t:Email>

<t:Address>[email protected]</t:Address>

</t:Email>

<t:AttendeeType>Required</t:AttendeeType>

<t:ExcludeConflicts>false</t:ExcludeConflicts>
</t:MailboxData>

</m:MailboxDataArray>

<t:FreeBusyViewOptions>

<t:TimeWindow>

<t:StartTime>2014-02-13T00:00:00</t:StartTime>

<t:EndTime>2014-02-14T00:00:00</t:EndTime>

</t:TimeWindow>

<t:MergedFreeBusyIntervalInMinutes>30</t:MergedFreeBusyIntervalInMinutes>

<t:RequestedView>FreeBusy</t:RequestedView>

</t:FreeBusyViewOptions>

<t:SuggestionsViewOptions>

<t:GoodThreshold>49</t:GoodThreshold>

<t:MaximumResultsByDay>2</t:MaximumResultsByDay>

<t:MaximumNonWorkHourResultsByDay>0</t:MaximumNonWorkHourResultsByDay>

<t:MeetingDurationInMinutes>60</t:MeetingDurationInMinutes>

<t:MinimumSuggestionQuality>Good</t:MinimumSuggestionQuality>

<t:DetailedSuggestionsWindow>

<t:StartTime>2014-02-13T00:00:00</t:StartTime>

<t:EndTime>2014-02-14T00:00:00</t:EndTime>

</t:DetailedSuggestionsWindow>

</t:SuggestionsViewOptions>

</m:GetUserAvailabilityRequest>

</soap:Body>

</soap:Envelope>

The server responds to the GetUserAvailability request with a GetUserAvailability


response message, as shown in the following example.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="873" MinorBuildNumber="9" Version="V2_9"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<GetUserAvailabilityResponse
xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">

<FreeBusyResponseArray>

<FreeBusyResponse>

<ResponseMessage ResponseClass="Success">

<ResponseCode>NoError</ResponseCode>

</ResponseMessage>

<FreeBusyView>

<FreeBusyViewType
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">FreeBusy<
/FreeBusyViewType>

<CalendarEventArray
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<CalendarEvent>

<StartTime>2014-02-13T08:00:00</StartTime>

<EndTime>2014-02-13T10:00:00</EndTime>

<BusyType>Free</BusyType>

</CalendarEvent>

<CalendarEvent>

<StartTime>2014-02-13T11:00:00</StartTime>

<EndTime>2014-02-13T12:00:00</EndTime>

<BusyType>Busy</BusyType>

</CalendarEvent>

</CalendarEventArray>

<WorkingHours
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<TimeZone>

<Bias>480</Bias>

<StandardTime>

<Bias>0</Bias>

<Time>02:00:00</Time>

<DayOrder>1</DayOrder>

<Month>11</Month>

<DayOfWeek>Sunday</DayOfWeek>

</StandardTime>

<DaylightTime>

<Bias>-60</Bias>

<Time>02:00:00</Time>

<DayOrder>2</DayOrder>

<Month>3</Month>

<DayOfWeek>Sunday</DayOfWeek>

</DaylightTime>

</TimeZone>

<WorkingPeriodArray>

<WorkingPeriod>

<DayOfWeek>Monday Tuesday Wednesday Thursday


Friday</DayOfWeek>

<StartTimeInMinutes>480</StartTimeInMinutes>

<EndTimeInMinutes>1020</EndTimeInMinutes>

</WorkingPeriod>

</WorkingPeriodArray>

</WorkingHours>

</FreeBusyView>

</FreeBusyResponse>

<FreeBusyResponse>

<ResponseMessage ResponseClass="Success">

<ResponseCode>NoError</ResponseCode>

</ResponseMessage>

<FreeBusyView>

<FreeBusyViewType
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">FreeBusy<
/FreeBusyViewType>

<CalendarEventArray
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<CalendarEvent>

<StartTime>2014-02-12T00:00:00</StartTime>

<EndTime>2014-02-13T00:00:00</EndTime>

<BusyType>Free</BusyType>

</CalendarEvent>

<CalendarEvent>

<StartTime>2014-02-13T08:00:00</StartTime>

<EndTime>2014-02-13T10:00:00</EndTime>

<BusyType>Free</BusyType>

</CalendarEvent>

<CalendarEvent>

<StartTime>2014-02-13T11:00:00</StartTime>

<EndTime>2014-02-13T12:00:00</EndTime>

<BusyType>Busy</BusyType>

</CalendarEvent>

<CalendarEvent>

<StartTime>2014-02-13T15:00:00</StartTime>

<EndTime>2014-02-13T16:00:00</EndTime>

<BusyType>Tentative</BusyType>

</CalendarEvent>

</CalendarEventArray>

<WorkingHours
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<TimeZone>

<Bias>480</Bias>

<StandardTime>

<Bias>0</Bias>

<Time>02:00:00</Time>

<DayOrder>1</DayOrder>

<Month>11</Month>

<DayOfWeek>Sunday</DayOfWeek>

</StandardTime>

<DaylightTime>

<Bias>-60</Bias>

<Time>02:00:00</Time>

<DayOrder>2</DayOrder>

<Month>3</Month>

<DayOfWeek>Sunday</DayOfWeek>

</DaylightTime>

</TimeZone>

<WorkingPeriodArray>

<WorkingPeriod>

<DayOfWeek>Monday Tuesday Wednesday Thursday


Friday</DayOfWeek>

<StartTimeInMinutes>540</StartTimeInMinutes>

<EndTimeInMinutes>1020</EndTimeInMinutes>

</WorkingPeriod>

</WorkingPeriodArray>

</WorkingHours>

</FreeBusyView>

</FreeBusyResponse>

</FreeBusyResponseArray>

<SuggestionsResponse>

<ResponseMessage ResponseClass="Success">

<ResponseCode>NoError</ResponseCode>

</ResponseMessage>

<SuggestionDayResultArray>

<SuggestionDayResult
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<Date>2014-02-13T00:00:00</Date>

<DayQuality>Excellent</DayQuality>

<SuggestionArray>

<Suggestion>

<MeetingTime>2014-02-13T09:00:00</MeetingTime>

<IsWorkTime>true</IsWorkTime>

<SuggestionQuality>Excellent</SuggestionQuality>

<AttendeeConflictDataArray>

<IndividualAttendeeConflictData>

<BusyType>Free</BusyType>

</IndividualAttendeeConflictData>

<IndividualAttendeeConflictData>

<BusyType>Free</BusyType>

</IndividualAttendeeConflictData>

</AttendeeConflictDataArray>

</Suggestion>

<Suggestion>

<MeetingTime>2014-02-13T09:30:00</MeetingTime>

<IsWorkTime>true</IsWorkTime>

<SuggestionQuality>Excellent</SuggestionQuality>

<AttendeeConflictDataArray>

<IndividualAttendeeConflictData>

<BusyType>Free</BusyType>

</IndividualAttendeeConflictData>

<IndividualAttendeeConflictData>

<BusyType>Free</BusyType>

</IndividualAttendeeConflictData>

</AttendeeConflictDataArray>

</Suggestion>

</SuggestionArray>

</SuggestionDayResult>

</SuggestionDayResultArray>

</SuggestionsResponse>

</GetUserAvailabilityResponse>

</s:Body>

</s:Envelope>

See also
Calendars and EWS in Exchange

Create appointments and meetings by using EWS in Exchange 2013

Update appointments and meetings by using EWS in Exchange


Propose a new meeting time by using
EWS in Exchange
Article • 10/25/2022 • 5 minutes to read

Find out how to propose new meeting times from your Exchange client application by
using EWS in Exchange.

The propose new time feature enables attendees to propose new meeting times to the
meeting organizer as part of the Exchange calendar workflow. When an attendee
proposes a new meeting, the organizer can use the proposed new meeting time to
update the meeting and send updates to all attendees. Before you can enable attendees
to propose new meeting times, you need to determine whether the organizer allows for
new time proposals. This article describes how to determine whether you can propose a
new time and how to use EWS to propose a new time.

7 Note

The EWS Managed API does not implement this functionality.

Determine whether you can propose a new


time for a meeting by using EWS
Before you can propose a new time for a meeting, you need to find a reference to that
meeting and determine whether the meeting organizer configured the meeting to
support new time proposals. You can get a reference to a meeting by doing either of the
following:

Finding the meeting request in the Inbox

Finding the appointment in the calendar

Use the following steps to find a meeting reference:

1. Use the FindItem EWS operation (or the Folder.FindItems EWS Managed API
method) to find the target meeting request or calendar item. Alternatively, you can
use the SyncFolderItems EWS operation to get the identifier of the target
meeting request or calendar item.

2. Parse the results of the FindItem operation (or Folder.FindItems method) to get
the item identifier of the meeting item.
3. Use the GetItem EWS operation to get the response objects for the meeting.

The following XML shows what is sent to request the response objects on an item.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"

xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">

<soap:Header>

<t:RequestServerVersion Version="Exchange2013" />

<t:MailboxCulture>en-US</t:MailboxCulture>

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:ResponseObjects"/>

<t:FieldURI FieldURI="item:Subject"/>

<t:FieldURI FieldURI="calendar:Start"/>

<t:FieldURI FieldURI="calendar:End"/>

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="AAMkADEzOTExYjJkL1AAA=" ChangeKey="CwAAAB/G6X"/>

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The GetItem operation response will look similar to the following XML if you request the
item identifier, the meeting start and end time, the response object collection, and if the
organizer allows for proposed changes to the meeting time. The response object
collection, which is represented by the ResponseObjects element, contains the set of
responses that are valid for the calendar item. The ProposeNewTime element is a
response object that indicates that the user can propose a new time for the meeting.
The AcceptItem , TentativelyAcceptItem , and DeclineItem elements represent the
response objects that you can use to propose a new meeting time to the meeting
organizer.

XML

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="815"

MinorBuildNumber="6"

Version="V2_7"

xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"

xmlns="http://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"/>

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:MeetingRequest>

<t:ItemId Id="AAMkADEzOTExYjJkL1AAA=" ChangeKey="CwAAAB/G6X"/>

<t:Subject>Competitive analysis: kick off meeting</t:Subject>

<t:ResponseObjects>

<t:AcceptItem/>

<t:TentativelyAcceptItem/>

<t:DeclineItem/>

<t:ProposeNewTime/>

<t:ReplyToItem/>

<t:ReplyAllToItem/>

<t:ForwardItem/>

</t:ResponseObjects>

<t:Start>2013-11-09T17:00:00Z</t:Start>

<t:End>2013-11-09T17:30:00Z</t:End>

</t:MeetingRequest>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

Propose a new meeting time by using EWS


If you received a ProposeNewTime response object when you used the GetItem
operation to get a calendar item or meeting request, you can respond with a proposed
new meeting time. If you didn't receive a ProposeNewTime response object, you won't
be able to propose a new meeting time as part of the calendar workflow. You can,
however, reply to the organizer to request a new meeting time. If you receive a
ProposeNewTime response object, you can respond to the meeting by referencing its
identifier, and propose a new meeting time to the organizer. This is where the
ProposeNewTime response object is different than the typical response object pattern
in that you don't respond with a ProposeNewTime response object. You use one of the
other meeting response objects, such as AcceptItem, TentativelyAcceptItem, or
DeclineItem, to propose a new meeting. This example uses the AcceptItem response
object.

XML

<?xml version="1.0" encoding="UTF-8"?>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"

xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">

<soap:Header>

<t:RequestServerVersion Version="Exchange2013"/>

</soap:Header>

<soap:Body>

<m:CreateItem>

<m:Items>

<t:AcceptItem>

<t:Body BodyType="Text">This time works better for the HiPPO.


</t:Body>

<t:ReferenceItemId Id="AAMkADEzOTExYjJkL1AAA="
ChangeKey="CwAAAB/G6X"/>

<t:ProposedStart>2013-11-28T04:00:00Z</t:ProposedStart>

<t:ProposedEnd>2013-11-28T04:30:00Z</t:ProposedEnd>

</t:AcceptItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The response to this request contains the identifier of the calendar item that was added
to the attendee's calendar and a copy of the meeting request that was placed in the
attendee's Deleted Items folder. The response message with the new time proposal was
also saved in the attendee's Sent Items folder (you will need to find the meeting
response message to get a handle on it).

XML

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="815"

MinorBuildNumber="6"

Version="V2_7"

xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"

xmlns="http://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"/>

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:CreateItemResponse
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkAGRmOWE2OWAAA=" ChangeKey="DwAAJsmU"/>

</t:CalendarItem>

<t:MeetingRequest>

<t:ItemId Id="AAMkAGRmOWE2AAABB=" ChangeKey="AAAGJu1A"/>

</t:MeetingRequest>

</m:Items>

</m:CreateItemResponseMessage>

</m:ResponseMessages>

</m:CreateItemResponse>

</s:Body>

</s:Envelope>

The organizer will receive a MeetingResponse message when the attendee responds
with a proposed new meeting time. The MeetingResponse message contains the
proposed new meeting start time and end time, and the identifier of the associated
calendar item in the organizer's calendar. The organizer can use that information to
update their existing calendar item for the meeting. The following is the workflow for
the organizer to respond to a MeetingResponse message that proposes a new meeting
time:

1. Determine whether the ProposedStart or ProposedEnd elements have been set in


the MeetingResponse. If so, go to step 2. If not, the MeetingResponse message
only indicates whether the attendee has accepted, tentatively accepted, or declined
the meeting.

2. Get the organizer's existing calendar item for the meeting by using the EWS
identifier returned in the AssociatedCalendarItemId element.
3. Compare the original start and end time with the proposed new meeting time. If
the proposed new meeting time is acceptable to the organizer, go to step 4.
Otherwise, the meeting organizer can either ignore the proposed meeting time, or
send an email response to the attendee that proposed the new meeting time.

4. (Optional) Perform a GetUserAvailability EWS operation call to find out whether


the proposed time will work for all attendees, including room and resource
mailboxes. (You can also use the ExchangeService.GetUserAvailability EWS
Managed API method to do this.)

5. The organizer can then update their meeting with the new proposed meeting
times and send the updates to all attendees by using the UpdateItem EWS
operation (or the Appointment.Update EWS Managed API method).

The following figure shows the process that occurs between the meeting organizer, the
attendee, and the Exchange server that handled the EWS calls.

Figure 1. Process for proposing a new meeting time


Version differences
The propose new time feature was introduced in Exchange build version 15.00.0800.007.
In earlier versions of Exchange, EWS application users have to send a separate email to
the meeting organizer to request a different meeting time.

See also
Calendars and EWS in Exchange

Create appointments and meetings by using EWS in Exchange 2013

Get appointments and meetings by using EWS in Exchange

Update appointments and meetings by using EWS in Exchange

Delete appointments and cancel meetings by using EWS in Exchange


Process calendar items in batches in
Exchange
Article • 09/15/2021 • 15 minutes to read

Learn how to create, get, update, or delete batches of calendar items in a single call by
using the EWS Managed API or EWS in Exchange.

You can use the EWS Managed API or EWS to work with batches of appointments and
meetings to reduce the number of calls a client makes to an Exchange server. When you
use the EWS Managed API to create, get, update, and delete a batch of calendar items,
you use ExchangeService object methods, whereas when you work with single
calendar items, you use Appointment object methods. If you are using EWS, you use
the same operation for batch calls that you use for single calls.

Table 1. EWS Managed API methods and EWS operations for working with batches of
calendar items

In order to… Use this EWS Managed API Use this EWS
method operation

Create calendar items in batches CreateItems


CreateItem

Get calendar items in batches BindToItems


GetItem

Update calendar items in batches UpdateItems


UpdateItem

Delete calendar items in batches DeleteItems


DeleteItem

In this article, you'll learn how to complete basic tasks for batches of calendar items by
using the EWS Managed API or EWS.

Note that in the EWS Managed API examples in this article, if the methods are called
sequentially, you can create, get, update, and then delete a batch of calendar items.

C#

Collection<ItemId> itemIds = BatchCreateCalendarItems(service);

Collection<Appointment> myAppointments = BatchGetCalendarItems(service,


itemIds);

itemIds = BatchUpdateCalendarItems(service, myAppointments);

BatchDeleteCalendarItemsTwice(service, itemIds);

Create calendar items in batches by using the


EWS Managed API
You can create calendar items in batches by using the CreateItems EWS Managed API
method, as shown in the following example. This example creates three Appointment
objects — a single-instance appointment, a recurring appointment, and a meeting —
and then adds them to a collection.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

public static Collection<ItemId> BatchCreateCalendarItems(ExchangeService


service)

// These are unsaved local instances of an Appointment object.


// Despite the required parameter of an ExchangeService object
(service), no call

// to an Exchange server is made when the objects are instantiated.

// A call to the Exchange server is made when the service.CreateItems()


method is called.

Appointment appt1 = new Appointment(service);

Appointment recurrAppt2 = new Appointment(service);

Appointment meeting3 = new Appointment(service);

// Set the properties for a single instance appointment.

appt1.Subject = "Review current quarterly deliverables";

appt1.Body = "Wrap up all outstanding deliverables for this quarter and


prepare for Q2.";

appt1.Start = DateTime.Now.AddDays(2);

appt1.End = appt1.Start.AddHours(3);

appt1.Location = "My office";

appt1.ReminderMinutesBeforeStart = 30;

// Set the properties for a recurring appointment.

recurrAppt2.Subject = "Food bank delivery";

recurrAppt2.Body = "Deliver the team's weekly food drive collection to


the food bank.";

recurrAppt2.Start = DateTime.Now.AddDays(1);

recurrAppt2.End = recurrAppt2.Start.AddHours(1);

recurrAppt2.Location = "Local food bank";

arecurrAppt2.ReminderMinutesBeforeStart = 30;

DayOfTheWeek[] dow = new DayOfTheWeek[]


{(DayOfTheWeek)recurrAppt2.Start.DayOfWeek};

recurrAppt2.Recurrence = new
Recurrence.WeeklyPattern(recurrAppt2.Start.Date, 1, dow);

recurrAppt2.Recurrence.StartDate = recurrAppt2.Start.Date;

recurrAppt2.Recurrence.NumberOfOccurrences = 10;

// Set the properties for a single instance meeting.

meeting3.Subject = "Code Blast";

meeting3.Body = "Let's get together to finish all the methods and unit
tests for the ContosoLive project.";

meeting3.Start = DateTime.Now.AddDays(3);

meeting3.End = meeting3.Start.AddHours(6);

meeting3.Location = "The lounge";

meeting3.RequiredAttendees.Add("[email protected]");

meeting3.RequiredAttendees.Add("[email protected]");

meeting3.RequiredAttendees.Add("[email protected]");

meeting3.ReminderMinutesBeforeStart = 30;

// Add the appointment objects to a collection.

Collection<Appointment> calendarItems = new Collection<Appointment>() {


appt1, recurrAppt2, meeting3 };

// Instantiate a collection of item IDs to populate from the values that


are returned by the Exchange server.

Collection<ItemId> itemIds = new Collection<ItemId>();

// Send the batch of Appointment objects.

// Note that multiple calls to the Exchange server might be made when
Appointment objects have attachments.

// Note also that the the ID of the item collection passed as the first
parameter to CreateItems is set on return.

ServiceResponseCollection<ServiceResponse> response =
service.CreateItems(calendarItems,

WellKnownFolderName.Calendar,

MessageDisposition.SendAndSaveCopy,

SendInvitationsMode.SendToAllAndSaveCopy);

if (response.OverallResult == ServiceResult.Success)

Console.WriteLine("All appointments and meetings sucessfully


created.");

// Collect the item IDs from the created calendar items.

foreach (Appointment appt in calendarItems)

itemIds.Add(appt.Id);

int counter = 1;

// Show the IDs and errors for each message.

foreach (ServiceResponse resp in response)

// Because item IDs are long, show only five characters.

Console.WriteLine("Result (message {0}), id {1}: {2}", counter,


itemIds[counter - 1].ToString().Substring(0, 5), resp.Result);

Console.WriteLine("Error Code: {0}", resp.ErrorCode);

Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);

counter++;

// Return the collection of item IDs.

return itemIds;

The Appointment objects in the collection can be appointments or meetings, and


either single instances or a recurring series of either.

Create calendar items in batches by using EWS


You can create calendar items in batches by using the CreateItem EWS operation, as
shown in the following code example. This is also the XML request that the EWS
Managed API sends when you use the EWS Managed API to create calendar items in
batches.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SendAndSaveCopy"
SendMeetingInvitations="SendToAllAndSaveCopy">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="calendar" />

</m:SavedItemFolderId>

<m:Items>

<t:CalendarItem>

<t:Subject>Review current quarterly deliverables</t:Subject>

<t:Body BodyType="HTML">Wrap up all outstanding deliverables for


this quarter and prepare for Q2.</t:Body>

<t:ReminderDueBy>2014-01-07T12:13:40.333-08:00</t:ReminderDueBy>

<t:Start>2014-01-08T13:13:37.717-08:00</t:Start>

<t:End>2014-01-08T16:13:37.717-08:00</t:End>

<t:Location>Local food bank</t:Location>

<t:MeetingTimeZone TimeZoneName="Pacific Standard Time" />

</t:CalendarItem>

<t:CalendarItem>

<t:Subject>Food bank delivery</t:Subject>

<t:Body BodyType="HTML">Deliver the team's weekly food drive


collection to the food bank.</t:Body>

<t:Start>2014-01-07T13:13:40.333-08:00</t:Start>

<t:End>2014-01-07T14:13:40.333-08:00</t:End>

<t:Recurrence>

<t:WeeklyRecurrence>

<t:Interval>1</t:Interval>

<t:DaysOfWeek>Tuesday</t:DaysOfWeek>

</t:WeeklyRecurrence>

<t:NumberedRecurrence>

<t:StartDate>2014-01-07-08:00</t:StartDate>

<t:NumberOfOccurrences>10</t:NumberOfOccurrences>

</t:NumberedRecurrence>

</t:Recurrence>

<t:MeetingTimeZone TimeZoneName="Pacific Standard Time" />

</t:CalendarItem>

<t:CalendarItem>

<t:Subject>Code Blast</t:Subject>

<t:Body BodyType="HTML">Let's get together to finish all the


methods and unit tests for the ContosoLive project.</t:Body>

<t:ReminderMinutesBeforeStart>30</t:ReminderMinutesBeforeStart>

<t:Start>2014-01-09T13:13:44.998-08:00</t:Start>

<t:End>2014-01-09T19:13:44.998-08:00</t:End>

<t:Location>The lounge</t:Location>

<t:RequiredAttendees>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

</t:RequiredAttendees>

<t:MeetingTimeZone TimeZoneName="Pacific Standard Time" />

</t:CalendarItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError for each of the new calendar items,
which indicates that each calendar item was created successfully.

Note that the calendar items are either meetings or appointments, or single instances or
a recurring series, according to the element values of each calendar item passed to the
Exchange server.

The following is the response from the server. The ItemId and ChangeKey attributes are
shortened for readability.
XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="847" MinorBuildNumber="12" Version="V2_8"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:CreateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

</m:CreateItemResponseMessage>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

</m:CreateItemResponseMessage>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

</m:CreateItemResponseMessage>

</m:ResponseMessages>

</m:CreateItemResponse>

</s:Body>

</s:Envelope>

Get calendar items in batches by using the EWS


Managed API
You can get calendar items in batches by using the BindToItems EWS Managed API
method, as shown in the following example.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

public static Collection<Appointment> BatchGetCalendarItems(ExchangeService


service, Collection<ItemId> itemIds)

// As a best practice, create a property set that limits the properties


returned by the Bind method to only those that are required.

PropertySet appointmentProps = new PropertySet(BasePropertySet.IdOnly,

AppointmentSchema.Subject,

AppointmentSchema.Body,

AppointmentSchema.ReminderMinutesBeforeStart,

AppointmentSchema.Start,

AppointmentSchema.End,

AppointmentSchema.AppointmentType,

AppointmentSchema.Location,

AppointmentSchema.RequiredAttendees);

ServiceResponseCollection<GetItemResponse> response =
service.BindToItems(itemIds, appointmentProps);

Collection<Appointment> calendarItems = new Collection<Appointment>();

foreach (GetItemResponse items in response)

Item item = items.Item;

Appointment appointmentItem = (Appointment)item;

calendarItems.Add(appointmentItem);

Console.WriteLine("Found item {0}.",


appointmentItem.Id.ToString().Substring(144));

if (response.OverallResult == ServiceResult.Success)

Console.WriteLine("All calendar items retrieved successfully.");

Console.WriteLine("\r\n");

else

int counter = 1;

// List the status of each message.

foreach (ServiceResponse resp in response)

// Because item IDs are long, show only last 8 characters.

Console.WriteLine("Result (message {0}), id {1}: {2}", counter,


itemIds[counter - 1].ToString().Substring(144), resp.Result);

Console.WriteLine("Error Code: {0}", resp.ErrorCode);

Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);

Console.WriteLine("\r\n");

counter++;

return calendarItems;

Get calendar items in batches by using EWS


You can get calendar items in batches by using the GetItem EWS operation, as shown
in the following example. This is also the XML request that the EWS Managed API sends
when you use the EWS Managed API to get calendar items in batches.

The ItemId and ChangeKey attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="item:Body" />

<t:FieldURI FieldURI="item:ReminderMinutesBeforeStart" />

<t:FieldURI FieldURI="calendar:Start" />

<t:FieldURI FieldURI="calendar:End" />

<t:FieldURI FieldURI="calendar:CalendarItemType" />

<t:FieldURI FieldURI="calendar:Location" />

<t:FieldURI FieldURI="calendar:RequiredAttendees" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The server responds to the GetItem request with a GetItemResponse message with
the requested properties for each item, as shown in the following example.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="847" MinorBuildNumber="16" Version="V2_8"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:Subject>Review current quarterly deliverables</t:Subject>

<t:Body BodyType="HTML">

&amp;lt;html&amp;gt;

&amp;lt;head&amp;gt;

&amp;lt;meta http-equiv="Content-Type" content="text/html;


charset=utf-8"&amp;gt;

&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;

Wrap up all outstanding deliverables for this quarter and


prepare for Q2.

&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;

</t:Body>

<t:ReminderMinutesBeforeStart>30</t:ReminderMinutesBeforeStart>

<t:Start>2014-01-19T18:59:07Z</t:Start>

<t:End>2014-01-19T21:59:07Z</t:End>

<t:Location>Local food bank</t:Location>

<t:CalendarItemType>Single</t:CalendarItemType>

</t:CalendarItem>

</m:Items>

</m:GetItemResponseMessage>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:Subject>Food bank delivery</t:Subject>

<t:Body BodyType="HTML">

&amp;lt;html&amp;gt;

&amp;lt;head&amp;gt;

&amp;lt;meta http-equiv="Content-Type" content="text/html;


charset=utf-8"&amp;gt;

&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;

Deliver the team's weekly food drive collection to the food


bank.

&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;

</t:Body>

<t:ReminderMinutesBeforeStart>15</t:ReminderMinutesBeforeStart>

<t:Start>2014-01-18T18:59:07Z</t:Start>

<t:End>2014-01-18T19:59:07Z</t:End>

<t:CalendarItemType>RecurringMaster</t:CalendarItemType>

</t:CalendarItem>

</m:Items>

</m:GetItemResponseMessage>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:Subject>Code Blast</t:Subject>

<t:Body BodyType="HTML">

&amp;lt;html&amp;gt;

&amp;lt;head&amp;gt;

&amp;lt;meta http-equiv="Content-Type" content="text/html;


charset=utf-8"&amp;gt;

&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;

Let's get together to finish all the methods and unit tests
for the ContosoLive project.

&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;

</t:Body>
<t:ReminderMinutesBeforeStart>30</t:ReminderMinutesBeforeStart>

<t:Start>2014-01-20T18:59:08Z</t:Start>

<t:End>2014-01-21T00:59:08Z</t:End>

<t:Location>The lounge</t:Location>

<t:CalendarItemType>Single</t:CalendarItemType>

<t:RequiredAttendees>

<t:Attendee>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

<t:ResponseType>Unknown</t:ResponseType>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

<t:ResponseType>Unknown</t:ResponseType>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

<t:ResponseType>Unknown</t:ResponseType>

</t:Attendee>

</t:RequiredAttendees>

</t:CalendarItem>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

Update calendar items in batches by using the


EWS Managed API
You can update calendar item properties in batches by using the UpdateItems EWS
Managed API method, as shown in the following example.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#
public static Collection<ItemId> BatchUpdateCalendarItems(ExchangeService
service, Collection<Appointment> calendarItems)

int i = 1;

// Appointment item IDs to return.

Collection<ItemId> itemIds = new Collection<ItemId>();

// Update the subject of each calendar item locally.

foreach (Appointment appointment in calendarItems)

// Update the subject of each calendar item in the collection

appointment.Subject = "Company headquarters are moving down the


street to 1234 Contoso Drive!: " + appointment.Subject.ToString();

Console.WriteLine("Updated the subject property for calendar item


{0} of {1}, item id {2}.", i, calendarItems.Count,
appointment.Id.ToString().Substring(0, 5));

i++;

// Collect item IDs to return instead of appointment objects.

itemIds.Add(appointment.Id);

// Send the updated items to the server.

// This method call results in an UpdateItem call to EWS.

ServiceResponseCollection<UpdateItemResponse> response =
service.UpdateItems(calendarItems,

WellKnownFolderName.Calendar,

ConflictResolutionMode.AutoResolve,

MessageDisposition.SendAndSaveCopy,

SendInvitationsOrCancellationsMode.SendToChangedAndSaveCopy);

// Display the result of the UpdateItems method call.

if (response.OverallResult == ServiceResult.Success)

Console.WriteLine("Calendar items successfully updated.\r\n");

else

Console.WriteLine("Not all items were successfully updated on the


server.\r\n");

i = 1;

foreach (ServiceResponse srvResponse in response)

Console.WriteLine("Result for message {0}: {1}", i,


srvResponse.Result);

Console.WriteLine("Error code: {0}", srvResponse.ErrorCode);

Console.WriteLine("ErrorMessage: {0}\r\n",
srvResponse.ErrorMessage);

i++;

return itemIds;

Update calendar items in batches by using EWS


You can update multiple calendar items by using the UpdateItem EWS operation, as
shown in following code example. This is also the XML request that the EWS Managed
API sends when you use the EWS Managed API to update calendar items in batches.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:UpdateItem MessageDisposition="SendAndSaveCopy"
ConflictResolution="AutoResolve"

SendMeetingInvitationsOrCancellations="SendToChangedAndSaveCopy">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="calendar" />

</m:SavedItemFolderId>

<m:ItemChanges>

<t:ItemChange>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:CalendarItem>

<t:Subject>Company headquarters are moving down the street


to 1234 Contoso Drive!: Review current quarterly deliverables

</t:Subject>

</t:CalendarItem>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

<t:ItemChange>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:CalendarItem>

<t:Subject>Company headquarters are moving down the street


to 1234 Contoso Drive!: Food bank delivery</t:Subject>

</t:CalendarItem>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

<t:ItemChange>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:CalendarItem>

<t:Subject>Company headquarters are moving down the street


to 1234 Contoso Drive!: Code Blast</t:Subject>

</t:CalendarItem>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

</m:ItemChanges>

</m:UpdateItem>

</soap:Body>

</soap:Envelope>

The server responds to the UpdateItem request with an UpdateItemResponse


message that includes a ResponseCode value of NoError, which indicates that each of
the updates was saved successfully on the server. Any conflicts are reported in the
ConflictResult element.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="859" MinorBuildNumber="13"

Version="V2_8"
xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:UpdateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:UpdateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

<m:ConflictResults>

<t:Count>1</t:Count>

</m:ConflictResults>

</m:UpdateItemResponseMessage>

<m:UpdateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

<m:ConflictResults>

<t:Count>1</t:Count>

</m:ConflictResults>

</m:UpdateItemResponseMessage>

<m:UpdateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</t:CalendarItem>

</m:Items>

<m:ConflictResults>

<t:Count>1</t:Count>

</m:ConflictResults>

</m:UpdateItemResponseMessage>

</m:ResponseMessages>

</m:UpdateItemResponse>

</s:Body>

</s:Envelope>

Delete calendar items in batches by using the


EWS Managed API
You can delete calendar items in batches by using the DeleteItems EWS Managed API
method, as shown in the following example. This example makes the deletion request a
second time to show that no exceptions are thrown but that the server will return an
ErrorItemNotFound error to indicate that the items to delete weren't in the store when
the call was made. This error is returned if the item has already been deleted, or if a bad
item ID is passed to the server.
This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

public static void BatchDeleteCalendarItemsTwice(ExchangeService service,


Collection<ItemId> itemIds)

// Delete the batch of appointment objects

// This method call results in a DeleteItem call to EWS.

ServiceResponseCollection<ServiceResponse> response =
service.DeleteItems(itemIds,

DeleteMode.MoveToDeletedItems,

SendCancellationsMode.SendToAllAndSaveCopy,

AffectedTaskOccurrence.AllOccurrences);

int counter = 1;

// Show the IDs and errors for each message.

foreach (ServiceResponse resp in response)

// Because item IDs are long, show only five characters.

Console.WriteLine("Result (message {0}), id {1}: {2}", counter,


itemIds[counter - 1].ToString().Substring(0, 5), resp.Result);

Console.WriteLine("Error Code: {0}", resp.ErrorCode);

Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);

counter++;

// Now attempt to delete the same items again.

response = service.DeleteItems(itemIds,

DeleteMode.MoveToDeletedItems,

SendCancellationsMode.SendToAllAndSaveCopy,

AffectedTaskOccurrence.AllOccurrences);

counter = 1;

// Show the IDs and errors for each message.

foreach (ServiceResponse resp in response)

// Because item IDs are long, show only five characters.

Console.WriteLine("Result (message {0}), id {1}: {2}", counter,


itemIds[counter - 1].ToString().Substring(0, 5), resp.Result);

Console.WriteLine("Error Code: {0}", resp.ErrorCode);

Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);

counter++;

When the DeleteItems method is called the second time, no exception is thrown, but
the server returns an ErrorItemNotFound error in the result.
Delete calendar items in batches by using EWS
You can delete calendar items in batches by using the DeleteItem EWS operation, as
shown in the following code example. This is also the XML request that the EWS
Managed API sends when you use the EWS Managed API to delete calendar items in
batches.

The ItemId and ChangeKey attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:DeleteItem DeleteType="MoveToDeletedItems"

AffectedTaskOccurrences="AllOccurrences"

SendMeetingCancellations="SendToAllAndSaveCopy">

<m:ItemIds>

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

<t:ItemId Id="AAMkA" ChangeKey="DwAAA" />

</m:ItemIds>

</m:DeleteItem>

</soap:Body>

</soap:Envelope>

The server responds to the DeleteItem request with a DeleteItemResponse message


that includes a ResponseCode value of NoError for each item that was removed.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="859" MinorBuildNumber="13" Version="V2_8"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:DeleteItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:DeleteItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

</m:DeleteItemResponseMessage>

<m:DeleteItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

</m:DeleteItemResponseMessage>

<m:DeleteItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

</m:DeleteItemResponseMessage>

</m:ResponseMessages>

</m:DeleteItemResponse>

</s:Body>

</s:Envelope>

Note that if the DeleteItem request is made when the associated items have already
been deleted, no exception will be thrown, but the server will return an
ErrorItemNotFound error in the result. The following example shows the server
response to a DeleteItem request when the associated items have already been deleted.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="859" MinorBuildNumber="13" Version="V2_8"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:DeleteItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:DeleteItemResponseMessage ResponseClass="Error">

<m:MessageText>The specified object was not found in the store.


</m:MessageText>

<m:ResponseCode>ErrorItemNotFound</m:ResponseCode>

<m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>

</m:DeleteItemResponseMessage>

<m:DeleteItemResponseMessage ResponseClass="Error">

<m:MessageText>The specified object was not found in the store.


</m:MessageText>

<m:ResponseCode>ErrorItemNotFound</m:ResponseCode>

<m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>

</m:DeleteItemResponseMessage>

<m:DeleteItemResponseMessage ResponseClass="Error">

<m:MessageText>The specified object was not found in the store.


</m:MessageText>

<m:ResponseCode>ErrorItemNotFound</m:ResponseCode>

<m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>

</m:DeleteItemResponseMessage>

</m:ResponseMessages>

</m:DeleteItemResponse>

</s:Body>

</s:Envelope>

Verifying that a batch process completed


successfully
When one or more calendar items in a batched request can't be processed as requested,
an error is returned for each calendar item that failed, and the rest of the calendar items
in the batch are processed as expected. Failures in batch processing can occur if the
item was deleted, and therefore can't be sent, retrieved, or updated, or if the item
moved to a different folder, and therefore has a new item ID, and cannot be modified
with the item ID sent. The information in this section shows how to get error details
about failures in batch processing of calendar items.

To verify the success of a batch process by using the EWS Managed API, you can check
that the OverallResult property of the ServiceResponseCollection is equal to
ServiceResult.Success . If so, all the calendar items were processed successfully. If the
OverallResult is not equal to ServiceResult.Success, one or more of the calendar items
were not processed successfully. Each of the objects returned in the
ServiceResponseCollection contains the following properties:

ErrorCode
ErrorDetails

ErrorMessage

ErrorProperties

Result

These properties contain information about why the calendar items could not be
processed as requested. The examples in this article print out the Result, ErrorCode, and
ErrorMessage for each failed item. You can use these results to investigate the issue.

For EWS, to verify the success of a batched process, check the ResponseClass attribute
for each item being processed. The following is the basic structure of the
ResponseMessageType, the base type from which all response messages are derived.

XML

<ResponseMessage ResponseClass="Success | Warning | Error">

<MessageText/>

<ResponseCode/>

<DescriptiveLinkKey/>

<MessageXml/>

</ResponseMessage>

The ResponseClass attribute is set to Success if the calendar item was processed
successfully, or Error if it was not processed successfully. For calendar items, you will not
encounter a Warning during batch processing. If the ResponseClass is Success, the
ResponseCode element that follows is also always set to NoError. If the
ResponseClass is Error, you need to check the values of the MessageText ,
ResponseCode, and MessageXml elements to determine what caused the problem.
DescriptiveLinkKey is currently unused.

See also
Calendars and EWS in Exchange

Get appointments and meetings by using EWS in Exchange

Update appointments and meetings by using EWS in Exchange

Delete appointments and cancel meetings by using EWS in Exchange

Process calendar items in batches in Exchange

Throttling implications for EWS batch requests


Recurrence patterns and EWS
Article • 09/15/2021 • 7 minutes to read

Learn about recurrence patterns and recurring series in Exchange.

A recurring series is an appointment or meeting that repeats according to a defined


pattern. A recurring series can either have a specific number of occurrences or can
repeat indefinitely. Additionally, a recurring series can have exceptions that don't follow
the pattern of the rest of the occurrences, and can have occurrences that have been
deleted from the pattern. You can use the EWS Managed API and EWS to work with
recurring series and their associated calendar items.

Recurring calendar items


All calendar items fall into one of the following four categories:

Non-recurring calendar items

Recurring masters

Occurrences in a series

Modified occurrences in a series, known as exceptions

In this article, we'll look at the three types of calendar items that are part of a recurring
series.

It's helpful to understand how recurring series are implemented on the Exchange server.
Instead of creating a separate distinct item for each occurrence in a recurring series, the
server creates only one actual item in the calendar, known as the recurring master. The
format of a recurring master is very similar to a non-recurring appointment, with the
addition of recurrence pattern information. The server then generates occurrences
based on the recurrence pattern in response to client requests for appointment
information, using a process called expansion. These generated occurrences are not
permanently stored on the server. This is important to understand because the way that
you search for calendar items determines what information you receive and whether
expansion occurs.

Recurrence patterns
The key piece to a recurring series that makes expansion possible is the recurrence
pattern. The recurrence pattern is found on the recurring master, and describes a set of
criteria for calculating occurrences based on the date and time of the recurring master.

Table 1. Available recurrence patterns

EWS Managed API class EWS element Examples

Recurrence.DailyPattern
DailyRecurrence
Repeat every day.
Repeat every other day.

Recurrence.MonthlyPattern
AbsoluteMonthlyRecurrence Repeat every month on
the tenth day of the
month.
Repeat every other
month on the twenty-
first day of the month.

Recurrence.RelativeMonthlyPattern RelativeMonthlyRecurrence
Repeat on the second
Tuesday of every month.
Repeat on the third
Thursday of the month
every three months.

Recurrence.RelativeYearlyPattern
RelativeYearlyRecurrence
Repeat on the first
Monday of August every
year.

Recurrence.WeeklyPattern
WeeklyRecurrence
Repeat every Monday.
Repeat every Tuesday
and Thursday every
other week.

Recurrence.YearlyPattern
AbsoluteYearlyRecurrence
Repeat on September
1st every year.

The other important piece of information for a recurrence pattern is when the
recurrence ends. This can be expressed as either a set number of occurrences, as an end
date, or as having no end.

Table 2. Options for the end of a recurring series

EWS Managed API EWS element Description


method/property

Recurrence.NumberOfOccurrences NumberedRecurrence The value of this property or


element specifies the number
of occurrences.
EWS Managed API EWS element Description
method/property

Recurrence.EndDate
EndDateRecurrence
The last occurrence in the
series falls on or before the
date specified by this property
or element.

Recurrence.HasEnd
NoEndRecurrence
The series has no end.
Recurrence.NeverEnds

Expanded vs. non-expanded views


Using the FindAppointments method in the EWS Managed API (or the FindItem
operation with a CalendarView element in EWS) invokes the expansion process. This
hides recurring master appointments from the result set, and instead presents an
expanded view of that recurring series. Occurrences of and exceptions to the recurring
master that fall within the parameters of the calendar view are included in the result set.
Conversely, using the FindItems method in the EWS Managed API (or the FindItem
operation with a IndexedPageItemView or FractionalPageItemView element in EWS),
does not invoke the expansion process, and occurrences and exceptions are not
included. Let's look at an example comparing the two methods.

Table 3. Methods and operations for finding appointments

EWS Managed API method EWS operation Expands Items included in


series? results

ExchangeService.FindAppointments FindItem operation Yes Non-recurring


with a CalendarView appointments,
element single
occurrences of
recurring series,
and exceptions
to recurring
series

ExchangeService.FindItems
FindItem operation No Non-recurring
with an appointments
IndexedPageItemView and recurring
element or master
FractionalPageItemView appointments
element
Sadie has just signed her son up for swim team. The team has practice every Wednesday
morning at 8:30 AM, starting July 2, with the last practice being on August 6. Not
wanting to forget about practice, Sadie adds a recurring appointment to her calendar to
remind her.

Table 4. Sadie's recurring appointment

Appointment field Value

Subject Swim Team Practice

Start July 2, 2014 8:30 AM

End July 2, 2014 10:00 AM

Recurs Every Wednesday

Last occurrence August 6, 2014 8:30 AM

A quick look at a calendar shows that the team will have a total of six practices.
However, there aren't six distinct appointment items in the calendar. Instead, there is
just one recurring master appointment representing the series.

Now let's look at finding appointments on Sadie's calendar that occur within the month
of July. The following code example uses the FindItems method in the Exchange
Managed API to produce a non-expanded view of Sadie's calendar.

C#

PropertySet propSet = new PropertySet(AppointmentSchema.Subject,

AppointmentSchema.Location,

AppointmentSchema.Start,

AppointmentSchema.End,

AppointmentSchema.AppointmentType);

#region FindItems + ItemView method

ItemView itemView = new ItemView(100);

itemView.PropertySet = propSet;

List<SearchFilter> filterList = new List<SearchFilter>();

// Find appointments that start after midnight on July 1, 2014.

SearchFilter.IsGreaterThan startFilter = new


SearchFilter.IsGreaterThan(AppointmentSchema.Start,

new DateTime(2014, 7, 1));

// Find appointments that end before midnight on July 31, 2014

SearchFilter.IsLessThan endFilter = new


SearchFilter.IsLessThan(AppointmentSchema.End,

new DateTime(2014, 7, 31));

filterList.Add(startFilter);

filterList.Add(endFilter);

SearchFilter.SearchFilterCollection calendarFilter = new


SearchFilter.SearchFilterCollection(LogicalOperator.And, filterList);

// This results in a call to EWS.


FindItemsResults<Item> results =
service.FindItems(WellKnownFolderName.Calendar, calendarFilter, itemView);

foreach(Item appt in results.Items)

Console.WriteLine(appt.Subject);

That code results in the following FindItem operation request with an


IndexedPageItemView element.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:FindItem Traversal="Shallow">

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="calendar:Location" />

<t:FieldURI FieldURI="calendar:Start" />

<t:FieldURI FieldURI="calendar:End" />

<t:FieldURI FieldURI="calendar:CalendarItemType" />

</t:AdditionalProperties>

</m:ItemShape>

<m:IndexedPageItemView MaxEntriesReturned="100" Offset="0"


BasePoint="Beginning" />

<m:Restriction>

<t:And>

<t:IsGreaterThan>

<t:FieldURI FieldURI="calendar:Start" />

<t:FieldURIOrConstant>

<t:Constant Value="2014-07-01T07:00:00.000Z" />

</t:FieldURIOrConstant>

</t:IsGreaterThan>

<t:IsLessThan>

<t:FieldURI FieldURI="calendar:End" />

<t:FieldURIOrConstant>

<t:Constant Value="2014-07-31T07:00:00.000Z" />

</t:FieldURIOrConstant>

</t:IsLessThan>

</t:And>

</m:Restriction>

<m:ParentFolderIds>

<t:DistinguishedFolderId Id="calendar" />

</m:ParentFolderIds>

</m:FindItem>

</soap:Body>

</soap:Envelope>

The server's response includes only a single item, the recurring master, indicated by the
CalendarItemType element value of RecurringMaster. The value of the ItemId
element has been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="939" MinorBuildNumber="16" Version="V2_11"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:FindItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:FindItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootFolder IndexedPagingOffset="1" TotalItemsInView="1"


IncludesLastItemInRange="true">

<t:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkADA5..." ChangeKey="DwAAABYA..." />

<t:Subject>Swim Team Practice</t:Subject>

<t:Start>2014-07-02T15:30:00Z</t:Start>

<t:End>2014-07-02T17:00:00Z</t:End>

<t:Location>Neighborhood Swimming Pool</t:Location>

<t:CalendarItemType>RecurringMaster</t:CalendarItemType>

</t:CalendarItem>

</t:Items>

</m:RootFolder>

</m:FindItemResponseMessage>

</m:ResponseMessages>

</m:FindItemResponse>

</s:Body>

</s:Envelope>

Now let's compare with an expanded view. The following code example uses the
FindAppointments method in the EWS Managed API to create an expanded view of
Sadie's calendar.

C#

PropertySet propSet = new PropertySet(AppointmentSchema.Subject,

AppointmentSchema.Location,

AppointmentSchema.Start,

AppointmentSchema.End,

AppointmentSchema.AppointmentType);

CalendarView calView = new CalendarView(new DateTime(2014, 7, 1),

new DateTime(2014, 7, 31));

calView.PropertySet = propSet;

FindItemsResults<Appointment> results =
service.FindAppointments(WellKnownFolderName.Calendar, calView);

foreach(Appointment appt in results.Items)

Console.WriteLine(appt.Subject);

This code results in the following FindItem operation request with a CalendarView
element.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Pacific Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:FindItem Traversal="Shallow">

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="calendar:Location" />

<t:FieldURI FieldURI="calendar:Start" />

<t:FieldURI FieldURI="calendar:End" />

<t:FieldURI FieldURI="calendar:CalendarItemType" />

</t:AdditionalProperties>

</m:ItemShape>

<m:CalendarView StartDate="2014-07-01T07:00:00.000Z" EndDate="2014-07-


31T07:00:00.000Z" />

<m:ParentFolderIds>

<t:DistinguishedFolderId Id="calendar" />

</m:ParentFolderIds>

</m:FindItem>

</soap:Body>

</soap:Envelope>

This time, the server response includes five occurrences, one for each Wednesday in July.
The CalendarItemType elements on these items all have a value of Occurrence. Note
that the recurring master is not present in the response. The values of the ItemId
elements have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="939" MinorBuildNumber="16" Version="V2_11"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:FindItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:FindItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootFolder TotalItemsInView="5" IncludesLastItemInRange="true">

<t:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkADA6..." ChangeKey="DwAAABYA..." />

<t:Subject>Swim Team Practice</t:Subject>

<t:Start>2014-07-02T15:30:00Z</t:Start>

<t:End>2014-07-02T17:00:00Z</t:End>

<t:Location>Neighborhood Swimming Pool</t:Location>

<t:CalendarItemType>Occurrence</t:CalendarItemType>

</t:CalendarItem>

<t:CalendarItem>

<t:ItemId Id="AAMkADA7..." ChangeKey="DwAAABYA..." />

<t:Subject>Swim Team Practice</t:Subject>

<t:Start>2014-07-09T15:30:00Z</t:Start>

<t:End>2014-07-09T17:00:00Z</t:End>

<t:Location>Neighborhood Swimming Pool</t:Location>

<t:CalendarItemType>Occurrence</t:CalendarItemType>

</t:CalendarItem>

<t:CalendarItem>

<t:ItemId Id="AAMkADA8..." ChangeKey="DwAAABYA..." />

<t:Subject>Swim Team Practice</t:Subject>

<t:Start>2014-07-16T15:30:00Z</t:Start>

<t:End>2014-07-16T17:00:00Z</t:End>

<t:Location>Neighborhood Swimming Pool</t:Location>

<t:CalendarItemType>Occurrence</t:CalendarItemType>

</t:CalendarItem>

<t:CalendarItem>

<t:ItemId Id="AAMkADA9..." ChangeKey="DwAAABYA..." />

<t:Subject>Swim Team Practice</t:Subject>

<t:Start>2014-07-23T15:30:00Z</t:Start>

<t:End>2014-07-23T17:00:00Z</t:End>

<t:Location>Neighborhood Swimming Pool</t:Location>

<t:CalendarItemType>Occurrence</t:CalendarItemType>

</t:CalendarItem>

<t:CalendarItem>

<t:ItemId Id="AAMkADAA..." ChangeKey="DwAAABYA..." />

<t:Subject>Swim Team Practice</t:Subject>

<t:Start>2014-07-30T15:30:00Z</t:Start>

<t:End>2014-07-30T17:00:00Z</t:End>

<t:Location>Neighborhood Swimming Pool</t:Location>

<t:CalendarItemType>Occurrence</t:CalendarItemType>

</t:CalendarItem>

</t:Items>

</m:RootFolder>

</m:FindItemResponseMessage>

</m:ResponseMessages>

</m:FindItemResponse>

</s:Body>

</s:Envelope>

After you have a recurring master, an occurrence, or an exception, you can always
retrieve the other related items. Given an occurrence or exception, you can retrieve the
recurring master, and vice versa.

Working with recurring calendar items


You use all the same methods and operations to work with recurring series as you use to
work with non-recurring calendar items. The difference is that, depending on the item
you use to invoke those methods or operations, the actions you take can apply to the
entire series, or just a single occurrence. Actions taken on the recurring master will apply
to all occurrences in the series, while actions taken to a single occurrence or exception
will only apply to that occurrence or exception.

In this section
Access a recurring series by using EWS in Exchange
Create a recurring series by using EWS in Exchange

Delete appointments in a recurring series by using EWS in Exchange

Update a recurring series by using EWS

Update a recurring series by using EWS in Exchange

See also
Calendars and EWS in Exchange

Develop web service clients for Exchange

Get appointments and meetings by using EWS in Exchange


Access a recurring series by using EWS
in Exchange
Article • 09/15/2021 • 6 minutes to read

Learn how to access calendar items in a recurring series by using the EWS Managed API
or EWS in Exchange.

A recurring series of appointments or meetings is made up of a recurring master, a


number of occurrences in a series that repeat according to a set pattern, and, optionally,
sets of occurrences that were changed and that were deleted. You can use the EWS
Managed API or EWS to access calendar items in a recurring series. This enables you to:

Check to see if a calendar item associated with an item ID is a recurring master, an


occurrence in a series, or an exception to a series.

Search your calendar folder for recurrence appointments.

Get related recurrence calendar items

Iterate through occurrences in a series, occurrence exceptions, or occurrence


deletions.

Get a collection of recurring calendar items by


using the EWS Managed API
If you want to retrieve a collection of appointments, you can use the
ExchangeService.FindAppointments method to retrieve all appointments between a
given start and end date, and then add all calendar items with an appointment type of
Occurrence or Exception to a collection, as shown in the following example.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

public static Collection<Appointment>


FindRecurringCalendarItems(ExchangeService service,

DateTime
startSearchDate,

DateTime
endSearchDate)

// Instantiate a collection to hold occurrences and exception calendar


items.

Collection<Appointment> foundAppointments = new Collection<Appointment>


();

// Create a calendar view to search the calendar folder and specify the
properties to return.

CalendarView calView = new CalendarView(startSearchDate, endSearchDate);

calView.PropertySet = new PropertySet(BasePropertySet.IdOnly,


AppointmentSchema.Subject,

AppointmentSchema.Start,

AppointmentSchema.IsRecurring,

AppointmentSchema.AppointmentType);

// Retrieve a collection of calendar items.

FindItemsResults<Appointment> findResults =
service.FindAppointments(WellKnownFolderName.Calendar, calView);

// Add all calendar items in your view that are occurrences or


exceptions to your collection.

foreach (Appointment appt in findResults.Items)

if (appt.AppointmentType == AppointmentType.Occurrence ||
appt.AppointmentType == AppointmentType.Exception)

foundAppointments.Add(appt);

else

Console.WriteLine("Discarding calendar item of type {0}.",


appt.AppointmentType);

return foundAppointments;

Note that recurring master calendar items aren't returned in a call to


FindAppointments. If you want to retrieve recurring masters, or you want a more
general approach to retrieving calendar items, you need to use
ExchangeService.FindItems . You can then use a search filter to retrieve only items with
a start date greater than or equal to a date you choose, and an item view to limit the
number of items to return. Note that a recurring master with a start date earlier than the
start date in your search will not be found, even if occurrences occur in this range.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

public static Collection<Appointment>


FindCalendarItemsByAppointmentType(ExchangeService service,

AppointmentType myAppointmentType,

DateTime startSearchDate)

Collection<Appointment> foundAppointments = new Collection<Appointment>


();

// Create a search filter based on the start search date.

SearchFilter.SearchFilterCollection searchFilter = new


SearchFilter.SearchFilterCollection();

searchFilter.Add(new
SearchFilter.IsGreaterThanOrEqualTo(AppointmentSchema.Start,
startSearchDate));

// Create an item view to specify which properties to return.

ItemView view = new ItemView(20);

view.PropertySet = new PropertySet(BasePropertySet.IdOnly,

AppointmentSchema.Subject,

AppointmentSchema.Start,

AppointmentSchema.AppointmentType,

AppointmentSchema.IsRecurring);

// Get the appointment items from the server with the properties we
specified.

FindItemsResults<Item> findResults =
service.FindItems(WellKnownFolderName.Calendar, searchFilter, view);

// Add each of the appointments of the type you want to the collection.

foreach (Item item in findResults.Items)

Appointment appt = item as Appointment;

if (appt.AppointmentType == myAppointmentType)

foundAppointments.Add(appt);

return foundAppointments;

Get related recurrence calendar items by using


the EWS Managed API
Sometimes you have one piece of the puzzle, but to solve it you need the rest of the
pieces. If you have the item ID for a recurrence calendar item, you can get the other
pieces you need by using one of several EWS Managed API properties or methods.

Table 1. EWS Managed API property or method to use to get related recurrence
calendar items

If you have the item ID You can get… By using the…


for…
If you have the item ID You can get… By using the…
for…

The recurring master The first occurrence in a Appointment.FirstOccurrence


calendar item series property
The last occurrence in a Appointment.LastOccurrence
series property
The exceptions to a series Appointment.ModifiedOccurrences
The deleted property
appointments in a series Appointment.DeletedOccurrences
Any occurrence (given its property
index) Appointment.BindToOccurrence
method

A single occurrence in a The recurring master Appointment.BindToRecurringMaster


series method

Any calendar item (an The appointment type Appointment.AppointmentType


Appointment object) enumeration value property

The following code example shows how to get a recurring master, the first or last
occurrence in a series, or an occurrence given its index.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service.

C#

public static void GetRelatedRecurrenceCalendarItems(ExchangeService


service, ItemId itemId)

Appointment calendarItem = Appointment.Bind(service, itemId, new


PropertySet(AppointmentSchema.AppointmentType));

Appointment recurrMaster = new Appointment(service);

PropertySet props = new PropertySet(AppointmentSchema.AppointmentType,

AppointmentSchema.Subject,

AppointmentSchema.FirstOccurrence,

AppointmentSchema.LastOccurrence,

AppointmentSchema.ModifiedOccurrences,

AppointmentSchema.DeletedOccurrences);

// If the item ID is not for a recurring master, retrieve the recurring


master for the series.

switch (calendarItem.AppointmentType)

// Calendar item is a recurring master so use Appointment.Bind

case AppointmentType.RecurringMaster:

recurrMaster = Appointment.Bind(service, itemId, props);

break;

// The calendar item is a single instance meeting, so there are no


instances to modify or delete.

case AppointmentType.Single:

Console.WriteLine("Item id must reference a calendar item that


is part of a recurring series.");
return;

// The calendar item is an occurrence in the series, so use


BindToRecurringMaster.

case AppointmentType.Occurrence:

recurrMaster = Appointment.BindToRecurringMaster(service,
itemId, props);

break;

// The calendar item is an exception to the series, so use


BindToRecurringMaster.

case AppointmentType.Exception:

recurrMaster = Appointment.BindToRecurringMaster(service,
itemId, props);

break;

// View the first occurrence, last occurrence, and number of modified


and deleted occurrences associated with the recurring master.

Console.WriteLine("Information for the {0} recurring series:",


recurrMaster.Subject);

Console.WriteLine("The start time for the first appointment with id


\t{0} was on \t{1}.",

recurrMaster.FirstOccurrence.ItemId.ToString().Substring(144),

recurrMaster.FirstOccurrence.Start.ToString());

Console.WriteLine("The start time for the last appointment with id \t{0}


will be on \t{1}.",

recurrMaster.LastOccurrence.ItemId.ToString().Substring(144),

recurrMaster.LastOccurrence.Start.ToString());

Console.WriteLine("There are {0} modified occurrences and {1} deleted


occurrences.",

recurrMaster.ModifiedOccurrences == null ? "no" :


recurrMaster.ModifiedOccurrences.Count.ToString(),

recurrMaster.DeletedOccurrences == null ? "no" :


recurrMaster.DeletedOccurrences.Count.ToString());

// Bind to the first occurrence of a series by using its index.

Appointment firstOccurrence = Appointment.BindToOccurrence(service,

recurrMaster.Id,

1, // Index
of first item is 1, not 0.

new
PropertySet(AppointmentSchema.AppointmentType,

AppointmentSchema.Start));

Console.WriteLine("Compare the start times for a recurring master's


first occurrence " +

"and the occurrence found at index 1 using the


BindToOccurrence method:");

Console.WriteLine("The appointment at index 1 has a start time


of\t\t\t\t {0}\n" +

"Which matches that of the first occurrence on the


recurring master: \t {1}",

firstOccurrence.Start.ToString(),

recurrMaster.FirstOccurrence.Start.ToString());

Access calendar items in a recurring series by


using EWS
Accessing calendar items in a recurring series is very similar to accessing single instances
of calendar items. You use a GetItem operation request, specifying the properties you
want, with the OccurrenceItemId of the appointment instance you need. The
OccurrenceItemId contains the ItemID of the occurrence's recurring master, as well as
its index value in the series.

The following XML shows the GetItem request used to return an occurrence in a series
specified by its index. Note that the ItemID of the recurring master has been shortened
for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="calendar:CalendarItemType" />

<t:FieldURI FieldURI="calendar:Start" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:OccurrenceItemId RecurringMasterId="AAMkA" InstanceIndex="1" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The server responds to the GetItem request with a GetItemResponse message that
includes a ResponseCode value of NoError, which indicates that the email was created
successfully, and the ItemId of the newly created message.

See also
Calendars and EWS in Exchange
Get appointments and meetings by using EWS in Exchange
Create a recurring series by using EWS
in Exchange
Article • 09/15/2021 • 6 minutes to read

Learn how to create recurring meetings by using the EWS Managed API or EWS in
Exchange.

Creating a recurring appointment or meeting isn't all that much different than creating a
single instance appointment or meeting. You just need to assign values to a few
additional recurrence-related properties. These are set on an
ExchangeService.Appointment object's Recurrence object (if you're using the EWS
Managed API), or the Recurrence child element of a CalendarItem element (if you're
using EWS). One thing to consider when you create a recurring, rather than a single-
instance meeting, is that the calendar item you create is the recurring master for a
series. A number of properties are set only on a recurring master; these properties can
help you find, modify, or delete individual instances in a series. For this reason, it might
be useful to keep track of the ID of the recurring master when you create a recurring
series.

Table 1. Properties set on recurring master calendar items

EWS Managed API class or property EWS XML element Description

Recurrence class
Recurrence Contains recurrence-related
The Recurrence class is the base class (RecurrenceType)
information, including the
for a derived pattern class, either recurrence pattern (daily,
IntervalPattern , weekly, monthly, and so on),
RelativeYearlyPattern , or start and end date, number of
YearlyPattern . occurrences, and so on.

FirstOccurrence property
FirstOccurrence
Contains the start and end
times and the item ID for the
first meeting in a series.

LastOccurrence property
LastOccurrence
Contains the start and end
times and the item ID for the
last meeting in a series.

ModifiedOccurrences property
ModifiedOccurrences Contains the set of all
meetings in the series that
have been modified from the
original recurrence pattern.
EWS Managed API class or property EWS XML element Description

DeletedOccurrences property
DeletedOccurrences
Contains the set of all
meetings in the series that
have been deleted from the
original recurrence pattern.

Because meetings are essentially appointments that include attendees, the code
examples in this article show how to create recurring meetings. If you want to create a
recurring appointment, you can modify the examples by removing code related to
attendees.

Create a recurring meeting by using the EWS


Managed API
The following code example shows how to create a recurring meeting. First, assign
values to the properties of an Appointment object used to create a meeting, then use
the Save method to save the recurring series to your calendar folder, and send
meeting requests to your attendees. Finally, use the Appointment.Bind method to
look at the values set on the recurring master for the recurring series you just created.

This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service. The method in this example
returns the item ID of the recurring series' recurring master.

C#

public static ItemId CreateARecurringMeeting(ExchangeService service)

{ Appointment recurrMeeting = new Appointment(service);

// Set the properties you need to create a meeting.

recurrMeeting.Subject = "Weekly Update Meeting";

recurrMeeting.Body = "Come hear about how the project is coming


along!";

recurrMeeting.Start = DateTime.Now.AddDays(1);

recurrMeeting.End = recurrMeeting.Start.AddHours(1);

recurrMeeting.Location = "Contoso Main Gallery";

recurrMeeting.RequiredAttendees.Add("[email protected]");

recurrMeeting.RequiredAttendees.Add("[email protected]");

recurrMeeting.RequiredAttendees.Add("[email protected]");
recurrMeeting.ReminderMinutesBeforeStart = 30;

DayOfTheWeek[] dow = new DayOfTheWeek[] {


(DayOfTheWeek)recurrMeeting.Start.DayOfWeek };

// The following are the recurrence-specific properties for the


meeting.

recurrMeeting.Recurrence = new
Recurrence.WeeklyPattern(recurrMeeting.Start.Date, 1, dow);

recurrMeeting.Recurrence.StartDate = recurrMeeting.Start.Date;

recurrMeeting.Recurrence.NumberOfOccurrences = 10;

// This method results in in a CreateItem call to EWS.

recurrMeeting.Save(SendInvitationsMode.SendToAllAndSaveCopy);

// Retrieve the meeting subject and the properties that are set on a
recurring master when a recurring series is created.

recurrMeeting = Appointment.Bind(service, recurrMeeting.Id, new


PropertySet(AppointmentSchema.Subject,

AppointmentSchema.AppointmentType,

AppointmentSchema.Recurrence,

AppointmentSchema.FirstOccurrence,

AppointmentSchema.LastOccurrence,

AppointmentSchema.ModifiedOccurrences,

AppointmentSchema.DeletedOccurrences));

// Print out the recurring master properties.

Console.WriteLine("\nAppointment created: " +


recurrMeeting.Subject);

Console.WriteLine("Appointment Type: {0}\n",


recurrMeeting.AppointmentType);

Console.WriteLine("These property values are always null unless the


item is a recurring master:\n");

Console.WriteLine("\tRecurrence pattern: {0}",


recurrMeeting.Recurrence.ToString());

Console.WriteLine("\tRecurring series start Date: {0}",


recurrMeeting.Recurrence.StartDate.ToString());

Console.WriteLine("\tRecurring series end Date: {0}",

recurrMeeting.Recurrence.EndDate == null ? "Null" :


recurrMeeting.Recurrence.EndDate.ToString());

Console.WriteLine("\tHas end: {0}",


recurrMeeting.Recurrence.HasEnd.ToString());

Console.WriteLine("\tNumber of occurrances: {0}",


recurrMeeting.Recurrence.NumberOfOccurrences);

Console.WriteLine("\tLast 24 characters of the first occurrence's


item ID:\t {0}",

recurrMeeting.FirstOccurrence.ItemId.ToString().Substring(144));

Console.WriteLine("\tLast 24 characters of the last occurrence's


item ID:\t {0}",

recurrMeeting.LastOccurrence.ItemId.ToString().Substring(144));

Console.WriteLine("\tModified Occurrences: {0}",

(recurrMeeting.ModifiedOccurrences == null ? "Null"


: recurrMeeting.ModifiedOccurrences.Count.ToString()));

Console.WriteLine("\tDeleted Occurrences: {0}",

recurrMeeting.DeletedOccurrences == null ? "Null" :


recurrMeeting.ModifiedOccurrences.Count.ToString());

// Return the ID of the recurring master.

return recurrMeeting.Id;

Create a recurring meeting by using EWS


The request and response XML in the following examples correspond to calls made to
create a recurring meeting by using the EWS Managed API. Note that other than setting
recurrence-specific values on the Recurrence element, the request is essentially the
same as one you would use to create a single-instance appointment. The following
example shows the request XML when you use the CreateItem operation to create a
meeting.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Name="(UTC-08:00) Pacific Time (US &amp;amp;
Canada)" Id="Pacific Standard Time">

<t:Periods>

<t:Period Bias="P0DT8H0M0.0S" Name="Standard" Id="Std" />

<t:Period Bias="P0DT7H0M0.0S" Name="Daylight" Id="Dlt/1" />

<t:Period Bias="P0DT7H0M0.0S" Name="Daylight" Id="Dlt/2007" />

</t:Periods>

<t:TransitionsGroups>

<t:TransitionsGroup Id="0">

<t:RecurringDayTransition>

<t:To Kind="Period">Dlt/1</t:To>

<t:TimeOffset>P0DT2H0M0.0S</t:TimeOffset>

<t:Month>4</t:Month>

<t:DayOfWeek>Sunday</t:DayOfWeek>

<t:Occurrence>1</t:Occurrence>

</t:RecurringDayTransition>

<t:RecurringDayTransition>

<t:To Kind="Period">Std</t:To>

<t:TimeOffset>P0DT2H0M0.0S</t:TimeOffset>

<t:Month>10</t:Month>

<t:DayOfWeek>Sunday</t:DayOfWeek>

<t:Occurrence>-1</t:Occurrence>

</t:RecurringDayTransition>

</t:TransitionsGroup>

<t:TransitionsGroup Id="1">

<t:RecurringDayTransition>

<t:To Kind="Period">Dlt/2007</t:To>

<t:TimeOffset>P0DT2H0M0.0S</t:TimeOffset>

<t:Month>3</t:Month>

<t:DayOfWeek>Sunday</t:DayOfWeek>

<t:Occurrence>2</t:Occurrence>

</t:RecurringDayTransition>

<t:RecurringDayTransition>

<t:To Kind="Period">Std</t:To>

<t:TimeOffset>P0DT2H0M0.0S</t:TimeOffset>

<t:Month>11</t:Month>

<t:DayOfWeek>Sunday</t:DayOfWeek>

<t:Occurrence>1</t:Occurrence>

</t:RecurringDayTransition>

</t:TransitionsGroup>

</t:TransitionsGroups>

<t:Transitions>

<t:Transition>

<t:To Kind="Group">0</t:To>

</t:Transition>

<t:AbsoluteDateTransition>

<t:To Kind="Group">1</t:To>

<t:DateTime>2007-01-01T08:00:00.000Z</t:DateTime>

</t:AbsoluteDateTransition>

</t:Transitions>

</t:TimeZoneDefinition>

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:CreateItem SendMeetingInvitations="SendToAllAndSaveCopy">

<m:Items>

<t:CalendarItem>

<t:Subject>Weekly Update Meeting</t:Subject>

<t:Body BodyType="HTML">Come hear about how the Organized


Observational Paradigm SkyNet project is coming along!</t:Body>

<t:ReminderMinutesBeforeStart>30</t:ReminderMinutesBeforeStart>

<t:Start>2014-03-08T13:21:32.868-08:00</t:Start>

<t:End>2014-03-08T14:21:32.868-08:00</t:End>

<t:Location>Contoso Main Gallery</t:Location>

<t:RequiredAttendees>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

</t:RequiredAttendees>

<t:Recurrence>

<t:WeeklyRecurrence>

<t:Interval>1</t:Interval>

<t:DaysOfWeek>Saturday</t:DaysOfWeek>

</t:WeeklyRecurrence>

<t:NumberedRecurrence>

<t:StartDate>2014-03-08-08:00</t:StartDate>

<t:NumberOfOccurrences>10</t:NumberOfOccurrences>

</t:NumberedRecurrence>

</t:Recurrence>

</t:CalendarItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The following example shows the response XML that is returned by the CreateItem
operation.

The ItemId and ChangeKey attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="893" MinorBuildNumber="10"

Version="V2_10"
xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:CreateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkAD" ChangeKey="DwAAAB" />

</t:CalendarItem>

</m:Items>

</m:CreateItemResponseMessage>

</m:ResponseMessages>

</m:CreateItemResponse>

</s:Body>

</s:Envelope>

The following example shows the request XML that is generated when you use the
GetItem operation and the ItemId for the series you created, and request properties
only set on a recurring master to confirm that the ItemId returned by the server when
creating a recurring series is for a recurring master.

The ItemId and ChangeKey attributes are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="calendar:CalendarItemType" />

<t:FieldURI FieldURI="calendar:Recurrence" />

<t:FieldURI FieldURI="calendar:FirstOccurrence" />

<t:FieldURI FieldURI="calendar:LastOccurrence" />

<t:FieldURI FieldURI="calendar:ModifiedOccurrences" />

<t:FieldURI FieldURI="calendar:DeletedOccurrences" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="AAMkAD" ChangeKey="DwAAAB" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The following example shows the response XML that is returned by the GetItem
operation.

The ItemId and ChangeKey attributes are shortened for readability.


XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15" MinorVersion="0"


MajorBuildNumber="893" MinorBuildNumber="10"

Version="V2_10"
xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:CalendarItem>

<t:ItemId Id="AAMkAD" ChangeKey="DwAAAB" />

<t:Subject>Weekly Update Meeting</t:Subject>

<t:CalendarItemType>RecurringMaster</t:CalendarItemType>

<t:Recurrence>

<t:WeeklyRecurrence>

<t:Interval>1</t:Interval>

<t:DaysOfWeek>Saturday</t:DaysOfWeek>

</t:WeeklyRecurrence>

<t:NumberedRecurrence>

<t:StartDate>2014-03-08-08:00</t:StartDate>

<t:NumberOfOccurrences>10</t:NumberOfOccurrences>

</t:NumberedRecurrence>

</t:Recurrence>

<t:FirstOccurrence>

<t:ItemId Id="AAMkAD" ChangeKey="DwAAABY" />

<t:Start>2014-03-08T21:21:00Z</t:Start>

<t:End>2014-03-08T22:21:00Z</t:End>

<t:OriginalStart>2014-03-08T21:21:00Z</t:OriginalStart>

</t:FirstOccurrence>

<t:LastOccurrence>

<t:ItemId Id="AAMkAD" ChangeKey="DwAAABY" />

<t:Start>2014-05-10T20:21:00Z</t:Start>

<t:End>2014-05-10T21:21:00Z</t:End>

<t:OriginalStart>2014-05-10T20:21:00Z</t:OriginalStart>

</t:LastOccurrence>

</t:CalendarItem>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

See also
Calendars and EWS in Exchange

Create appointments and meetings by using EWS in Exchange 2013

Recurrence patterns and EWS

Access a recurring series by using EWS in Exchange

Delete appointments in a recurring series by using EWS in Exchange

Update a recurring series by using EWS

Update a recurring series by using EWS in Exchange


Delete appointments in a recurring
series by using EWS in Exchange
Article • 02/11/2022 • 5 minutes to read

Learn how to delete appointments in a recurring series by using the EWS Managed API
or EWS in Exchange.

You can use the EWS Managed API or EWS to delete a series of appointments or
meetings, or just one instance in the series. The process you use to delete an entire
series is essentially the same as the process you use to delete just a single occurrence.
You use the same EWS Managed API methods or EWS operations that you use to delete
a single instance appointment or meeting. The difference is in the item ID that is
included in the method or operation. Let's start by looking at how both scenarios are
the same.

In order to delete a recurring series or a single occurrence in a recurring series, you need
to find the occurrence or series that you want to delete, and then call the appropriate
method or operation to remove it. While you can simply delete any type of
appointment, we recommend that you keep any attendees or the organizer up to date
and cancel meetings that the user has organized and decline meetings that the user did
not organize.

So how are the scenarios different? It's all about the Appointment object used to
invoke the method (for the EWS Managed API) or the item ID included in the operation
request (for EWS). To delete an entire series, you need the Appointment object or item
ID for the recurring master. To delete a single occurrence, you need the Appointment
object or item ID for the occurrence.

Delete a recurring appointment by using the


EWS Managed API
This example assumes that you have authenticated to an Exchange server and have
acquired an ExchangeService object named service. The recurringItem parameter is an
Appointment object for either the recurring master or a single occurrence. The
deleteEntireSeries parameter indicates whether to delete the entire series that the
recurringItem is a part of.

C#
public static bool DeleteRecurringItem(ExchangeService service, Appointment
recurringItem, bool deleteEntireSeries)

Appointment appointmentToDelete = null;

// If the item is a single appointment, fail.

if (recurringItem.AppointmentType == AppointmentType.Single)

Console.WriteLine("ERROR: The item to delete is not part of a


recurring series.");

return false;

// Check the Appointment that was passed. Is it

// an occurrence or the recurring master?

if (recurringItem.AppointmentType == AppointmentType.RecurringMaster)

if (!deleteEntireSeries)

// The item is the recurring master, so deleting it will delete

// the entire series. The caller indicated that the entire


series

// should not be deleted, so fail.

Console.WriteLine("ERROR: The item to delete is the recurring


master of the series. Deleting it will delete the entire series.");

return false;

else

appointmentToDelete = recurringItem;

else

if (deleteEntireSeries)

// The item passed is not the recurring master, but the caller

// wants to delete the entire series. Bind to the recurring

// master to delete it.

try

appointmentToDelete =
Appointment.BindToRecurringMaster(service, recurringItem.Id);

catch (Exception ex)

Console.WriteLine("ERROR: {0}", ex.Message);

return false;

else

// The item passed is not the recurring master, but the caller

// only wants to delete the occurrence, so just

// delete the passed item.

appointmentToDelete = recurringItem;

if (appointmentToDelete != null)

// Remove the item, depending on the scenario.

if (appointmentToDelete.IsMeeting)

CalendarActionResults results;

// If it's a meeting and the user is the organizer, cancel it.

// Determine this by testing the AppointmentState bitmask for

// the presence of the second bit. This bit indicates that the
appointment

// was received, which means that someone sent it to the user.


Therefore,

// they're not the organizer.

int isReceived = 2;

if ((appointmentToDelete.AppointmentState &amp; isReceived) ==


0)

results = appointmentToDelete.CancelMeeting("Cancelling this


meeting.");

return true;

// If it's a meeting and the user is not the organizer, decline


it.

else

results = appointmentToDelete.Decline(true);

return true;

else

// The item isn't a meeting, so just delete it.

appointmentToDelete.Delete(DeleteMode.MoveToDeletedItems);

return true;

return false;

In order to use this example, you need to bind to either an occurrence or the recurring
master, and pass the resulting Appointment object to the method. Keep in mind that if
you access appointments by using a CalendarView class, the resulting items are all
single occurrences. Conversely, if you use the ItemView class, the resulting items are
all recurring masters.

Delete a recurring appointment by using EWS


Deleting a recurring series by using EWS is the same as deleting a single-instance
meeting. In fact, the SOAP requests take the same format. Again, the key is the item ID
used in the request. If the item ID corresponds to the recurring master, the entire series
will be deleted. If the item ID corresponds to a single occurrence, only that occurrence
will be deleted.

7 Note

In the code examples that follow, the ItemId, ChangeKey, and RecurringMasterId
attributes are shortened for readability.

This example uses the CreateItem operation with a CancelCalendarItem element to


cancel a meeting for which the user is the organizer. The value of the ReferenceItemId
element indicates the item to cancel, and can be the item ID of a recurring master or a
single occurrence.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Eastern Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SendAndSaveCopy">

<m:Items>

<t:CancelCalendarItem>

<t:ReferenceItemId Id="AAMkADA5..." ChangeKey="DwAAABYA..." />

<t:NewBodyContent BodyType="HTML">Cancelling this meeting.


</t:NewBodyContent>

</t:CancelCalendarItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

This example uses the CreateItem operation with a DeclineItem element to decline a
meeting for which the user is not the organizer. As in the previous example, the value of
the ReferenceItemId element indicates the item to decline, and can be the item ID of a
recurring master or a single occurrence.
XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Eastern Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SendAndSaveCopy">

<m:Items>

<t:DeclineItem>

<t:ReferenceItemId Id="AAMkADA6..." ChangeKey="DwAAABYA..." />

</t:DeclineItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

This example uses the DeleteItem operation to delete a single occurrence of an


appointment with no attendees. The occurrence to delete is specified by the
OccurrenceItemId element, which is constructed from the item ID of the recurring
master and the index of the occurrence.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Eastern Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:DeleteItem DeleteType="MoveToDeletedItems"
SendMeetingCancellations="SendToAllAndSaveCopy">

<m:ItemIds>

<t:OccurrenceItemId RecurringMasterId="AAMkADA8..."
InstanceIndex="3" />

</m:ItemIds>

</m:DeleteItem>

</soap:Body>

</soap:Envelope>

Note that you can get the same result by replacing the OccurrenceItemId element with
an ItemId element that contains the item ID of the occurrence, as shown.

XML

<m:ItemIds>

<t:ItemId Id="AAMkADA7..." ChangeKey="DwAAABYA..." />

</m:ItemIds>

See also
Recurrence patterns and EWS
Access a recurring series by using EWS in Exchange
Create a recurring series by using EWS in Exchange
Update a recurring series by using EWS
Update a recurring series by using EWS in Exchange
Calendars and EWS in Exchange
Create appointments and meetings by using EWS in Exchange 2013
Delete appointments and cancel meetings by using EWS in Exchange
Update a recurring series by using EWS
Article • 03/04/2022 • 4 minutes to read

Learn how to modify appointments in a recurring series by using the EWS Managed API
or EWS in Exchange.

You can use the EWS Managed API or EWS to update a recurring series by either
updating the entire series, or by updating a single occurrence. In this article we'll discuss
how to update a single occurrence.

Modifying a single appointment in a series is very similar to modifying a single instance


appointment. You use the same methods and operations, but you use the item ID of the
occurrence you want to change.

When you change a single occurrence in a series, that occurrence is added to an array of
modified appointments associated with the recurring master for the series. You can use
the Appointment.ModifiedOccurrences EWS Managed API property or the
ModifiedOccurrences EWS element to access all the appointments in a series that
have been modified.

Modify a single occurrence in a series by using


the EWS Managed API
1. Bind to the occurrence you want to modify by using either the
Appointment.BindToOccurrence method with the item's index value, or the
Appointment.Bind method with the occurrence's ID. You obtain this ID from
either the Id property of an Appointment object that corresponds to the
occurrence, or from the ItemId property of the OccurrenceInfo object that
corresponds to the occurrence.

2. Update the properties on the occurrence's Appointment object.

3. Save the changes to the occurrence's appointment object by using the


Appointment.Save method.

The following example updates an appointment in a recurring series and verifies that
the modified appointment is updated on the recurring master. This example assumes
that you have authenticated to an Exchange server and have acquired an
ExchangeService object named service. The recurrenceMasterId parameter is an
identifier associated with the recurring master for the occurrence to modify.
C#

public static ItemId ModifyARecurringSeries(ExchangeService service, ItemId


recurrenceMasterId)

Appointment calendarItem = Appointment.Bind(service, recurrenceMasterId,


new PropertySet(AppointmentSchema.AppointmentType));

Appointment recurrMaster = new Appointment(service);

if (calendarItem.AppointmentType == AppointmentType.RecurringMaster)

// Get the recurring master from an occurrence in a recurring series


with the properties you need.

recurrMaster = Appointment.Bind(service,

recurrenceMasterId,

new
PropertySet(AppointmentSchema.AppointmentType,

AppointmentSchema.Subject,

AppointmentSchema.FirstOccurrence,

AppointmentSchema.LastOccurrence,

AppointmentSchema.ModifiedOccurrences,

AppointmentSchema.DeletedOccurrences));

else

Console.WriteLine("Item id was not for a recurring master.");

return recurrenceMasterId;

// Bind to the second occurrence in the series with the properties to


modify.

Appointment occurrenceToModify = Appointment.BindToOccurrence(service,

recurrMaster.Id,

2,

new
PropertySet(AppointmentSchema.Location,

AppointmentSchema.Start,

AppointmentSchema.End,

AppointmentSchema.RequiredAttendees,

AppointmentSchema.Subject));

// Update the properties you want to change.

occurrenceToModify.Location = "Helipad of Contoso Bldg 1";

occurrenceToModify.Start = occurrenceToModify.Start.AddDays(1);

occurrenceToModify.End = occurrenceToModify.End.AddDays(1);

occurrenceToModify.RequiredAttendees.Add("Contoso CEO",
"sadie@contoso");

occurrenceToModify.RequiredAttendees.Add("Contoso Head of Research",


"[email protected]");

occurrenceToModify.RequiredAttendees.Add("Contoso Head of Security",


"[email protected]");

occurrenceToModify.Subject = occurrenceToModify.Subject.ToString() +
":Mandatory";

// Update the occurrence in your calendar folder and send meeting update
requests to attendees.

// This method call results in an UpdateItem request to EWS.

occurrenceToModify.Update(ConflictResolutionMode.AlwaysOverwrite,
SendInvitationsOrCancellationsMode.SendToAllAndSaveCopy);

// View updated and deleted occurrences on the recurring master prior to


retrieving updated information.

Console.WriteLine("Modified Occurrences prior to updating recurring


master: {0}",

(recurrMaster.ModifiedOccurrences == null ? "None" :


recurrMaster.ModifiedOccurrences.Count.ToString()));

// Update the recurring master to view the modified and deleted


occurrences.

recurrMaster = Appointment.Bind(service, recurrenceMasterId, new


PropertySet(AppointmentSchema.ModifiedOccurrences,

AppointmentSchema.DeletedOccurrences));

// View updated and deleted occurrences on the recurring master after


retrieving updated information.

Console.WriteLine("Modified Occurrences after updating recurring


master:\t {0}",

(recurrMaster.ModifiedOccurrences == null ? "None" :


recurrMaster.ModifiedOccurrences.Count.ToString()));

return recurrMaster.Id;

Modify a single occurrence in a series by using


EWS
Modifying a single instance in a series is essentially the same as modifying a single
instance appointment. You can specify the occurrence to change by using either an
ItemId or an OccurrenceItemId element.

The following example shows the request XML when you use the UpdateItem
operation to update an occurrence in a recurring series of appointments. The ItemId
and ChangeKey are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010" />

</soap:Header>

<soap:Body>

<m:UpdateItem ConflictResolution="AlwaysOverwrite"
SendMeetingInvitationsOrCancellations="SendToAllAndSaveCopy">

<m:ItemChanges>

<t:ItemChange>

<t:ItemId Id="AAMkA" ChangeKey="DwAAAB" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:Location" />

<t:CalendarItem>

<t:Location>Helipad of Contoso Bldg 1</t:Location>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:Start" />

<t:CalendarItem>

<t:Start>2014-03-27T19:33:00.000-07:00</t:Start>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:End" />

<t:CalendarItem>

<t:End>2014-03-27T20:33:00.000-07:00</t:End>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:RequiredAttendees" />

<t:CalendarItem>

<t:RequiredAttendees>

<t:Attendee>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:Name>Contoso CEO</t:Name>

<t:EmailAddress>sadie@contoso</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:Name>Contoso Head of Research</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:Name>Contoso Head of Security</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

</t:RequiredAttendees>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:CalendarItem>

<t:Subject>Weekly Update Meeting:Mandatory</t:Subject>

</t:CalendarItem>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

</m:ItemChanges>

</m:UpdateItem>

</soap:Body>

</soap:Envelope>

The server responds to the UpdateItem request with an UpdateItemResponse


message that includes a ResponseCode value of NoError, which indicates that the
occurrence was updated successfully, and the ItemId of the updated appointment.

See also
Calendars and EWS in Exchange

Update appointments and meetings by using EWS in Exchange

Recurrence patterns and EWS

Access a recurring series by using EWS in Exchange


Create a recurring series by using EWS in Exchange

Delete appointments in a recurring series by using EWS in Exchange

Update a recurring series by using EWS in Exchange


Update a recurring series by using EWS
in Exchange
Article • 02/11/2022 • 4 minutes to read

Learn how to update an entire recurring series at once by using the EWS Managed API
or EWS in Exchange.

You can use the EWS Managed API or EWS to update a recurring series by either
updating the entire series, or by updating a single occurrence. In this article we'll discuss
how to update the entire series at once.

In general, updating a recurring series is very similar to modifying a single appointment.


You use the same methods and operations, but you use the item ID of the series'
recurring master. In some cases you might not start with the recurring master, and you
might need to find the item ID for the recurring master.

However, there is one key difference to consider when updating a recurring series:
updating the recurrence pattern. Updating the recurrence pattern is only possible with
the recurring master, and changes to the pattern can add or remove occurrences. For
example, if you modify the Recurrence.EndDate property to a date later than its
current value, the recurrence pattern is reevaluated, and additional occurrences might
be added.

Modify all occurrences in a series by using the


EWS Managed API
To modify all occurrences in a series you:

1. Bind to the recurring master for the series by using the


Appointment.BindToRecurringMaster or Appointment.Bind method on a
recurring master.
2. Update the properties on the recurring master Appointment object.
3. Save the changes to the recurring master by using the Appointment.Save
method.

The following example updates a recurring series to change the location, add an
attendee, and modify the recurrence pattern. This example assumes that the
ExchangeService object passed in the service parameter has been initialized with valid
values in the Credentials and Url properties. The recurringAppointment parameter is
an Appointment object bound to either an occurrence or the recurring master for the
series to be updated.

C#

using Microsoft.Exchange.WebServices.Data;

public static bool UpdateRecurringSeries(ExchangeService service,


Appointment recurringAppointment)
{

Appointment recurringMaster = null;

// If the item is a single appointment, fail.

if (recurringAppointment.AppointmentType == AppointmentType.Single)

Console.WriteLine("ERROR: The item to delete is not part of a


recurring series.");

return false;

// Check the Appointment that was passed. Is it

// an occurrence or the recurring master?

if (recurringAppointment.AppointmentType !=
AppointmentType.RecurringMaster)

// If an occurrence was passed in, bind to the master.

try

// This method results in a call to EWS.

recurringMaster = Appointment.BindToRecurringMaster(service,
recurringAppointment.Id);

catch (Exception ex)

Console.WriteLine("Couldn't bind to master: {0}", ex.Message);

return false;

else

// Bind to the appointment to load all properties.

// This method results in a call to EWS.

recurringMaster = Appointment.Bind(service,
recurringAppointment.Id);

// Basic updates. These kinds of updates are the same

// as if you were updating a single appointment.

// Update the location. All occurrences will update to this new


location.

recurringMaster.Location = "Conference Room 2";

// Add an attendee.

Attendee newAttendee = new Attendee("[email protected]");

recurringMaster.RequiredAttendees.Add(newAttendee);

// Changes to the recurrence. This is only applicable to a recurring

// master.

// If the series has an end date, extend the series to add two more
occurrences.

if (recurringMaster.Recurrence.HasEnd)

// NumberOfOccurrences is only set if the user created the

// appointment with a set number of occurrences.

// Otherwise, there's a start and end date.

if (recurringMaster.Recurrence.NumberOfOccurrences != null)

recurringMaster.Recurrence.NumberOfOccurrences += 2;

else

// This is a bit more complicated if you want to add two more

// occurrences. You need to calculate a new end date.

Type recurrenceType = recurringMaster.Recurrence.GetType();

switch (recurrenceType.Name)

case "DailyPattern":

recurringMaster.Recurrence.EndDate =

recurringMaster.Recurrence.EndDate.Value.AddDays(2);

break;

case "WeeklyPattern":

recurringMaster.Recurrence.EndDate =

recurringMaster.Recurrence.EndDate.Value.AddDays(14);

break;

case "YearlyPattern":

recurringMaster.Recurrence.EndDate =

recurringMaster.Recurrence.EndDate.Value.AddYears(2);

break;

default:

// Do nothing here. There are other recurrence


// types but for simplicity, these aren't covered.

break;

else

// If it has no end, set an end date to 2 weeks from today.

recurringMaster.Recurrence.EndDate = DateTime.Now.AddDays(14);

// Update the series.

try

// This method results in a call to EWS.

recurringMaster.Update(ConflictResolutionMode.AutoResolve);

catch (Exception ex)

Console.WriteLine("Error updating series: {0}", ex.Message);

return false;

return true;

Modify all occurrences in a series by using EWS


To modify all occurrences in a series, you need to use the UpdateItem operation with
the item ID of the recurring master in the ItemId element in the request. The structure
of the request is the same as a request to update a single appointment.

The following example updates the recurring series in the following ways:

Updates the location of the series by setting the Location element.


Updates the attendees by setting the RequiredAttendees element.
Updates the recurrence by setting the Recurrence (RecurrenceType) element.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Eastern Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:UpdateItem MessageDisposition="SaveOnly"
ConflictResolution="AutoResolve"
SendMeetingInvitationsOrCancellations="SendToAllAndSaveCopy">

<m:ItemChanges>

<t:ItemChange>

<t:ItemId Id="AAMkADA5..." ChangeKey="DwAAABYA..." />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:Location" />

<t:CalendarItem>

<t:Location>Conference Room 2</t:Location>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:RequiredAttendees" />

<t:CalendarItem>

<t:RequiredAttendees>

<t:Attendee>

<t:Mailbox>

<t:Name>Mack Chaves</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

</t:Attendee>

<t:Attendee>

<t:Mailbox>

<t:Name>Sadie Daniels</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

</t:Mailbox>

</t:Attendee>

</t:RequiredAttendees>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:Recurrence" />

<t:CalendarItem>

<t:Recurrence>

<t:WeeklyRecurrence>

<t:Interval>1</t:Interval>

<t:DaysOfWeek>Tuesday</t:DaysOfWeek>

</t:WeeklyRecurrence>

<t:EndDateRecurrence>

<t:StartDate>2014-05-06</t:StartDate>

<t:EndDate>2014-06-22-04:00</t:EndDate>

</t:EndDateRecurrence>

</t:Recurrence>

</t:CalendarItem>

</t:SetItemField>

<t:SetItemField>

<t:FieldURI FieldURI="calendar:MeetingTimeZone" />

<t:CalendarItem>

<t:MeetingTimeZone TimeZoneName="Pacific Standard Time" />

</t:CalendarItem>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

</m:ItemChanges>

</m:UpdateItem>

</soap:Body>

</soap:Envelope>

The server responds with an UpdateItemResponse element that includes a


ResponseCode element with a value of NoError, which indicates that the update was
successful.

See also
Calendars and EWS in Exchange
Recurrence patterns and EWS
Update appointments and meetings by using EWS in Exchange
Update a recurring series by using EWS
Access a recurring series by using EWS in Exchange
Delegate access and EWS in Exchange
Article • 06/14/2022 • 9 minutes to read

Find out how to use the EWS Managed API and EWS in Exchange to provide delegate
access to users' mailboxes.

You can enable users to access other users' mailboxes in one of three ways:

By adding delegates and specifying permissions for each delegate.

By modifying folder permissions directly.

By using impersonation.

Delegation and folder permissions are best when you're only granting access to a few
users, because you have to add permissions individually to each mailbox. Impersonation
is the best choice when you're dealing with quantities of mailboxes, because you can
easily enable one service account to access every mailbox in a database. Figure 1 shows
some of the differences between each type of access.

Figure 1. Ways to access other users' mailboxes


When it comes to sending mail or scheduling meetings, delegates can be given "send
on behalf of" permissions, so the recipient of an email or a meeting request that was
sent by a delegate will see " delegate on behalf of mailbox owner " when they receive the
email or meeting request in Outlook. Including the "send on behalf of" text is a client
implementation detail - and can be created by using the "from" and "sender" values.
The "from" value indicates the mailbox owner, and the "sender" value indicates the
delegate that sent the mail. If a service account impersonating a user sends an email or
schedules a meeting for the mailbox owner, the message is "sent as" the mailbox owner.
There is no way for the recipient to know the mail was sent by the service account. Users
who are granted folder permissions and not delegate access are not able to "send as" or
"send on behalf of" of a mailbox owner. They have access to the mailbox folders, and
might be able to create items in the folders, but they cannot send the items.

When is it appropriate to modify folder permissions directly? Generally, when you want
to provide a user access to a folder, but do not want to grant the user "send on behalf
of" permissions, when your permissions requirements do not map to the
DelegateFolderPermissionLevel EWS Managed API enumeration values or the
PermissionLevel EWS element values, or when you want to provide a user access to a
single custom folder.

If you only need to modify folder permissions to achieve your goal, and do not need to
add a delegate (that is, you don't need "send on behalf of" permissions), see Set folder
permissions for another user by using EWS in Exchange.

Note that you can also use Outlook or the Exchange Server PowerShell (Exchange
Management Shell) to set up delegate access.

How does delegate access work?


Delegate access enables users to access some or all of the mailbox owner's folders and
act on behalf of the mailbox owner. The mailbox owner can be a user, or a resource, like
a conference room. For example, a receptionist can be granted delegate permissions to
a conference room's calendar folder, to handle booking requests. You can use the EWS
Managed API or EWS to enable the mailbox owner or an administrator to add a
delegate, specify what folders the delegate can access, and then specify permissions for
that folder. Delegates can be granted access to the following folders:

Calendar

Tasks

Inbox
Contacts

Notes

Journal

When a user has delegate access to one or more of these folders, they can create, get,
update, delete, copy, and search for items in that folder and any child folders,
depending on the permissions set on the folder. The way in which the application
performs these actions depends on whether explicit or implicit access is required.

Delegate permissions
When an administrator or mailbox owner adds a delegate to a mailbox, they can also set
the permission level for one or more folders. If a permission level is not set for a folder,
the permission value defaults to None. Multiple users can have the same permission
level on a folder, and users can have different permission levels for different folders. If
you're using the EWS Managed API, you use the DelegateUser.Permissions property,
which contains one of the DelegateFolderPermissionLevel enumeration values for
each folder, to set delegate permissions on folders. If you're using EWS, you use the
DelegatePermissions element to set delegate permissions, and the PermissionLevel
element to define the permission level.

Table 2. Delegate permission levels

Permission Description
level

None This is the default value for all folders.

Author A delegate can read and create items, and modify and delete items they create. For
example, a delegate can create task requests and meeting requests directly in the
mailbox owner's Task or Calendar folder, and then send either item on the mailbox
owner's behalf.

Editor A delegate can do everything an Author can do, and also modify and delete the
items the mailbox owner created.

Reviewer A delegate can read items; for example a delegate with Reviewer permission can
read messages in another person's Inbox.

Custom The mailbox owner has granted a custom set of permissions to the delegate.

The DelgateUser.ViewPrivateItems EWS Managed API property and the


ViewPrivateItems EWS element is a global setting that affects all the mailbox owner's
folders, including all Mail, Contacts, Calendar, Tasks, Notes, and Journal folders. You
cannot allow access to private items in only one folder.

Explicit access
Simply put, explicit access is the entry way for delegates to perform actions on a
mailbox owner's folders or items. Explicit access is granted to a delegate when they
include the well-known folder name for a mailbox owner's folder along with the mailbox
owner's SMTP address in a request to the server. The access is explicit because the
delegate's request explicitly states that the context for the method or operation is the
mailbox owner's mailbox, and not the delegate's mailbox.

Explicit access defines the context for all methods or operations performed on the
folders or items moving forward. All item and folder IDs returned when the explicit
access is set uniquely identify themselves as belonging to the mailbox owner (although
not in any human readable format). This way, the application doesn't need to specify the
mailbox owner's SMTP address again and again; the context is hidden in the identifiers.
After an item or folder is identified, a delegate actually uses implicit access to modify the
item. The following figure shows the process of getting explicit and implicit access.

Figure 2. Requesting explicit and implicit access to an item or folder

You can set explicit access in many different scenarios. Essentially, any time you're
sending a folder ID in a method or operation, you can set explicit access. This can
include finding folders, finding appointments, getting items, finding conversations, and
so on.

Explicit access and the EWS Managed API


You can initiate explicit delegate access by using any of the following overloaded
methods that take a FolderId input parameter to identify the target folder:
Folder.Bind

ExchangeService.FindItems

ExchangeService.FindAppointments

ExchangeService.FindFolders

And more!

You can use the FolderId parameter in each of these methods to identify the mailbox
owner's target folder, as follows.

C#

new FolderId(WellKnownFolderName.Calendar, "[email protected]");

For example, to bind to the Calendar folder, the FolderId in this Bind method specifies
the well-known folder name, and the mailbox owner's SMTP address.

C#

CalendarFolder calendar = CalendarFolder.Bind(service, new


FolderId(WellKnownFolderName.Calendar, "[email protected]"), new
PropertySet());

By specifying the well-known folder name and the SMTP address, the delegate can bind
to the mailbox owner's Calendar folder — thereby gaining explicit access to the folder.
All subsequent requests for implicit access to items in the folder then rely on the context
returned in the item IDs and folder IDs. Essentially, the identifiers contain the context for
the implied delegate access calls. Or, to retrieve the item ID of an item that meets
specific criteria, use the following.

C#

FindItemsResults<Item> results = service.FindItems(new


FolderId(WellKnownFolderName.Calendar, "[email protected]"), filter,
view);

In this case the item ID is returned, and then the delegate can then use implicit access to
make changes to the item by using the item ID.

You don't have to initiate explicit access again until you require an item ID or a folder ID
that you didn't access via the existing explicit access.
Explicit access and EWS
You can initiate explicit access by using the GetFolder , FindItem , or FindFolder
operations. These operations provide the option to use the DistinguishedFolderId
element to identify the target folder. The DistinguishedFolderId element has a single
optional child element, the Mailbox element. The Mailbox element, when used as a
child of the DistinguishedFolderId element, specifies the mailbox for the delegate to
access. If the calling user has permission to access the mailbox owner's folder, the
response will contain a collection of identifiers to items or folders in that mailbox. The
item and folder identifiers that are returned in the response can be used for implicit
delegate access.

Implicit access
Implicit access is used after a delegate has retrieved the ID for an item or folder in the
mailbox owner's mailbox and the delegate wants to update, delete, or copy the item.
When the delegate uses that item or folder ID in a request, the changes are made to the
item in the mailbox owner's mailbox. The delegate does not have to include the mailbox
owner's SMTP address.

For example, when a delegate has the ID of one of the mailbox owner's folders, the
delegate can perform a FindItem operation on that folder by using the folder ID,
without explicitly identifying the mailbox owner's mailbox. At that point, the delegate
can perform actions on the mailbox owner's folder by using the IDs that are returned in
the responses.

Implicit access and the EWS Managed API


If an item ID was retrieved by the FindItems method, that item ID can be used in a
subsequent Item.Bind method call to bind to the item. You can then call the
Item.Update , Item.Delete , or Item.Copy method — or any method call that
requires an item ID — as needed to complete your task. As long as the delegate has
appropriate permissions to the folder that contains the item (and, if applicable, the
folder the item is moving to), the delegate can make changes according to their
permission levels.

Implicit access and EWS


If an item ID was retrieved by the FindItem operation, that item ID can be used in
subsequent GetItem operations to bind to the item. You can then call the
UpdateItem , DeleteItem, or CopyItem operation — or any operation that requires
an item ID — as needed to complete your task. As long as the delegate has appropriate
permissions to the folder that contains the item (and, if applicable, the folder the item is
moving to), the delegate can make changes according to their permission levels.

In this section
Add and remove delegates by using EWS in Exchange

Access a calendar as a delegate by using EWS in Exchange

Access contacts as a delegate by using EWS in Exchange

Access email as a delegate by using EWS in Exchange

Set folder permissions for another user by using EWS in Exchange

Handling delegation-related errors in EWS in Exchange

See also
Develop web service clients for Exchange

Allow someone else to manage your mail and calendar

Add- MailboxPermission
Add and remove delegates by using
EWS in Exchange
Article • 09/15/2021 • 6 minutes to read

Learn how to add delegates to or remove delegates from users' mailboxes by using the
EWS Managed API or EWS in Exchange.

You can use the EWS Managed API or EWS to enable delegates to act on behalf of a
mailbox owner or remove a delegate's access to a mailbox. Users who are added as a
delegate, and are given permissions, can perform tasks on behalf of the mailbox owner.
For example, they can create and send meeting invitations, send emails, and respond to
meeting requests on the mailbox owner's behalf.

Table 1. EWS Managed API methods and EWS operations for adding and removing
delegates

Task EWS Managed API method EWS operation

Add delegates ExchangeService.AddDelegates


AddDelegate

Remove delegates ExchangeService.RemoveDelegates


RemoveDelegate

After a delegate is granted permissions to a folder, they can act on items in the folder
and any subfolders, according to their delegate permissions. Permissions for delegates
only apply to subfolders that are created after the delegate access was granted. To
update folder permissions for pre-existing folders, or other folders, see Set folder
permissions for another user by using EWS in Exchange.

Note that delegates can only be added to mailbox-enabled accounts, including mail-
enabled security groups. By default, a single EWS delegate access call can access a
maximum of 255 different mailboxes.

Add delegates by using the EWS Managed API


You can add delegates to a mailbox by using the AddDelegates EWS Managed API
method. In this example, a new calendar, contact, and email DelegateUser object is
created, and each delegate is given Editor permissions for their respective folder. You
can modify the example to add a delegate to any of the folders specified by the
DelegatePermissions properties , and you can set the permissions to any of the values
specified by the DelegateFolderPermissionLevel enumeration.
This example assumes that service is a valid ExchangeService object for the mailbox
owner, and that the user has been authenticated to an Exchange server.

C#

public static Collection<DelegateUserResponse> AddDelegates(ExchangeService


service)

// Create a list to hold the new delegates to add.

List<DelegateUser> newDelegates = new


System.Collections.Generic.List<DelegateUser>();

// Create a new delegate that has editor access to the mailbox owner's
Calendar folder.

DelegateUser calendarDelegate = new


DelegateUser("[email protected]");

calendarDelegate.Permissions.CalendarFolderPermissionLevel =
DelegateFolderPermissionLevel.Editor;

// Add the delegate to the list of new delegates.

newDelegates.Add(calendarDelegate);

// Create a new delegate that has editor access to the mailbox owner's
Contacts folder.

DelegateUser contactDelegate = new


DelegateUser("[email protected]");

contactDelegate.Permissions.ContactsFolderPermissionLevel =
DelegateFolderPermissionLevel.Editor;

// Add the delegate to the list of new delegates.

newDelegates.Add(contactDelegate);

// Create a new delegate that has editor access to the mailbox owner's
Inbox folder.

DelegateUser emailDelegate = new


DelegateUser("[email protected]");

emailDelegate.Permissions.InboxFolderPermissionLevel =
DelegateFolderPermissionLevel.Editor;

// Add the delegate to the list of new delegates.

newDelegates.Add(emailDelegate);

// Create a mailbox object that represents the mailbox owner.

Mailbox mailbox = new Mailbox("[email protected]");

// Call the AddDelegates method to add the delegates to the target


mailbox.

Collection<DelegateUserResponse> response =
service.AddDelegates(mailbox,
MeetingRequestsDeliveryScope.DelegatesAndSendInformationToMe, newDelegates);

foreach (DelegateUserResponse resp in response)

// Print out the result and the last eight characters of the item
ID.

Console.WriteLine("For delegate " +


resp.DelegateUser.UserId.PrimarySmtpAddress.ToString());

Console.WriteLine("Result: {0}", resp.Result);

Console.WriteLine("Error Code: {0}", resp.ErrorCode);

Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);

Console.WriteLine("\r\n");

return response;

Add delegates by using EWS


The following code example shows how to add separate calendar, contact, and email
delegates by using the AddDelegate EWS operation. The mailbox to modify is
specified by the Mailbox element, and the permission settings for each delegate are
contained in the DelegateUser element. Each of the delegates has been granted
Editor permissions to their target folder.

This is also the XML request that the EWS Managed API sends when you use the
AddDelegates method to add delegates.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:AddDelegate>

<m:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</m:Mailbox>

<m:DelegateUsers>
<t:DelegateUser>

<t:UserId>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

</t:UserId>

<t:DelegatePermissions>

<t:CalendarFolderPermissionLevel>Editor</t:CalendarFolderPermissionLevel>

<t:TasksFolderPermissionLevel>None</t:TasksFolderPermissionLevel>

<t:InboxFolderPermissionLevel>None</t:InboxFolderPermissionLevel>

<t:ContactsFolderPermissionLevel>None</t:ContactsFolderPermissionLevel>

<t:NotesFolderPermissionLevel>None</t:NotesFolderPermissionLevel>

<t:JournalFolderPermissionLevel>None</t:JournalFolderPermissionLevel>

</t:DelegatePermissions>

<t:ReceiveCopiesOfMeetingMessages>false</t:ReceiveCopiesOfMeetingMessages>

<t:ViewPrivateItems>false</t:ViewPrivateItems>
</t:DelegateUser>

<t:DelegateUser>

<t:UserId>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

</t:UserId>

<t:DelegatePermissions>

<t:CalendarFolderPermissionLevel>None</t:CalendarFolderPermissionLevel>

<t:TasksFolderPermissionLevel>None</t:TasksFolderPermissionLevel>

<t:InboxFolderPermissionLevel>None</t:InboxFolderPermissionLevel>

<t:ContactsFolderPermissionLevel>Editor</t:ContactsFolderPermissionLevel>

<t:NotesFolderPermissionLevel>None</t:NotesFolderPermissionLevel>

<t:JournalFolderPermissionLevel>None</t:JournalFolderPermissionLevel>

</t:DelegatePermissions>

<t:ReceiveCopiesOfMeetingMessages>false</t:ReceiveCopiesOfMeetingMessages>

<t:ViewPrivateItems>false</t:ViewPrivateItems>
</t:DelegateUser>

<t:DelegateUser>

<t:UserId>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

</t:UserId>

<t:DelegatePermissions>

<t:CalendarFolderPermissionLevel>None</t:CalendarFolderPermissionLevel>

<t:TasksFolderPermissionLevel>None</t:TasksFolderPermissionLevel>

<t:InboxFolderPermissionLevel>Editor</t:InboxFolderPermissionLevel>

<t:ContactsFolderPermissionLevel>None</t:ContactsFolderPermissionLevel>

<t:NotesFolderPermissionLevel>None</t:NotesFolderPermissionLevel>

<t:JournalFolderPermissionLevel>None</t:JournalFolderPermissionLevel>

</t:DelegatePermissions>

<t:ReceiveCopiesOfMeetingMessages>false</t:ReceiveCopiesOfMeetingMessages>

<t:ViewPrivateItems>false</t:ViewPrivateItems>
</t:DelegateUser>

</m:DelegateUsers>

<m:DeliverMeetingRequests>DelegatesAndSendInformationToMe</m:DeliverMeetingR
equests>

</m:AddDelegate>

</soap:Body>

</soap:Envelope>

The server responds to the AddDelegate request with an AddDelegateResponse


message that includes a ResponseCode element value of NoError, which indicates
that the delegates were successfully created.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="888"

MinorBuildNumber="9"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:AddDelegateResponse ResponseClass="Success"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseCode>NoError</m:ResponseCode>
<m:ResponseMessages>

<m:DelegateUserResponseMessageType ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:DelegateUser>

<t:UserId>

<t:SID>S-1-5-21-1337771579-694202782-848329751-1535221</t:SID>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

<t:DisplayName>calendardelegate</t:DisplayName>

</t:UserId>

<t:ReceiveCopiesOfMeetingMessages>false</t:ReceiveCopiesOfMeetingMessages>

<t:ViewPrivateItems>false</t:ViewPrivateItems>

</m:DelegateUser>

</m:DelegateUserResponseMessageType>

<m:DelegateUserResponseMessageType ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:DelegateUser>

<t:UserId>

<t:SID>S-1-5-21-1337771579-694202782-848329751-1535264</t:SID>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

<t:DisplayName>contactdelegate</t:DisplayName>

</t:UserId>

<t:ReceiveCopiesOfMeetingMessages>false</t:ReceiveCopiesOfMeetingMessages>

<t:ViewPrivateItems>false</t:ViewPrivateItems>

</m:DelegateUser>

</m:DelegateUserResponseMessageType>

<m:DelegateUserResponseMessageType ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:DelegateUser>

<t:UserId>

<t:SID>S-1-5-21-1337771579-694202782-848329751-1535223</t:SID>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

<t:DisplayName>emaildelegate</t:DisplayName>

</t:UserId>

<t:ReceiveCopiesOfMeetingMessages>false</t:ReceiveCopiesOfMeetingMessages>

<t:ViewPrivateItems>false</t:ViewPrivateItems>

</m:DelegateUser>

</m:DelegateUserResponseMessageType>

</m:ResponseMessages>

</m:AddDelegateResponse>

</s:Body>

</s:Envelope>

Remove delegates by using the EWS Managed


API
You can remove delegates from a target mailbox by using the
ExchangeService.RemoveDelegates EWS Managed API method. In this example, the
delegate permissions set in the add a delegate example are removed.

This example assumes that service is a valid ExchangeService object for the mailbox
owner, and that the user has been authenticated to an Exchange server.

C#

public static Collection<DelegateUserResponse>


RemoveDelegates(ExchangeService service)

// Create a list to hold the delegates to delete.

List<UserId> deletedDelegates = new


System.Collections.Generic.List<UserId>();

// Add the delegate to the list of new delegates.

deletedDelegates.Add("[email protected]");

// Add the delegate to the list of new delegates.

deletedDelegates.Add("[email protected]");

// Add the delegate to the list of new delegates.

deletedDelegates.Add("[email protected]");

// Create a mailbox object that represents the mailbox owner.

Mailbox mailbox = new Mailbox("[email protected]");

// Call the AddDelegates method to add the delegates to the target


mailbox.

Collection<DelegateUserResponse> response =
service.RemoveDelegates(mailbox, deletedDelegates);

foreach (DelegateUserResponse resp in response)

// Print out the result and the last eight characters of the item
ID.

Console.WriteLine("Result: {0}", resp.Result);

Console.WriteLine("Error Code: {0}", resp.ErrorCode);

Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);

return response;

Remove delegates by using EWS


You can remove delegates from a mailbox by using the RemoveDelegate EWS
operation. In this example, the delegate permissions set in the add a delegate example
are removed.

This is also the XML request that the EWS Managed API sends when you use the
RemoveDelegates method to remove delegates.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:RemoveDelegate>

<m:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</m:Mailbox>

<m:UserIds>

<t:UserId>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

</t:UserId>

<t:UserId>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

</t:UserId>

<t:UserId>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

</t:UserId>

</m:UserIds>

</m:RemoveDelegate>

</soap:Body>

</soap:Envelope>

The server responds to the RemoveDelegate request with a AddDelegateResponse


message that includes a ResponseCode element value of NoError, which indicates
that the delegates were successfully removed.

Next steps
After you add delegates to calendar, email, and task folders, the delegate can access the
items in the folders. To learn more, see the following articles:

Access email as a delegate by using EWS in Exchange

Access a calendar as a delegate by using EWS in Exchange

Access contacts as a delegate by using EWS in Exchange

If the folders for which you added delegates include child folders that were created
before you granted the delegate access, the delegate will not be able to access those
folders without additional permissions. To add these permissions, or modify permissions
for any other folders, see Set folder permissions for another user by using EWS in
Exchange.

See also
Delegate access and EWS in Exchange
Exchange 2013: Add delegate users to an email account programmatically
Exchange 2013: Update delegates associated with email accounts
programmatically
Exchange 2013: Remove delegates associated with email accounts
programmatically
Access a calendar as a delegate by using
EWS in Exchange
Article • 03/15/2022 • 9 minutes to read

Learn how to access a calendar as a delegate by using the EWS Managed API or EWS in
Exchange.

You can use the EWS Managed API or EWS to give a user delegate access to a mailbox
owner's Calendar folder. The delegate can then create meeting requests on behalf of the
mailbox owner, create appointments, respond to meeting requests, and retrieve, update,
and delete meetings from the mailbox owner's Calendar folder, depending on their
permissions.

As a delegate, you use the same methods and operations to access a mailbox owner's
Calendar folder that you use to access your own Calendar folder. The main difference is
that you have to use explicit access to find or create a calendar item or calendar
subfolder, and then after you identify the item ID or folder ID, you can use implicit
access to get, update, or delete the item.

Table 1. EWS Managed API methods and EWS operations for accessing a calendar as a
delegate

If you want to… Use this EWS Managed API method… Use this EWS operation…

Create a meeting Appointment.Save where the CreateItem where the


or appointment as FolderId parameter provides explicit Mailbox element specifies
a delegate access to the mailbox owner's Calendar the EmailAddress of the
folder mailbox owner

Create multiple ExchangeService.CreateItems where the CreateItem where the


meetings or FolderId parameter provides explicit Mailbox element specifies
appointments as a access to the mailbox owner's Calendar the EmailAddress of the
delegate folder mailbox owner

Search for or find ExchangeService.FindItems where the FindItem where the


an appointment or FolderId parameter provides explicit Mailbox element specifies
meeting as a access to the mailbox owner's Calendar the EmailAddress of the
delegate folder mailbox owner

Get an Appointment.Bind
GetItem

appointment or
meeting as a
delegate
If you want to… Use this EWS Managed API method… Use this EWS operation…

Update an Appointment.Bind followed by GetItem followed by


appointment or Appointment.Update
UpdateItem

meeting as a
delegate

Delete an Appointment.Bind followed by GetItem followed by


appointment or Appointment.Delete
DeleteItem

meeting as a
delegate

7 Note

In the code examples in this article, [email protected] is the mailbox owner.

Prerequisite tasks
Before a user can access a mailbox owner's Calendar folder as a delegate, the user must
be added as a delegate with permissions to the mailbox owner's Calendar folder.

A delegate must have a mailbox attached to their account to update the calendar of a
mailbox owner.

If a delegate needs to work with meeting requests and responses only, you can add the
delegate to the Calendar folder, and use the default
MeetingRequestsDeliveryScope.DelegatesAndSendInformationToMe EWS Managed
API enumeration value or the DeliverMeetingRequests EWS element value of
DelegatesAndSendInformationToMe to send the requests to the delegate and
informational messages to the mailbox owner. The delegate then does not need to be
given access to the mailbox owner's Inbox folder.

Create a meeting or appointment as a delegate


by using the EWS Managed API
The EWS Managed API enables you to use the service object for the delegate user to
create calendar items for the mailbox owner. This example shows how to use the Save
method to create a meeting and send meeting requests to the attendees.

This example assumes that service is a valid ExchangeService object for the delegate
and that the delegate has been granted the appropriate permissions for the mailbox
owner's Calendar folder.

C#

private static void DelegateAccessCreateMeeting(ExchangeService service)

Appointment meeting = new Appointment(service);

// Set the properties on the meeting object to create the meeting.

meeting.Subject = "Team building exercise";

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("[email protected]");

meeting.ReminderMinutesBeforeStart = 60;

// Save the meeting to the Calendar folder for

// the mailbox owner and send the meeting request.

// This method call results in a CreateItem call to EWS.

meeting.Save(new FolderId(WellKnownFolderName.Calendar,

"[email protected]"),

SendInvitationsMode.SendToAllAndSaveCopy);

// Verify that the meeting was created.

Item item = Item.Bind(service, meeting.Id, new


PropertySet(ItemSchema.Subject));
Console.WriteLine("\nMeeting created: " + item.Subject + "\n");

Note that when you save the item, the Save method call must identify the mailbox
owner's Calendar folder. If the mailbox owner's Calendar folder is not specified, the
meeting request gets saved to the delegate's calendar and not the mailbox owner's
Calendar folder. You can include the mailbox owner's Calendar folder in the Save
method call in two ways. We recommend that you instantiate a new instance of the
FolderId object by using the WellKnownFolderName and the SMTP address of the
mailbox owner.

C#

meeting.Save(new FolderId(WellKnownFolderName.Calendar,

"[email protected]"), SendInvitationsMode.SendToAllAndSaveCopy);

However, you can also Bind to the Calendar folder first, and then use the ID of the
folder in the Save method call. Be aware, however, that this creates an extra EWS call.

C#

// Identify the mailbox owner's SMTP address

// and bind to their Calendar folder.

Mailbox primary = new Mailbox("[email protected]");

Folder primaryCalendar = Folder.Bind(service,

new FolderId(WellKnownFolderName.Calendar, primary));

// Save the meeting to the Calendar folder for the mailbox owner and
send the meeting request.

meeting.Save(primaryCalendar.Id,

SendInvitationsMode.SendToAllAndSaveCopy);

Create a meeting or appointment as a delegate


by using EWS
EWS enables you to use the service object for the delegate user to create calendar items
for the mailbox owner. This example shows how to use the CreateItem operation to
create a meeting and send meeting requests to the attendees.

This is also the XML request that the EWS Managed API sends when you use the Save
method to create a meeting or appointment as a delegate.

The SOAP header has been removed from the following example for brevity.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Body>

<m:CreateItem SendMeetingInvitations="SendToAllAndSaveCopy">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="calendar">

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:DistinguishedFolderId>

</m:SavedItemFolderId>

<m:Items>

<t:CalendarItem>

<t:Subject>Team building exercise</t:Subject>

<t:Body BodyType="HTML">Let's learn to really work as a

team and then have lunch!</t:Body>

<t:ReminderMinutesBeforeStart>60</t:ReminderMinutesBeforeStart>

<t:Start>2014-03-09T23:26:33.756-05:00</t:Start>

<t:End>2014-03-10T03:26:33.756-05:00</t:End>

<t:Location>Conference Room 12</t:Location>

<t:RequiredAttendees>

<t:Attendee>

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:Attendee>

</t:RequiredAttendees>

</t:CalendarItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode element value of NoError, which indicates that the
meeting was created successfully. The response also contains the item ID of the newly
created meeting.

Search for a meeting or appointment as a


delegate by using the EWS Managed API
To search for a meeting, you must use one of the ExchangeService.FindItems methods
that includes a FolderId parameter, so that you can specify the mailbox owner's
Calendar folder.

C#

static void DelegateAccessSearchWithFilter

(ExchangeService service, SearchFilter filter)

// Limit the result set to 10 items.

ItemView view = new ItemView(10);

view.PropertySet = new PropertySet(ItemSchema.Subject,

ItemSchema.DateTimeReceived,

EmailMessageSchema.IsRead);

// Item searches do not support deep traversal.

view.Traversal = ItemTraversal.Shallow;

// Define the sort order.

view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending);

try

// Call FindItems to find matching calendar items.

// The FindItems parameters must denote the mailbox owner,

// mailbox, and Calendar folder.

// This method call results in a FindItem call to EWS.

FindItemsResults<Item> results = service.FindItems(

new FolderId(WellKnownFolderName.Calendar,

"[email protected]"),

filter,

view);

foreach (Item item in results.Items)

Console.WriteLine("Subject: {0}", item.Subject);

Console.WriteLine("Id: {0}", item.Id.ToString());

catch (Exception ex)

Console.WriteLine("Exception while

enumerating results: {0}", ex.Message);

After the FindItems call returns a response with an ID, you can get, update or delete that
meeting by using the ID and implicit access — and you do not need to specify the
mailbox owner's SMTP address.

Search for a meeting or appointment as a


delegate by using EWS
EWS enables you to use the service object for the delegate user to search for
appointments and meetings that meet a set of search criteria. This example shows how
to use the FindItem operation to find meetings in the mailbox owner's Calendar folder
that contain the word "building" in the subject.

This is also the XML request that the EWS Managed API sends when you use the
FindItem method to search for a meeting or appointment as a delegate.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:FindItem Traversal="Shallow">

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="item:DateTimeReceived" />

<t:FieldURI FieldURI="message:IsRead" />

</t:AdditionalProperties>

</m:ItemShape>

<m:IndexedPageItemView MaxEntriesReturned="10"

Offset="0"

BasePoint="Beginning" />

<m:Restriction>

<t:Contains ContainmentMode="Substring"

ContainmentComparison="IgnoreCase">

<t:FieldURI FieldURI="item:Subject" />

<t:Constant Value="building" />

</t:Contains>

</m:Restriction>

<m:SortOrder>

<t:FieldOrder Order="Descending">

<t:FieldURI FieldURI="item:DateTimeReceived" />

</t:FieldOrder>

</m:SortOrder>

<m:ParentFolderIds>

<t:DistinguishedFolderId Id="calendar">

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:DistinguishedFolderId>

</m:ParentFolderIds>

</m:FindItem>

</soap:Body>

</soap:Envelope>

The server responds to the FindItem request with a FindItemResponse message that
includes a ResponseCode element value of NoError, which indicates that the search
completed successfully. The response contains a CalendarItem for any appointments
or meetings that met the search criteria. In this case, only one meeting is found.

The value of the ItemId element has been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="893"

MinorBuildNumber="10"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body>

<m:FindItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:FindItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootFolder IndexedPagingOffset="1"

TotalItemsInView="1"

IncludesLastItemInRange="true">

<t:Items>

<t:CalendarItem>

<t:ItemId Id="IJpUAAA="

ChangeKey="DwAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAAAIKhS" />

<t:Subject>Team building exercise</t:Subject>

<t:DateTimeReceived>2014-03-
04T21:27:22Z</t:DateTimeReceived>

</t:CalendarItem>

</t:Items>

</m:RootFolder>

</m:FindItemResponseMessage>

</m:ResponseMessages>

</m:FindItemResponse>

</s:Body>

</s:Envelope>

Now that you have the ItemId for the meeting that meets your criteria, you can get,
update, or delete that meeting by using the ItemId and implicit access — and you do
not need to specify the mailbox owner's SMTP address.

Get, update, or delete calendar items as a


delegate by using the EWS Managed API
You can use the EWS Managed API to get, update, or delete a meeting or appointment
in the same way that you perform these actions when you're not using delegate access.
The only difference is that the service object is for the delegate user. The item ID
included in the Bind method call uniquely identifies the item in the mailbox store, in the
mailbox owner's Calendar folder.

Table 2. EWS Managed API methods for working with appointments and meetings as
a delegate
Task EWS Managed API Code example
method

Get an appointment or Bind


Get an item by using the EWS Managed
meeting API

Update an appointment or Bind followed by Update a meeting by using the EWS


meeting Update
Managed API

Delete an appointment or Bind followed by Delete a meeting by using the EWS


meeting Delete
Managed API

Get, update, or delete calendar items as a


delegate by using EWS
You can use EWS to get, update, or delete a meeting or appointment in the same way
that you perform these actions when you're not using delegate access. The only
difference is that the service object is for the delegate user. The item ID included in the
GetItem method call uniquely identifies the item in the mailbox store, in the mailbox
owner's Calendar folder.

Table 3. EWS operations for working with appointments and meetings as a delegate

Task EWS operation Code example

Get an appointment or GetItem


Get an item by using EWS

meeting

Update an appointment or GetItem followed by Update a meeting by using


meeting UpdateItem
EWS

Delete an appointment or GetItem followed by Delete a meeting by using


meeting DeleteItem
EWS

See also
Delegate access and EWS in Exchange
Add and remove delegates by using EWS in Exchange
Set folder permissions for another user by using EWS in Exchange
Calendars and EWS in Exchange
Access contacts as a delegate by using
EWS in Exchange
Article • 09/15/2021 • 8 minutes to read

Learn how to access contacts as a delegate by using the EWS Managed API or EWS in
Exchange.

You can use the EWS Managed API or EWS to give a user access to a mailbox owner's
Contacts folder. The delegate can then create contacts on behalf of the mailbox owner,
and retrieve, update, and delete contacts from the mailbox owner's Contacts folder,
depending on their permissions.

As a delegate, you use the same methods and operations to access a mailbox owner's
Contacts folder that you use to access your own Contacts folder. The main difference is
that you have to use explicit access to find or create a contact item, and then after you
identify the item ID, you can use implicit access to get, update, or delete the item.

Table 1. EWS Managed API methods and EWS operations for accessing a contact as a
delegate

If you want Use this EWS Managed API method… Use this EWS operation…
to…

Create a Item.Save where the FolderId parameter CreateItem where the


contact as a provides explicit access to the mailbox Mailbox element specifies the
delegate owner's Contacts folder EmailAddress of the mailbox
owner

Create ExchangeService.CreateItems where the CreateItem where the


multiple FolderId parameter provides explicit access Mailbox element specifies the
contacts as a to the mailbox owner's Contacts folder EmailAddress of the mailbox
delegate owner

Resolve a ExchangeService.ResolveName where the ResolveNames where the


contact as a FolderId parameter provides explicit Mailbox element specifies the
delegate access to the mailbox owner's Contacts EmailAddress of the mailbox
folder owner

Search for or ExchangeService.FindItems where the FindItem where the Mailbox


find a FolderId parameter provides explicit access element specifies the
contact as a to the mailbox owner's Contacts folder EmailAddress of the mailbox
delegate owner
If you want Use this EWS Managed API method… Use this EWS operation…
to…

Get a Contact.Bind
GetItem

contact as a
delegate

Update a Contact.Bind followed by GetItem followed by


contact as a Contact.Update
UpdateItem

delegate

Delete a Contact.Bind followed by Contact.Delete GetItem followed by DeleteItem


contact as a
delegate

7 Note

In the code examples in this article, [email protected] is the mailbox owner.

Prerequisite tasks
Before a user can access the mailbox owner's Contacts folder as a delegate, the user
must be added as a delegate with permissions to the mailbox owner's Contacts folder.

Create a contact as a delegate by using the


EWS Managed API
The EWS Managed API enables you to use the service object for the delegate user to
create contacts for the mailbox owner. This example shows how to use the Save
method to create a meeting and send meeting requests to the attendees.

This example assumes that service is a valid ExchangeService object for the delegate
and that the delegate has been granted the appropriate permissions for the mailbox
owner's Contacts folder.

C#

public static void DelegateAccessCreateContact(ExchangeService service)

// Create the contact.

Contact contact = new Contact(service);

// Specify the name and how the contact should be filed.

contact.GivenName = "Brian";

contact.MiddleName = "David";

contact.Surname = "Johnson";

contact.FileAsMapping = FileAsMapping.SurnameCommaGivenName;

// Specify the company name.

contact.CompanyName = "Contoso";

// Specify the business, home, and car phone numbers.

contact.PhoneNumbers[PhoneNumberKey.BusinessPhone] = "425-555-0110";

contact.PhoneNumbers[PhoneNumberKey.HomePhone] = "425-555-0120";

contact.PhoneNumbers[PhoneNumberKey.CarPhone] = "425-555-0130";

// Specify two email addresses.

contact.EmailAddresses[EmailAddressKey.EmailAddress1] =

new EmailAddress("[email protected]");

contact.EmailAddresses[EmailAddressKey.EmailAddress2] =

new EmailAddress("[email protected]");

// Save the contact in the mailbox owner's Contacts folder.

// This method call results in a CreateItem call to EWS.

// The contact identifier contains the context for the mailbox owner's

// Contact folder. Any additional actions take on this contact will

// be performed in the mailbox owner's mailbox.

contact.Save(new FolderId(WellKnownFolderName.Contacts,

"[email protected]"));

// Verify that the contact was created.

// This method call results in a GetItem call to EWS

// to load the display name property on the contact.

contact.Load(new PropertySet (ContactSchema.DisplayName));

Console.WriteLine("\nContact created: " + contact.DisplayName + "\n");

Note that when you save the item, the Save method call must identify the mailbox
owner's Contacts folder. If the mailbox owner's Contacts folder is not specified, the
meeting request gets saved to the delegate's Contacts folder and not the mailbox
owner's Contacts folder. You can include the mailbox owner's Contacts folder in the
Save method call in two way. We recommend that you instantiate a new instance of the
FolderId object by using the WellKnownFolderName and the SMTP address of the
mailbox owner.

C#

contact.Save(new FolderId(WellKnownFolderName.Contacts,
"[email protected]"));

However, you can also Bind to the Contacts folder first, and then use the ID of the
folder in the Save method call. Be aware, however, that this creates an extra EWS call.

C#

// Identify the mailbox owner's SMTP address

// and bind to their Contacts folder.

Mailbox primary = new Mailbox("[email protected]");

Folder primaryContacts = Folder.Bind(service, new


FolderId(WellKnownFolderName.Contacts, primary));

// Save the contact to the mailbox owner's Contacts folder.

meeting.Save(primaryContacts.Id);

Create a contact as a delegate by using EWS


EWS enables you to use the service object for the delegate user to create contact items
for the mailbox owner. This example shows how to use the CreateItem operation to
create a contact.

This is also the XML request that the EWS Managed API sends when you use the Save
method to create a contact.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SaveOnly">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="contacts">

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:DistinguishedFolderId>

</m:SavedItemFolderId>

<m:Items>

<t:Contact>

<t:FileAsMapping>LastCommaFirst</t:FileAsMapping>

<t:GivenName>Brian</t:GivenName>

<t:MiddleName>David</t:MiddleName>

<t:CompanyName>Contoso</t:CompanyName>

<t:EmailAddresses>

<t:Entry Key="EmailAddress1">[email protected]</t:Entry>

<t:Entry Key="EmailAddress2">[email protected]</t:Entry>

</t:EmailAddresses>

<t:PhoneNumbers>

<t:Entry Key="BusinessPhone">425-555-0110</t:Entry>

<t:Entry Key="HomePhone">425-555-0120</t:Entry>

<t:Entry Key="CarPhone">425-555-0130</t:Entry>

</t:PhoneNumbers>

<t:Surname>Johnson</t:Surname>

</t:Contact>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode element value of NoError, which indicates that the
contact was created successfully. The response also contains the item ID of the newly
created contact.

Resolve a contact as a delegate by using the


EWS Managed API
To find a contact based on a possibly ambiguous name or term, you must use one of the
ExchangeService.ResolveName methods that includes a FolderId parameter, so that
you can specify the mailbox owner's Contacts folder.

C#

private static void DelegateAccessResolveContacts(ExchangeService service)

// Create a list to store folders to search.

List<FolderId> folders = new List<FolderId>();

// Add the mailbox owner's folder to the list.

folders.Add(new FolderId(WellKnownFolderName.Contacts,

"[email protected]"));

// Resolve the ambiguous name "Johnson".

// This method call results in a ResolveNames call to EWS.

NameResolutionCollection resolvedNames = service.ResolveName(

"johnson", folders, ResolveNameSearchLocation.ContactsOnly, true);

// Output the list of candidate email addresses and contact names.

foreach (NameResolution nameRes in resolvedNames)

Console.WriteLine("Contact e-mail address: " +


nameRes.Mailbox.Address);

Console.WriteLine("Contact ID: " + nameRes.Mailbox.Id);

After the ResolveNames method call returns a response with an ID, you can get, update
or delete the contact using the ID and implicit access—and you do not need to specify
the mailbox owner's SMTP address.
Resolve a contact as a delegate by using EWS
EWS enables you to use the service object for the delegate user to resolve partial names
in the mailbox owner's Contacts folder. This example shows how to use the
ResolveNames operation to find meetings in the mailbox owner's Contacts folder that
contain the word "johnson".

This is also the XML request that the EWS Managed API sends when you use the
ResolveName method to resolve a contact.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:ResolveNames ReturnFullContactData="true"

SearchScope="Contacts">

<m:ParentFolderIds>

<t:DistinguishedFolderId Id="contacts">

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:DistinguishedFolderId>

</m:ParentFolderIds>

<m:UnresolvedEntry>johnson</m:UnresolvedEntry>

</m:ResolveNames>

</soap:Body>

</soap:Envelope>

The server responds to the ResolveNames request with a ResolveNamesResponse


message that includes a ResponseCode element value of NoError, which indicates
that the operation completed successfully and found only one result, or
ErrorNameResolutionMultipleResults if multiple results were found - which is what's
shown in third code example based on the contact Create a contact as a delegate by
using the EWS Managed API. The response also contains the ItemId of each result.

The value of the ItemId element has been shortened for readability.

XML
<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="893"

MinorBuildNumber="17"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body>

<m:ResolveNamesResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:ResolveNamesResponseMessage ResponseClass="Warning">

<m:MessageText>Multiple results were found.</m:MessageText>

<m:ResponseCode>ErrorNameResolutionMultipleResults</m:ResponseCode>

<m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>

<m:ResolutionSet TotalItemsInView="2"

IncludesLastItemInRange="true">

<t:Resolution>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>Contact</t:MailboxType>

<t:ItemId Id="iMihAAA="

ChangeKey="EQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiPQo" />

</t:Mailbox>

</t:Resolution>

<t:Resolution>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>Contact</t:MailboxType>

<t:ItemId Id="iMihAAA="

ChangeKey="EQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiPQo" />

</t:Mailbox>

</t:Resolution>

</m:ResolutionSet>

</m:ResolveNamesResponseMessage>

</m:ResponseMessages>

</m:ResolveNamesResponse>

</s:Body>

</s:Envelope>

Now that you have the ItemId for the contacts that match the ambiguous name, you
can Get, update, or delete contact items as a delegate by using EWS by using the ItemId
and implicit access—and you do not need to specify the mailbox owner's SMTP address.

Get, update, or delete contact items as a


delegate by using the EWS Managed API
You can use the EWS Managed API to get, update, or delete a contact in the same way
that you perform these actions when you're not using delegate access. The only
difference is that the service object is for the delegate user. The item ID included in the
Bind method call uniquely identifies the item in the mailbox store, in the mailbox
owner's Contacts folder.

Table 2. EWS Managed API methods working with a contact as a delegate

Task EWS Managed API method Code example

Get a contact Bind


Get an item by using the EWS Managed API

Update a contact Bind followed by Update an item by using the EWS Managed
Update
API

Delete a contact Bind followed by Delete Delete an item by using the EWS Managed API

Get, update, or delete contact items as a


delegate by using EWS
You can use EWS to get, update, or delete a meeting or appointment contact in the
same way that you perform these actions when you're not using delegate access. The
only difference is that the service object is for the delegate user. The item ID included in
the GetItem request uniquely identifies the item in the mailbox store, in the mailbox
owner's Contacts folder.

Table 3. EWS operations for working with a contact as a delegate

Task EWS operation Sample

Get a contact GetItem


Get an item by using EWS

Task EWS operation Sample

Update a contact GetItem followed by UpdateItem


Update an item by using EWS

Delete a contact GetItem followed by DeleteItem


Delete an item by using EWS

See also
Delegate access and EWS in Exchange
Add and remove delegates by using EWS in Exchange
Set folder permissions for another user by using EWS in Exchange
People and contacts in EWS in Exchange
Resolve ambiguous names by using EWS in Exchange 2013
Access email as a delegate by using
EWS in Exchange
Article • 09/15/2021 • 9 minutes to read

Learn how to access email as a delegate by using the EWS Managed API or EWS in
Exchange.

You can use the EWS Managed API or EWS to give a user delegate access to a mailbox
owner's Inbox folder. The delegate can then create meeting requests on behalf of the
mailbox owner, search for email, and retrieve, update, and delete email from the
mailbox owner's Inbox folder, depending on their permissions.

As a delegate, you use the same methods and operations to access a mailbox owner's
Inbox folder that you use to access an Inbox folder without delegate access. The main
difference is that you have to use explicit access to find or create an email item, and
then after you identify the item ID, you can use implicit access to get, update, or delete
the item.

Table 1. EWS Managed API methods and EWS operations for accessing email as a
delegate

If you want Use this EWS Managed API method… Use this EWS operation…
to…

Create and EmailMessage.Save where the FolderId CreateItem where the


send an email parameter provides explicit access to the Mailbox element specifies the
as a delegate mailbox owner's Drafts folder EmailAddress of the mailbox
EmailMessage.SendAndSaveCopy where owner
the FolderId parameter provides explicit SendItem where the
access to the mailbox owner's Sent Items Mailbox element specifies the
folder EmailAddress of the mailbox
owner

Create ExchangeService.CreateItems where the CreateItem where the


multiple email FolderId parameter provides explicit access to Mailbox element specifies the
messages as a the mailbox owner's Inbox folder EmailAddress of the mailbox
delegate owner

Search for or ExchangeService.FindItems where the FindItem where the


find an email FolderId parameter provides explicit access to Mailbox element specifies the
as a delegate the mailbox owner's Inbox folder EmailAddress of the mailbox
owner

Get an email EmailMessage.Bind


GetItem

as a delegate
If you want Use this EWS Managed API method… Use this EWS operation…
to…

Update an EmailMessage.Bind followed by GetItem followed by


email as a EmailMessage.Update
UpdateItem

delegate

Delete an EmailMessage.Bind followed by GetItem followed by


email as a EmailMessage.Delete
DeleteItem

delegate

Keep the following things in mind when working with emails as a delegate:

If a delegate only needs to work with meeting requests and responses, the
delegate does not need access to the Inbox folder. For more information, see
prerequisite tasks for accessing calendars as a delegate.

When a recipient receives a message that was sent on behalf of a mailbox owner,
the sender appears as " Delegate on behalf of mailbox owner ."

7 Note

In the code examples in this article, [email protected] is the mailbox owner.

Prerequisite tasks
Before a user can access the mailbox owner's Inbox folder as a delegate, the user must
be added as a delegate with permissions to the mailbox owner's Inbox folder.

Create and send an email as a delegate by


using the EWS Managed API
The EWS Managed API enables you to use the service object for the delegate user to
create and send email on behalf of the mailbox owner. This example shows how to use
the Save method to save the message in the mailbox owner's Drafts folder, and then
the SendAndSaveCopy method to send the mail and save the message in the mailbox
owner's Sent Items folder.

This example assumes that service is a valid ExchangeService object for the delegate
and that the delegate has been granted the appropriate permissions for the mailbox
owner's Inbox, Drafts, and Sent Items folder.
C#

public static void DelegateAccessCreateEmail(ExchangeService service)

// Create an email message and provide it with connection

// configuration information by using an ExchangeService

// object named service.

EmailMessage message = new EmailMessage(service);

// Set properties on the email message.

message.Subject = "Company Soccer Team";

message.Body = "Are you interested in joining?";

message.ToRecipients.Add("[email protected]");

// Save the email to the mailbox owner's Drafts folder.

// This method call results in a CreateItem call to EWS.

// The FolderId parameter contains the context for the

// mailbox owner's Inbox folder. Any additional actions

// taken on this message will be performed in the mailbox

// owner's mailbox.

message.Save(new FolderId(WellKnownFolderName.Drafts, new


Mailbox("[email protected]")));
// Send the email and save the message in the mailbox owner's
// Sent Items folder.

// This method call results in a SendItem call to EWS.

message.SendAndSaveCopy(new FolderId(WellKnownFolderName.SentItems, new


Mailbox("[email protected]")));
Console.WriteLine("An email with the subject '" + message.Subject + "'
has been sent to '"

+ message.ToRecipients[0] + "' and saved in the Sent Items folder of the


mailbox owner.");

Create and send an email as a delegate by


using EWS
EWS enables you to use the service object for the delegate user to create and send
email on behalf of the mailbox owner. This example shows how to use the CreateItem
operation to create an email and the SendItem operation to send the time and save it
in the mailbox owner's Sent Items folder.

This is also the first XML request that the EWS Managed API sends when you use the
Save method to create and send an email.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version=" Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SaveOnly">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="drafts">

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:DistinguishedFolderId>

</m:SavedItemFolderId>

<m:Items>

<t:Message>

<t:Subject>Company Soccer Team</t:Subject>

<t:Body BodyType="HTML">Are you interested in joining?</t:Body>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode element value of NoError, which indicates that the
email was created and saved successfully. The response also contains the item ID of the
newly created email.

The ItemId value has been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="893"

MinorBuildNumber="17"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body>

<m:CreateItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:CreateItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:Message>
<t:ItemId Id="iNRaAAA="

ChangeKey="CQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiQPU"
/>

</t:Message>

</m:Items>

</m:CreateItemResponseMessage>

</m:ResponseMessages>

</m:CreateItemResponse>

</s:Body>

</s:Envelope>

Next, use the SendItem operation to send the message on behalf of the mailbox owner
and save it in the mailbox owner's Sent Items folder.

The ItemId value has been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version=" Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:SendItem SaveItemToFolder="true">

<m:ItemIds>

<t:ItemId Id="iNRaAAA="

ChangeKey="CQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiQPU" />

</m:ItemIds>

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="sentitems">

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:DistinguishedFolderId>

</m:SavedItemFolderId>

</m:SendItem>

</soap:Body>

</soap:Envelope>

The server responds to the SendItem request with a SendItemResponse message that
includes a ResponseCode element value of NoError, which indicates that the email
was sent and saved to the mailbox owner's Sent Items folder successfully.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="893"

MinorBuildNumber="17"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body>

<m:SendItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:SendItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

</m:SendItemResponseMessage>

</m:ResponseMessages>

</m:SendItemResponse>

</s:Body>

</s:Envelope>

Search for an email as a delegate by using the


EWS Managed API
To search for an email, you must use one of the ExchangeService.FindItems methods
that includes a FolderId parameter, so that you can specify the mailbox owner's Inbox
folder.

C#
static void DelegateAccessSearchEmailWithFilter(ExchangeService service)

// Limit the result set to 10 items.

ItemView view = new ItemView(10);

// Define the search filter.

SearchFilter.ContainsSubstring filter = new


SearchFilter.ContainsSubstring(ItemSchema.Subject,

"soccer", ContainmentMode.Substring, ComparisonMode.IgnoreCase);

view.PropertySet = new PropertySet(ItemSchema.Subject,

ItemSchema.DateTimeReceived,

EmailMessageSchema.IsRead);

// Item searches do not support deep traversal.

view.Traversal = ItemTraversal.Shallow;

// Sorting.

view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending);

try

// Call FindItems to find matching Inbox items.

// The parameters of FindItems must denote the mailbox owner,

// mailbox, and Inbox folder.

// This call results in a FindItem call to EWS.

FindItemsResults<Item> results = service.FindItems(new

FolderId(WellKnownFolderName.Inbox, "[email protected]"),

filter, view);

foreach (Item item in results.Items)

Console.WriteLine("Subject: {0}", item.Subject);

Console.WriteLine("Id: {0}", item.Id.ToString());

if (item is EmailMessage)

EmailMessage message = item as EmailMessage;

Console.WriteLine("Read: {0}", message.IsRead.ToString());

catch (Exception ex)

Console.WriteLine("Exception while enumerating results: {0}",


ex.Message);

After the FindItems call returns a response with an ID, you can get, update or delete that
email by using the ID and implicit access - and you do not need to specify the mailbox
owner's SMTP address.

Search for an email as a delegate by using EWS


EWS enables you to use the service object for the delegate user to search for emails that
meet a set of search criteria. This example shows how to use the FindItem operation
to find messages in the owner's Inbox folder that contain the word "soccer" in the
subject.

This is also the XML request that the EWS Managed API sends when you search for an
email.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version=" Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:FindItem Traversal="Shallow">

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="item:DateTimeReceived" />

<t:FieldURI FieldURI="message:IsRead" />

</t:AdditionalProperties>

</m:ItemShape>

<m:IndexedPageItemView MaxEntriesReturned="10"

Offset="0"

BasePoint="Beginning" />

<m:Restriction>

<t:Contains ContainmentMode="Substring"

ContainmentComparison="IgnoreCase">

<t:FieldURI FieldURI="item:Subject" />

<t:Constant Value="soccer" />

</t:Contains>

</m:Restriction>

<m:SortOrder>

<t:FieldOrder Order="Descending">

<t:FieldURI FieldURI="item:DateTimeReceived" />

</t:FieldOrder>

</m:SortOrder>

<m:ParentFolderIds>

<t:DistinguishedFolderId Id="inbox">

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:DistinguishedFolderId>

</m:ParentFolderIds>

</m:FindItem>

</soap:Body>

</soap:Envelope>

The server responds to the FindItem request with a FindItemResponse message that
includes a ResponseCode element value of NoError, which indicates that the search
completed successfully. The response contains a Message element for any emails that
met the search criteria. In this case, only one email is found.

The value of the ItemId element has been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="893"

MinorBuildNumber="17"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body>

<m:FindItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:FindItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootFolder IndexedPagingOffset="1"

TotalItemsInView="1"

IncludesLastItemInRange="true">

<t:Items>

<t:Message>

<t:ItemId Id="iNwoAAA="

ChangeKey="CQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiQuu" />

<t:Subject>Soccer team</t:Subject>

<t:DateTimeReceived>2014-03-
10T06:16:55Z</t:DateTimeReceived>

<t:IsRead>false</t:IsRead>

</t:Message>

</t:Items>

</m:RootFolder>

</m:FindItemResponseMessage>

</m:ResponseMessages>

</m:FindItemResponse>

</s:Body>

</s:Envelope>

Now that you have the ItemId for the email that meets your criteria, you can get,
update, or delete that email by using the ItemId and implicit access - and you do not
need to specify the mailbox owner's SMTP address.

Get, update, or delete email items as a delegate


by using the EWS Managed API
You can use the EWS Managed API to get, update, or delete an email in the same way
that you perform these actions when you're not using delegate access. The only
difference is that the ExchangeService object is for the delegate user. The item ID
included in the Bind method call uniquely identifies the item in the mailbox store, in the
mailbox owner's Inbox folder.

Table 2. EWS Managed API methods working with email as a delegate

Task EWS Managed API method Code example

Get an email Bind


Get an item by using the EWS Managed API

Update an email Bind followed by Update an item by using the EWS Managed
Update
API

Delete an email Bind followed by Delete


Delete an item by using the EWS Managed API

Get, update, or delete email items as a delegate


by using EWS
You can use the EWS Managed API to get, update, or delete an email in the same way
that you perform these actions when you're not using delegate access. The only
difference is that the service object is for the delegate user. The item ID included in the
GetItem request uniquely identifies the item in the mailbox store, in the mailbox owner's
Inbox folder.

Table 3. EWS operations for working with email as a delegate

Task EWS operation Code example

Get an email GetItem


Get an item by using EWS

Task EWS operation Code example

Update an email GetItem followed by UpdateItem


Update an item by using EWS

Delete an email GetItem followed by DeleteItem


Delete an item by using EWS

See also
Delegate access and EWS in Exchange
Add and remove delegates by using EWS in Exchange
Set folder permissions for another user by using EWS in Exchange
Calendars and EWS in Exchange
Set folder permissions for another user
by using EWS in Exchange
Article • 09/15/2021 • 12 minutes to read

Learn how to set permission levels on a folder by using the EWS Managed API or EWS in
Exchange.

Folder-level permissions enable users to access one or more folders in another user's
mailbox. Folder permissions are similar to delegate access, but they differ in the
following ways:

Folder permissions do not enable a user to "send on behalf of" or "send as"
another user. They only enable access to folders. Users can create items in those
folders, but they can't send them.

You can set folder permissions on any folder in the mailbox, but you can only add
a delegate to the Calendar, Contacts, Inbox, Journal, Notes, and Tasks folders.

You can set a number of permissions on a specific folder. When you add a
delegate, you can assign one of only five permission levels.

You can set folder permissions for anonymous and default users. You can only
grant delegate access to a mail-enabled account.

If you're familiar with Access Control Entries (ACEs) and Discretionary Access Control
Lists (DACLs), you know that a user can only have one set of permissions for each folder.
If you try to add a set of permissions for a user and they already have a set of
permissions, you'll get an error. When you add, remove, or update permissions on a
folder, you get the current DACL, add or remove any ACEs, and then send the updated
DACL. You cannot add multiple ACEs for the same user. When you update permissions
by using the EWS Managed API, you need to remove the user's current ACE and then
add their new ACE to the collection. If you're using EWS, you just replace the previous
set of ACEs with the new ones.

If you're making multiple permission changes to a single folder, you can batch additions,
removals, or updates —just note that you cannot batch user updates on multiple
folders. One call is required to get the permissions on a single folder, and a second call
is required to update the permissions on that folder. When you add, remove, or update
user permissions, you use the same two method calls or operations for each task.

Table 1. EWS Managed API methods and EWS operations for setting folder
permissions
If you want to… Use this EWS Managed API Use this EWS operation…
method…

Enable, remove, or update Folder.Bind followed by GetFolder followed by


folder permissions Folder.Update UpdateFolder

Create a folder and define Folder.Save


CreateFolder

folder permissions

Folder permissions
You have quite a few options when it comes to setting folder permissions on a specific
folder. You can set a permission level on a folder for each user, which adds a set of
predefined individual permissions to the DACL, or you can set individual permissions on
a folder — but you can't mix and match.

The following individual permissions are available:

Can create
Can create subfolders
Is folder owner
Is folder visible
Is folder contact
Edit items
Delete items
Read items

In addition, the following permission levels are available, which define a subset of
individual permissions and values, as shown in Table 2:

None
Owner
PublishingEditor
Editor
PublishingAuthor
Author
NoneditingAuthor
Reviewer
Contributor
Custom - This value cannot be set by the application. The server sets this value if
the application includes a custom collection of individual permissions.
FreeBusyTimeOnly - This can only be set on Calendar folders.
FreeBusyTimeAndSubjectAndLocation - This can only be set on Calendar folders.
The following table shows which individual permissions are applied by default based on
permission level.

Table 2. Individual permissions by permission level

Permission level Can Can Is Is Is Edit Delete Can read


create create folder folder folder items items items
items sub owner visible contact
folders

None False False False False False None None None

Owner True True True True True All All FullDetails

PublishingEditor True True False True False All All FullDetails

Editor True False False True False All All FullDetails

PublishingAuthor True True False True False Owned Owned FullDetails

Author True False False True False Owned Owned FullDetails

NoneditingAuthor True False False True False None Owned FullDetails

Reviewer False False False True False None None FullDetails

Contributor True False False True False None None None

If you specify a non-custom permission level in the folder-level permissions request, you
don't need to specify the individual permission settings. If you do specify an individual
permission when you set a permission level, an ErrorInvalidPermissionSettings error will
be returned in the response.

Adding folder permissions by using the EWS


Managed API
The following code example shows how to use the EWS Managed API to:

Create a new FolderPermission object for the new user.

Get the current permissions for a folder by using the Bind method.

Add the new FolderPermissions to the Folder.Permissions property.

Call the Update method to save the new permissions to the server.
This example assumes that service is a valid ExchangeService object for the mailbox
owner and that the user has been authenticated to an Exchange server.

C#

static void EnableFolderPermissions(ExchangeService service)

// Create a property set to use for folder binding.

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly,


FolderSchema.Permissions);

// Specify the SMTP address of the new user and the folder permissions
level.

FolderPermission fldperm = new FolderPermission("[email protected]",


FolderPermissionLevel.Editor);

// Bind to the folder and get the current permissions.

// This call results in a GetFolder call to EWS.

Folder sentItemsFolder = Folder.Bind(service,


WellKnownFolderName.SentItems, propSet);

// Add the permissions for the new user to the Sent Items DACL.

sentItemsFolder.Permissions.Add(fldperm);

// This call results in a UpdateFolder call to EWS.

sentItemsFolder.Update();

The following line of code specifies the permission level.

C#

FolderPermission fldperm = new FolderPermission("[email protected]",


FolderPermissionLevel.Editor);

If you want to use the custom permission level, use this code instead.

C#

FolderPermission fldperm = new FolderPermission();

fldperm.UserId = "[email protected]";

fldperm.CanCreateItems = true;

fldperm.CanCreateSubFolders = true;

You can set any or all of the writable FolderPermission properties when you create a
FolderPermission object with a custom permission level. Note, however, that the
FolderPermissionLevel is never explicitly set to Custom by the application. The
FolderPermissionLevel is set to Custom only when you create a FolderPermission object
and set individual permissions.
Adding folder permissions by using EWS
The following EWS code examples show how to add permissions to a specific folder by
retrieving the current permissions and then submitting a list of new permissions.

The first step is to send a GetFolder request, where the DistinguishedFolderId value
specifies the folder in which to add permissions (the Sent Items folder in this example)
and the FieldURI value includes folder:PermissionSet. This request will retrieve the
permission settings for the folder specified.

This is also the XML request that the EWS Managed API sends when you call the Bind
method to add folder permissions.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:GetFolder>

<m:FolderShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="folder:PermissionSet" />

</t:AdditionalProperties>

</m:FolderShape>

<m:FolderIds>

<t:DistinguishedFolderId Id="sentitems" />

</m:FolderIds>

</m:GetFolder>

</soap:Body>

</soap:Envelope>

The server responds to the GetFolder request with a GetFolderResponse message that
includes a ResponseCode element value of NoError, which indicates that the folder
was retrieved successfully. The FolderId and ParentFolderId values have been
shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="893"

MinorBuildNumber="17"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetFolderResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetFolderResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Folders>

<t:Folder>

<t:FolderId Id="CgAAAA=="

ChangeKey="AQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiRd1" />

<t:PermissionSet>

<t:Permissions>

<t:Permission>

<t:UserId>

<t:DistinguishedUser>Default</t:DistinguishedUser>

</t:UserId>

<t:CanCreateItems>false</t:CanCreateItems>

<t:CanCreateSubFolders>false</t:CanCreateSubFolders>

<t:IsFolderOwner>false</t:IsFolderOwner>

<t:IsFolderVisible>false</t:IsFolderVisible>

<t:IsFolderContact>false</t:IsFolderContact>

<t:EditItems>None</t:EditItems>

<t:DeleteItems>None</t:DeleteItems>

<t:ReadItems>None</t:ReadItems>

<t:PermissionLevel>None</t:PermissionLevel>

</t:Permission>

<t:Permission>

<t:UserId>

<t:DistinguishedUser>Anonymous</t:DistinguishedUser>

</t:UserId>

<t:CanCreateItems>false</t:CanCreateItems>

<t:CanCreateSubFolders>false</t:CanCreateSubFolders>

<t:IsFolderOwner>false</t:IsFolderOwner>

<t:IsFolderVisible>false</t:IsFolderVisible>

<t:IsFolderContact>false</t:IsFolderContact>

<t:EditItems>None</t:EditItems>

<t:DeleteItems>None</t:DeleteItems>

<t:ReadItems>None</t:ReadItems>

<t:PermissionLevel>None</t:PermissionLevel>

</t:Permission>

</t:Permissions>

</t:PermissionSet>

</t:Folder>

</m:Folders>

</m:GetFolderResponseMessage>

</m:ResponseMessages>

</m:GetFolderResponse>

</s:Body>

</s:Envelope>

Next, use the UpdateFolder operation to send the updated PermissionSet , which
includes the Permission for the new user. Note that including the SetFolderField
element for the respective folder in the UpdateFolder operation will overwrite all the
permission settings on the folder. Likewise, including the DeleteFolderField option of
the UpdateFolder operation will also delete all the permission settings on the folder.

This is also the XML request that the EWS Managed API sends when you call the Update
method to add folder permissions.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:UpdateFolder>

<m:FolderChanges>
<t:FolderChange>

<t:FolderId Id="CgAAAA=="

ChangeKey="AQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiRd1"
/>

<t:Updates>

<t:SetFolderField>

<t:FieldURI FieldURI="folder:PermissionSet" />

<t:Folder>

<t:PermissionSet>

<t:Permissions>

<t:Permission>

<t:UserId>

<t:DistinguishedUser>Default</t:DistinguishedUser>

</t:UserId>

<t:PermissionLevel>None</t:PermissionLevel>

</t:Permission>

<t:Permission>

<t:UserId>

<t:DistinguishedUser>Anonymous</t:DistinguishedUser>

</t:UserId>

<t:PermissionLevel>None</t:PermissionLevel>

</t:Permission>

<t:Permission>

<t:UserId>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

</t:UserId>

<t:PermissionLevel>Editor</t:PermissionLevel>

</t:Permission>

</t:Permissions>

</t:PermissionSet>

</t:Folder>

</t:SetFolderField>

</t:Updates>

</t:FolderChange>

</m:FolderChanges>

</m:UpdateFolder>

</soap:Body>

</soap:Envelope>

The following line of code specifies the permission level.

XML

<t:Permission>

<t:UserId>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

</t:UserId>

<t:PermissionLevel>Editor</t:PermissionLevel>

</t:Permission>

If you want to use the custom permission level, use this code instead.

XML

<t:Permission>

<t:UserId>

<t:PrimarySmtpAddress> [email protected] </t:PrimarySmtpAddress>

</t:UserId>

<t:CanCreateItems>true</t:CanCreateItems>

<t:CanCreateSubFolders>true</t:CanCreateSubFolders>

<t:IsFolderOwner>false</t:IsFolderOwner>

<t:IsFolderVisible>false</t:IsFolderVisible>

<t:IsFolderContact>false</t:IsFolderContact>

<t:EditItems>None</t:EditItems>

<t:DeleteItems>None</t:DeleteItems>

<t:ReadItems>None</t:ReadItems>

<t:PermissionLevel>Custom</t:PermissionLevel>

</t:Permission>

The server responds to the UpdateFolder request with an UpdateFolderResponse


message that includes a ResponseCode element value of NoError, which indicates
that the folder was updated successfully.

Removing folder permissions by using the EWS


Managed API
The following code example shows how to use the EWS Managed API to remove all user
permissions on a specific folder, except for the default and anonymous permissions, by:

1. Getting the current permissions for a folder by using the Bind method.

2. Iterating through the Permissions collection and removing permissions for


individual users.

3. Calling the Update method to save the changes.

This example removes all user permissions on a folder. If you want to modify this
example to remove permissions only for a specific user, change the following line of
code to identify either the display name or SMTP address of the user.

C#

if (sentItemsFolder.Permissions[t].UserId.DisplayName != null ||
sentItemsFolder.Permissions[t].UserId.PrimarySmtpAddress != null)

This example assumes that service is a valid ExchangeService object for the mailbox
owner and that the user has been authenticated to an Exchange server.

C#

static void RemoveFolderPermissions(ExchangeService service)

// Create a property set to use for folder binding.

PropertySet propSet = new


PropertySet(BasePropertySet.FirstClassProperties, FolderSchema.Permissions);

// Bind to the folder and get the current permissions.

// This call results in a GetFolder call to EWS.

Folder sentItemsFolder = Folder.Bind(service, new


FolderId(WellKnownFolderName.SentItems, "[email protected]"), propSet);

// Iterate through the collection of permissions and remove permissions


for any

// user with a display name or SMTP address. This leaves the anonymous
and

// default user permissions unchanged.

if (sentItemsFolder.Permissions.Count != 0)

for (int t = 0; t < sentItemsFolder.Permissions.Count; t++)

// Find any permissions associated with the specified user and


remove them from the DACL

if (sentItemsFolder.Permissions[t].UserId.DisplayName != null ||
sentItemsFolder.Permissions[t].UserId.PrimarySmtpAddress != null)

sentItemsFolder.Permissions.Remove(sentItemsFolder.Permissions[t]);

// This call results in an UpdateFolder call to EWS.

sentItemsFolder.Update();

Removing folder permissions by using EWS


The following EWS code examples show how to remove all user permissions on a
specific folder, except for the default and anonymous permissions.

First, send a GetFolder request where the DistinguishedFolderId value specifies the
folder in which to remove permissions (the Sent Items folder in this example) and the
FieldURI value includes folder:PermissionSet. This request will retrieve the
PermissionSet for the folder specified.

This is also the XML request that the EWS Managed API sends when you call the Bind
method to remove folder permissions.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:GetFolder>

<m:FolderShape>

<t:BaseShape>AllProperties</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="folder:PermissionSet" />

</t:AdditionalProperties>

</m:FolderShape>

<m:FolderIds>

<t:DistinguishedFolderId Id="drafts">

<t:Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:DistinguishedFolderId>

</m:FolderIds>

</m:GetFolder>

</soap:Body>

</soap:Envelope>

The server responds to the GetFolder request with a GetFolderResponse message that
includes a ResponseCode element value of NoError, which indicates that the folder
was retrieved successfully. The values of the FolderId and ParentFolderId elements have
been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="893"

MinorBuildNumber="17"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetFolderResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetFolderResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Folders>

<t:Folder>

<t:FolderId Id="EAAAAA=="

ChangeKey="AQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiRd5" />

<t:ParentFolderId Id="CQAAAA=="

ChangeKey="AQAAAA==" />

<t:FolderClass>IPF.Note</t:FolderClass>

<t:DisplayName>Drafts</t:DisplayName>

<t:TotalCount>0</t:TotalCount>

<t:ChildFolderCount>0</t:ChildFolderCount>

<t:EffectiveRights>

<t:CreateAssociated>true</t:CreateAssociated>

<t:CreateContents>true</t:CreateContents>

<t:CreateHierarchy>true</t:CreateHierarchy>

<t:Delete>true</t:Delete>

<t:Modify>true</t:Modify>

<t:Read>true</t:Read>

<t:ViewPrivateItems>true</t:ViewPrivateItems>

</t:EffectiveRights>

<t:PermissionSet>

<t:Permissions>

<t:Permission>

<t:UserId>

<t:DistinguishedUser>Default</t:DistinguishedUser>

</t:UserId>

<t:CanCreateItems>false</t:CanCreateItems>

<t:CanCreateSubFolders>false</t:CanCreateSubFolders>

<t:IsFolderOwner>false</t:IsFolderOwner>

<t:IsFolderVisible>false</t:IsFolderVisible>

<t:IsFolderContact>false</t:IsFolderContact>

<t:EditItems>None</t:EditItems>

<t:DeleteItems>None</t:DeleteItems>

<t:ReadItems>None</t:ReadItems>

<t:PermissionLevel>None</t:PermissionLevel>

</t:Permission>

<t:Permission>

<t:UserId>

<t:DistinguishedUser>Anonymous</t:DistinguishedUser>

</t:UserId>

<t:CanCreateItems>false</t:CanCreateItems>

<t:CanCreateSubFolders>false</t:CanCreateSubFolders>

<t:IsFolderOwner>false</t:IsFolderOwner>

<t:IsFolderVisible>false</t:IsFolderVisible>

<t:IsFolderContact>false</t:IsFolderContact>

<t:EditItems>None</t:EditItems>

<t:DeleteItems>None</t:DeleteItems>

<t:ReadItems>None</t:ReadItems>

<t:PermissionLevel>None</t:PermissionLevel>

</t:Permission>

<t:Permission>

<t:UserId>

<t:SID>S-1-5-21-1337771579-694202782-848329751-
1535223</t:SID>

<t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>

<t:DisplayName>Sadie Daniels</t:DisplayName>

</t:UserId>

<t:CanCreateItems>true</t:CanCreateItems>

<t:CanCreateSubFolders>false</t:CanCreateSubFolders>

<t:IsFolderOwner>false</t:IsFolderOwner>

<t:IsFolderVisible>true</t:IsFolderVisible>

<t:IsFolderContact>false</t:IsFolderContact>

<t:EditItems>All</t:EditItems>

<t:DeleteItems>All</t:DeleteItems>

<t:ReadItems>FullDetails</t:ReadItems>

<t:PermissionLevel>Editor</t:PermissionLevel>

</t:Permission>

</t:Permissions>

</t:PermissionSet>

<t:UnreadCount>0</t:UnreadCount>

</t:Folder>

</m:Folders>

</m:GetFolderResponseMessage>

</m:ResponseMessages>

</m:GetFolderResponse>

</s:Body>

</s:Envelope>

Next, use the UpdateFolder operation to send the updated PermissionSet, which does
not include the Permission for the removed user.

This is also the XML request that the EWS Managed API sends when you call the Update
method to remove folder permissions.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:UpdateFolder>

<m:FolderChanges>
<t:FolderChange>

<t:FolderId Id="EAAAAA=="

ChangeKey="AQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiRd5"
/>

<t:Updates>

<t:SetFolderField>

<t:FieldURI FieldURI="folder:PermissionSet" />

<t:Folder>

<t:PermissionSet>

<t:Permissions>

<t:Permission>

<t:UserId>

<t:DistinguishedUser>Default</t:DistinguishedUser>

</t:UserId>

<t:PermissionLevel>None</t:PermissionLevel>

</t:Permission>

<t:Permission>

<t:UserId>

<t:DistinguishedUser>Anonymous</t:DistinguishedUser>

</t:UserId>

<t:PermissionLevel>None</t:PermissionLevel>

</t:Permission>

</t:Permissions>

</t:PermissionSet>

</t:Folder>

</t:SetFolderField>

</t:Updates>

</t:FolderChange>

</m:FolderChanges>

</m:UpdateFolder>

</soap:Body>

</soap:Envelope>

The server responds to the UpdateFolder request with an UpdateFolderResponse


message that includes a ResponseCode element value of NoError, which indicates
that the update was successful.

Updating folder permissions by using the EWS


Managed API
You can also update folder permissions for a specific folder by using the EWS Managed
API. To update the permissions:

1. Remove the folder permissions for the outdated permissions, but do not call the
Update method (yet).

2. Add folder permissions for the new or changed users.

3. Call the Update method to save the changes.

If you try to add two sets of permissions for the same user, you will receive a
ServiceResponseException error with the following description: "The specified
permission set contains duplicate UserIds". In that case, remove the current permissions
from the Permission collection, then add the new permissions to the Permission
collection.

Updating folder permissions by using EWS


You can also update folder permissions for specific folders by using EWS by combining
the removal and addition process. To update the permissions:

1. Retrieve the folder's current permissions by using the GetFolder operation.

2. Send an updated list of permissions by using the UpdateFolder operation.

These are the same two operations you use to enable or remove access by using EWS.
The only difference is that when you receive the GetFolder response, it will contain a
Permission set for user. Simply replace that existing Permission element with the new
Permission element, and then send the UpdateFolder operation with the new
Permission value or values.

If you try to add two sets of permissions for the same user, you will receive a
ResponseCode value of ErrorDuplicateUserIdsSpecified. In that case, remove the
outdated Permission value for the user from the request and then retry the request.

Next steps
After you give a user permission to a specific folder, the user can access the folder as a
delegate. For more information, see:

Access email as a delegate by using EWS in Exchange

Access a calendar as a delegate by using EWS in Exchange

Access contacts as a delegate by using EWS in Exchange

See also
Delegate access and EWS in Exchange
Add and remove delegates by using EWS in Exchange
Folders and items in EWS in Exchange
Handling delegation-related errors in
EWS in Exchange
Article • 09/15/2021 • 2 minutes to read

Find out how to handle delegation-related errors in applications that you develop by
using the EWS Managed API or EWS in Exchange.

If your application uses delegation or adds or removes delegates, you might have to
handle delegation-related errors. You can handle these errors at runtime, or while you
are developing your EWS application. These errors are defined by the EWS Managed API
ServiceError enumeration and the EWS ResponseCode element.

Delegation-related errors
Error Occurs when Handle it by…
you try to…

ErrorItemNotFound Perform an Updating the delegate's


ErrorFolderNotFound operation on permissions to enable them to
a mailbox, access the folder or item by
folder, or calling the UpdateDelegates
item that you EWS Managed API method or
do not have the UpdateDelegate EWS
access to. operation, and then retrying the
request.

ErrorAccessDenied Modify an Updating your delegate


item that you permissions by calling the
do not have UpdateDelegate EWS Managed
sufficient API method or the
privileges to UpdateDelegate EWS
modify. operation, and then retrying the
request.

ErrorDelegateCannotAddOwner Attempt to Adding a different user as a


add the delegate, not the mailbox
mailbox owner.
owner as a
delegate to
their own
mailbox.
Error Occurs when Handle it by…
you try to…

ErrorDelegateAlreadyExists Add the Doing nothing, because the


delegate delegate already exists for the
when the mailbox owner. Or, if you're
delegate trying to change the
already permissions of an existing
exists. delegate, then use the
UpdateDelegates method or
the UpdateDelegate operation.

ErrorNotDelegate Modify Adding the user as a delegate


delegate for the mailbox before
permissions attempting to update or
for a user remove their permissions.
who has no
delegate
permissions
for the
mailbox.

ErrorDelegateNoUser Modify Creating the user in AD DS, or


delegate correcting the delegate
permissions information in the request.
for a user
who is not in
Active
Directory
Domain
Service (AD
DS).

ErrorSubscriptionDelegateAccessNotSupported Use a Subscribing to notifications as


delegate to the mailbox owner.
subscribe to
notifications
on behalf of
the mailbox
owner.
Error Occurs when Handle it by…
you try to…

ErrorWrongServerVersionDelegate Make a Using a delegate or adding a


request from delegate whose mailbox has
a delegate the same server version as the
that has a mailbox owner.
different
server
version than
the
principal's
mailbox
server.

ErrorMissingEmailAddress Make a Adding a mailbox to the


request using delegate's account.
a delegate
account that
does not
have a
mailbox.

See also
Delegate access and EWS in Exchange

Tools and resources for troubleshooting EWS applications for Exchange


Distribution groups and EWS in
Exchange
Article • 09/15/2021 • 5 minutes to read

Learn about the different types of distribution groups that are available in Exchange and
how you can manage them in your EWS Managed API or EWS application.

A distribution group is a collection of email addresses that are associated with a single
alias or email address. Distribution groups (also sometimes called distribution lists)
enable a user to send email to multiple people by using a single recipient address.
Because distribution group membership, and therefore the message recipients, can be
managed outside of individual email threads, distribution groups provide an excellent
way to enable the distribution of mail to a group of users. You can programmatically
create and manage distribution groups by using the EWS Managed API, EWS, and the
Exchange Management Shell. Before you start programming, let's explore the different
types of distribution groups that are available and your options for managing them.

Types of distribution groups


Exchange supports three types of distribution groups:

Universal distribution groups — Active Directory universal distribution group


objects that are mail-enabled. Universal distribution groups are used to distribute
messages to a group of recipients.

Security groups — Active Directory objects that are mail-enabled; also known as
universal security groups. Security groups are used to assign access permissions to
resources in Active Directory Domain Services (AD DS) as well as to distribute
messages.

Contact groups — Private distribution groups that are located in a user's mailbox.

The type of distribution group that you choose will depend on where you plan to store
the distribution group, who will use it, and what it will be used for.

Universal distribution groups


You can use universal distribution groups to consolidate groups of recipients into a
single alias or email address. Because universal distribution groups are stored in AD DS,
anyone can use them to send email, including users outside your organization. You can
use the EWS Managed API or EWS to expand a distribution group, but to create and
manage distribution groups, you'll need to use Exchange Management Shell cmdlets.

You can also use universal distribution groups to contain a collection of rooms; for
example, to make it easier for users to find a conference room for a meeting. Users can
add a room list — a universal distribution group that contains room resource mailboxes
— to a meeting request to find an available room without having to add each room
individually.

You can create a static universal distribution group that stays the same until you to
update the membership, or you can create a dynamic universal distribution group. A
dynamic universal distribution group queries Active Directory mail-enabled objects and
builds the group membership based on the results. The group membership is
recalculated whenever an email message is sent to the group.

Security groups
Universal distribution groups and security groups are identical in most ways. However,
unlike universal distribution groups, you can use security groups to assign permissions
to network resources in AD DS. You cannot use the EWS Managed API or EWS to create
and manage security groups; instead, you use Exchange Management Shell cmdlets.
But, just like universal distribution groups, you can use the EWS Managed API or EWS to
expand security groups.

Contact groups
If you don't want to give every user administrative access to the server to create
distribution groups, but you want to enable them to send a single message to a large
collection of people, you can do this by using contact groups. A contact group does not
have an email address associated with it, and it exists only in one user's mailbox; other
users won't have access to it. You can use the EWS Managed API or EWS to create
contact groups.

Managing distribution groups by using the


EWS Managed API or EWS
You can use the EWS Managed API or EWS to expand a universal distribution group or
security group and to control the creation and management of a contact group;
however, you cannot use these technologies to create or edit the members of those
groups.
Table 1. EWS Managed API methods and EWS operations for managing distribution
groups

EWS Managed EWS operation Use to…


API method

ContactGroup CreateItem
Create a contact group in the Exchange store.

class
methods NOTE: You cannot create a universal distribution group or
security group by using EWS Managed API or EWS.

ExpandGroup ExpandDL
Expand a universal distribution group, security group, or
contact group by retrieving a list of its members.

FindItems FindItem
Search for contact groups in the mailbox.

GetRooms
GetRooms
Retrieve a collection of all rooms in a specified room list in
an organization. A room list is a distribution group that only
contains room resource mailboxes.

ResolveName ResolveNames Search for and return possible candidates to match an


ambiguous name. The candidates can be distribution
groups.

You can use the information returned by the ExpandGroup method or the
ExpandDL operation to determine what types of members are in the group. The
member types are defined by the MailboxType EWS Managed API enumeration and
the MailboxType EWS element.

Table 2. Distribution group member types

MailboxType MailboxType Description


enumeration element
value value

Mailbox Mailbox A mail-enabled Active Directory object.

PublicGroup PublicDL A distribution group contained within the group you just
expanded. To get a full list of members, expand this group as
well.

ContactGroup PrivateDL A group of contacts that is located in the mailbox and is only
available to users of that mailbox.

Contact Contact An Exchange database contact or Active Directory mail contact.


Managing distribution groups by using the
Exchange Management Shell
You can use Exchange Management Shell cmdlets to create and manage universal
distribution groups and security groups in your code.

7 Note

You cannot use Exchange Management Shell cmdlets to manage contact groups.

Table 3. Exchange Management Shell cmdlets for working with distribution groups

Cmdlet Use to…

Disable-DistributionGroup Remove mail capabilities from a mail-enabled distribution group.

Enable-DistributionGroup
Mail-enable an existing universal group.

Get-DistributionGroup
Query for existing distribution groups.

New-DistributionGroup
Create a distribution group.

Remove- Delete an existing distribution group from AD DS.


DistributionGroup

Set-DistributionGroup
Modify the settings of an existing distribution group.

Add- Add a recipient to a distribution group.


DistributionGroupMember

Get- Find existing distribution group members.


DistributionGroupMember

Remove- Remove an existing recipient from a distribution group.


DistributionGroupMember

Update- Update a member of a specified distribution group.


DistributionGroupMember

Get- Retrieve the settings on an existing dynamic distribution group.


DynamicDistributionGroup

New- Create a dynamic distribution group.


DynamicDistributionGroup

Remove- Delete an existing dynamic distribution group. This cmdlet


DynamicDistributionGroup removes the dynamic distribution group from AD DS.
Cmdlet Use to…

Set- Modify the settings of an existing dynamic distribution group.


DynamicDistributionGroup

In this section
Create contact groups by using EWS in Exchange
Expand distribution groups by using EWS in Exchange 2013

See also
Develop web service clients for Exchange
Calling Exchange Management Shell Cmdlets from Managed Code
Create contact groups by using EWS in
Exchange
Article • 09/15/2021 • 2 minutes to read

Learn how to create a contact group by using the EWS Managed API or EWS in
Exchange.

You can create a contact group, which is a private distribution group, by using the EWS
Managed API or EWS. To create contact groups, use the methods in the ContactGroup
EWS Managed API class, or use the CreateItem EWS operation.

Note that you can't use the EWS Managed API or EWS to create a universal distribution
group or security group. To create a universal distribution group or security group, you
can use the New-DistributionGroup Exchange Management Shell cmdlet .

Create a contact group by using the EWS


Managed API
To create a contact group, you just need a couple pieces of information: a name for the
group, and the members to add to the group. The following example shows how to
create a simple contact group that contains a couple of group members.

C#

// Create a new contact group object.

ContactGroup myContactGroup = new ContactGroup(service);

// Give the group a name.

myContactGroup.DisplayName = "My Contact Group";

// Add some members to the group.


myContactGroup.Members.Add(new GroupMember("[email protected]"));

myContactGroup.Members.Add(new GroupMember("[email protected]"));

// Save the group.

myContactGroup.Save();

Create a contact group by using EWS


It might take a few more lines of code, but you can create a contact group by using the
CreateItem EWS operation. The following XML request example shows how you can
create a contact group. This is also the XML request that is sent when you use the EWS
Managed API to create a contact group.
XML

<?xml version="1.0" encoding="utf-8"?>

<CreateItem
xmlns="https://schemas.microsoft.com/exchange/services/2006/messages"

MessageDisposition="SaveOnly">

<Items
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages">

<DistributionList
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<DisplayName
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

My Contact Group

</DisplayName>

<Members
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<Member
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<Mailbox
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<EmailAddress
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

[email protected]

</EmailAddress>

</Mailbox>

</Member>

<Member
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<Mailbox
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<EmailAddress
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

[email protected]

</EmailAddress>

</Mailbox>

</Member>

</Members>

</DistributionList>

</Items>

</CreateItem>

The following is an example of a successful XML response to the request. Notice that the
values returned include an item ID for the new contact group and a change key that you
can use in other code to modify the contact group or expand the group to see the
members. The item ID is shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<CreateItemResponse
xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">

<ResponseMessages
xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">

<CreateItemResponseMessage ResponseClass="Success"

xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">

<ResponseCode
xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">

NoError

</ResponseCode>

<Items
xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">

<DistributionList
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<ItemId
xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

Id="AAMkADBlY…"

ChangeKey="EgAAABYAAAAD7hO1SJPWTbICFWZ4U3NMAABXzQiK" />

</DistributionList>

</Items>

</CreateItemResponseMessage>

</ResponseMessages>

</CreateItemResponse>

See also
Distribution groups and EWS in Exchange

Expand distribution groups by using EWS in Exchange 2013


Expand distribution groups by using
EWS in Exchange 2013
Article • 09/15/2021 • 4 minutes to read

Learn how to expand a distribution group by using the EWS Managed API or EWS in
Exchange.

You can use the ExchangeService.ExpandGroup EWS Managed API method or the
ExpandDL EWS operation to expand a distribution group to identify all recipients.

Because the ExpandGroup method is overloaded, you can call it in several ways:

ExpandGroup(String) - Expands a group identified by an SMTP address.

ExpandGroup(EmailAddress) - Expands a group identified by an email address.

ExpandGroup(ItemId) - Expands a group identified by a group ID.

ExpanGroup(String, String) - Expands a group identified by an SMTP address and


the routing type of that address.

Expand a universal distribution group or


security group by using EWS Managed API
The following example shows how to expand a universal distribution group or security
group by using an email address, which is the simplest approach. This example assumes
that service is a valid ExchangeService object and that the user has been
authenticated to an Exchange server.

C#

// Return the expanded group.

ExpandGroupResults myGroupMembers =
service.ExpandGroup("[email protected]");

// Display the group members.

foreach (EmailAddress address in myGroupMembers.Members)

Console.WriteLine("Email Address: {0}", address);

That's not a lot of code, but it's also pretty basic and might not give you what you are
looking for. So let's take it a step further. Distribution groups can also contain other
distribution groups. Simply expanding it will output the email address of the contained
distribution groups but not expand them. By adding a few more lines of code, you can
recursively expand the groups to output every contact.

C#

private static void ExpandDistributionLists(ExchangeService service, string


Mailbox)

// Return the expanded group.

ExpandGroupResults myGroupMembers = service.ExpandGroup(Mailbox);

// Display the group members.

foreach (EmailAddress address in myGroupMembers.Members)

// Check to see if the mailbox is a public group

if (address.MailboxType == MailboxType.PublicGroup)

// Call the function again to expand the contained

// distribution group.

ExpandDistributionLists(service, address.Address);

else

// Output the address of the mailbox.

Console.WriteLine("Email Address: {0}", address);

And now you can call this new function in the your code and expand all the public
distribution groups contained within the first one.

C#

ExpandDistributionLists(service, "[email protected]");

Expand a contact group by using EWS


Managed API
Because contact groups do not have an associated email address, you need to expand
the group based on the ItemId by using the ExpandGroup(ItemId) method. You can
create a function, as shown in the previous example, and change the second parameter
type from a string to an ItemId .
C#

private static void ExpandContactGroup(ExchangeService service, ItemId


groupID)

// Return the expanded group.

ExpandGroupResults myGroupMembers = service.ExpandGroup(groupID);

// Display the group members.

foreach (EmailAddress address in myGroupMembers.Members)

if (address.MailboxType == MailboxType.PublicGroup)

ExpandDistributionLists(service, address.Address);

else

Console.WriteLine("Email Address: {0}", address);

Now you can call this function by using the Exchange service object and the ItemId of
the contact group. Note that the ItemId in the example is shortened for readability.

C#

ExpandContactGroup(service, new ItemId("AAMkADBlY…");

Expand a universal distribution group or


security group by using EWS
The following example shows the XML request message that is sent from the client to
the server when you use the ExpandDL operation. This is also the XML request that
the EWS Managed API sends when you use the EWS Managed API to expand a universal
distribution group.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<soap:Body>

<ExpandDL
xmlns="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<Mailbox>

<t:EmailAddress>[email protected]</t:EmailAddress>

</Mailbox>

</ExpandDL>

</soap:Body>

</soap:Envelope>

The following example shows the XML response message that is sent from the server to
the client. Notice that both mailboxes and universal distribution groups are returned.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<ExpandDLResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<ResponseMessages
xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">

<ExpandDLResponseMessage ResponseClass="Success">

<ResponseCode>NoError</ResponseCode>

<DLExpansion IncludesLastItemInRange="true" TotalItemsInView="4">

<Mailbox
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<Name>Sadie Daniels</Name>

<EmailAddress>[email protected]</EmailAddress>

<RoutingType>SMTP</RoutingType>

<MailboxType>Mailbox</MailboxType>

</Mailbox>

<Mailbox
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<Name>Alfred Welker</Name>

<EmailAddress>[email protected]</EmailAddress>

<RoutingType>SMTP</RoutingType>

<MailboxType>Mailbox</MailboxType>

</Mailbox>

<Mailbox
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<Name>Contoso Sales</Name>

<EmailAddress>[email protected]</EmailAddress>

<RoutingType>SMTP</RoutingType>

<MailboxType>PublicDL</MailboxType>

</Mailbox>

<Mailbox
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<Name>Contoso Support</Name>

<EmailAddress>[email protected]</EmailAddress>

<RoutingType>SMTP</RoutingType>

<MailboxType>PublicDL</MailboxType>

</Mailbox>

</DLExpansion>

</ExpandDLResponseMessage>

</ResponseMessages>

</ExpandDLResponse>

</s:Body>

</s:Envelope>

Unlike when you use the EWS Managed API, when you use EWS to expand a universal
distribution group, you can't recursively expand the distribution groups that are
returned. You will need to send an additional request to expand each of the distribution
groups included in the response.

Expand a contact group by using EWS


The XML request to expand a contact group is similar to a request to expand a
distribution group. Instead of an email address, you use the ItemId of the contact
group. The ItemId in this example is shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<soap:Body>

<ExpandDL
xmlns="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<Mailbox>

<ItemId
xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
Id="AAMkADBlY…" />

</Mailbox>

</ExpandDL>

</soap:Body>

</soap:Envelope>

The structure of the XML response to a request to expand a contact group is the same
as the response to a request to expand a universal distribution group.

See also
Distribution groups and EWS in Exchange

Create contact groups by using EWS in Exchange


eDiscovery in EWS in Exchange
Article • 09/15/2021 • 2 minutes to read

Learn about eDiscovery in EWS in Exchange.

eDiscovery is a federated query web service that enables external applications to


perform queries of Exchange data.

Discovery consists of several phases, including identifying and preserving key data,
culling down and reviewing the data, and producing data in court. eDiscovery queries
facilitate the discovery process by providing a single discovery workflow across
Exchange and SharePoint.

eDiscovery operations
The eDiscovery functionality that is exposed by EWS is available via operations
introduced in Exchange Online, Exchange Online as part of Office 365, and versions of
Exchange starting with Exchange 2013.

Table 1. New operations for eDiscovery

Operation name Description

GetDiscoverySearchConfiguration Gets configuration information for in-place holds, saved


discovery searches, and the mailboxes that are enabled for
discovery search.

GetHoldOnMailboxes
Gets the status of a query-based hold, which is set by using
the SetHoldOnMailboxes operation .

GetNonIndexableItemDetails
Retrieves details about items that cannot be indexed. This
includes, but is not limited to, the item identifier, an error
code, an error description, when an attempt was made to
index the item, and additional information about the file.

GetNonIndexableItemStatistics
Retrieves the count of items that cannot be indexed in a
mailbox.

GetSearchableMailboxes
Gets a list of mailboxes that the client has permission to
search or perform eDiscovery on.

SearchMailboxes
Searches for items in specific mailboxes that match query
keywords.

SetHoldOnMailboxes
Sets a query-based hold on items.
See also
Develop web service clients for Exchange

Start using web services in Exchange

EWS client design overview for Exchange


Email and EWS in Exchange
Article • 09/14/2022 • 4 minutes to read

Find out how to work with email messages, including how to create an email and how to
perform other email-related tasks by using the EWS Managed API or EWS in Exchange.

At its core, Exchange is about email. But what makes an email an email? Well, email
messages are one of the strongly typed items in Exchange, which means that they
contain a particular set of properties, even before they're sent. Email messages are
represented by the EmailMessage class in the EWS Managed API and by the
Message element and its child elements in EWS.

In the EWS Managed API, the EmailMessage object derives from the Item object. The
EmailMessage class extends the Item class by providing additional properties like
EmailMessage.Sender and EmailMessage.IsRead , which are now common to nearly
all messaging scenarios. When you get, update, or delete an email message, in most
cases you can do that by using the EmailMessage object or the base Item object,
depending on whether the properties you're working with are in the
EmailMessageSchema or the ItemSchema class. Item creation is different because
the Item class does not have a constructor, so when you're creating an email, you'll use
the EmailMessage constructor to create it and the EmailMessage.Save or
EmailMessage.SendAndSaveCopy methods to save it, or send it and save it.

Similarly, in EWS, use the CreateItem operation with the Message element to create
an email message. To get, update, or delete emails by using EWS, the fact that the item
being modified is an email message is not important, aside from the fact that additional
properties are available on email messages. The same operations that are used for other
strongly typed items are also used for email messages.

Task EWS Managed API method EWS operation

Create EmailMessage.Save
CreateItem

Get EmailMessage.Bind
GetItem

Update Item.Update
UpdateItem

Delete Item.Delete
DeleteItem

Because email messages are simply strongly typed items, in some cases you work with
them in the same way that you work with generic items.
Create an email message by using the EWS
Managed API
You can create an email message by using the EWS Managed API Save method, as
shown in the code in the following example. Note that the example only saves the
message in the Drafts folder, it does not send the message. For information about how
to send the message or create and send the message in one step, see Send email
messages by using EWS in Exchange.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

C#

// Create a new email message.

EmailMessage message = new EmailMessage(service);

// Set properties on the email message.

message.ToRecipients.Add("[email protected]");

message.Subject = "Project priorities";

message.Body = "(1) Buy pizza, (2) Eat pizza";

// Save the email message to the Drafts folder (where it can be retrieved,
updated, and sent at a later time).

// This method call results in a CreateItem call to EWS.

message.Save(WellKnownFolderName.Drafts);

Console.WriteLine("A draft email message with the subject '" +


message.Subject + "' has been saved to the Drafts folder.");

Create an email message by using EWS


You can create an email message by using the EWS CreateItem operation, as shown in
the following example. This is also the XML request that the EWS Managed API sends
when you create an email message. Note that the following example only saves the
message in the Drafts folder, it does not send the message. For information about how
to send the message or create and send the message in one ste, see Send email
messages by using EWS in Exchange.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010_SP2" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SaveOnly">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="drafts" />

</m:SavedItemFolderId>

<m:Items>

<t:Message>

<t:Subject>Project priorities</t:Subject>

<t:Body BodyType="HTML">(1) Buy pizza, (2) Eat pizza</t:Body>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError, which indicates that the email was
created successfully, and the ItemId of the newly created message.

Get, update, and delete an email message by


using the EWS Managed API
You can use the EWS Managed API to get, update, or delete an email message in the
same way that you perform these actions on any generic item from the Exchange store.
For more information, see Work with Exchange mailbox items by using EWS in
Exchange.

If you're updating an email message, see Email properties and elements in EWS in
Exchange for a list of writable email message properties. To send a draft message after
you've updated it, see Send a draft email message by using the EWS Managed API.

Get, update, and delete an email message by


using EWS
You can use EWS to get, update, and delete an email message in the same way that you
perform these actions on any generic item from the Exchange store. For more
information, see Work with Exchange mailbox items by using EWS in Exchange.

If you're updating an email message, see Email properties and elements in EWS in
Exchange for a list of writable email message properties. To send a draft message after
you've updated it, see Send a draft email message by using EWS.

In this section
Email properties and elements in EWS in Exchange

Send email messages by using EWS in Exchange

Respond to email messages by using EWS in Exchange

Move and copy email messages by using EWS in Exchange

Work with conversations by using EWS in Exchange

Extract an entity from an email message by using EWS in Exchange

Process email messages in batches by using EWS in Exchange

See also
Develop web service clients for Exchange
Folders and items in EWS in Exchange
Email properties and elements in EWS in
Exchange
Article • 01/15/2020 • 4 minutes to read

Learn about the first-class and other properties and elements that you can get on email
messages by using the EWS Managed API or EWS in Exchange.

Email messages have more than 50 properties, and getting the ones you want, when
you want them, can be confusing if you don't know where to look. The most important
thing to know about working with email properties and elements is which are included
in the set of first-class properties and elements that is returned by each of the main
retrieval methods and operations. The set of first-class properties that is returned varies
based on the retrieval method that you use. It's also important not to be fooled by the
AllProperties value of the BaseShape EWS element, which corresponds to the
BasePropertySet.FirstClassMessageProperties enumeration value in the EWS Managed
API. This value doesn't actually include all properties, it only includes the first-class
properties.

First-class properties and elements for email


messages
The set of first-class properties and elements that are returned by the EWS Managed API
EmailMessage.Bind method and the EWS GetItem operation is slightly different
than the set of first-class properties and elements that is returned by the EWS Managed
API ExchangeService.FindItems method and the EWS FindItem operation. The first-
class properties returned by the FindItems method and FindItem operation are a subset
of the properties returned by the Bind method and GetItem operation. Table 1 lists all
the first-class properties returned by the Bind method and the GetItem operation, and
specifies which of those are not returned by the FindItems method or FindItem
operation. Note that you cannot extend the FindItems method or the FindItem
operation to retrieve additional properties and elements such as ToRecipients,
CcRecipients, and BccRecipients. If you need to retrieve those values, use the FindItems
method or the FindItem operation to get the item IDs of the emails, and then use the
Bind method or the GetItem operation, to retrieve the required properties. For code
examples that show how to retrieve items by using the Bind or the FindItems method,
see Get an item by using the EWS Managed API. For code examples that show how to
retrieve items by using the GetItem or FindItem operations, see Get an item by using
EWS.
The first-class properties and elements are listed in the following table in the order in
which they appear in a response.

Table 1. First-class email properties and elements

EWS Managed API property EWS element First-class Read-


property for write
the FindItems or
method or read-
the FindItem only
operation?

Id
ItemId
Yes Read-
only

ParentFolderId ParentFolderId Yes Read-


only

ItemClass
ItemClass
Yes Read-
write

Subject
Subject
Yes Read-
write

Sensitivity
Sensitivity
Yes Read-
only

Body
Body
No Read-
write

Attachments
Attachments
No Read-
write

DateTimeReceived
DateTimeReceived
Yes Read-
only

Size
Size
Yes Read-
only

Categories
Categories
No Read-
write

Importance
Importance
Yes Read-
write

InReplyTo
InReplyTo
Yes Read-
write

IsSubmitted
IsSubmitted
Yes Read-
only
EWS Managed API property EWS element First-class Read-
property for write
the FindItems or
method or read-
the FindItem only
operation?

IsDraft
IsDraft
Yes Read-
only

IsFromMe
IsFromMe
Yes Read-
only

IsResend
IsResend
Yes Read-
only

IsUnmodified
IsUnmodified
Yes Read-
only

InternetMessageHeaders
InternetMessageHeaders
No Read-
only

DateTimeSent
DateTimeSent
Yes Read-
only

DateTimeCreated
DateTimeCreated
Yes Read-
only

AllowedResponseActions
ResponseObjects
No Read-
only

ReminderDueBy
ReminderDueBy
Yes Read-
write

IsReminderSet
ReminderIsSet
Yes Read-
write

ReminderMinutesBeforeStart
ReminderMinutesBeforeStart
Yes Read-
write

DisplayCc
DisplayCc
Yes Read-
only

DisplayTo
DisplayTo
Yes Read-
only

HasAttachments
HasAttachments
Yes Read-
only

Culture
Culture
Yes Read-
write
EWS Managed API property EWS element First-class Read-
property for write
the FindItems or
method or read-
the FindItem only
operation?

EffectiveRights
EffectiveRights
Yes Read-
only

LastModifiedName
LastModifiedName
Yes Read-
only

LastModifiedTime
LastModifiedTime
Yes Read-
only

IsAssociated
IsAssociated
Yes Read-
write

WebClientReadFormQueryString WebClientReadFormQueryString Yes Read-


only

WebClientEditFormQueryString
WebClientEditFormQueryString
Yes Read-
only

ConversationId
ConversationId
Yes Read-
only

Flag
Flag
Yes Read-
write

InstanceKey
InstanceKey
Yes Read-
only

EntityExtractionResult
EntityExtractionResult
No Read-
only

Sender
Sender
Yes Read-
write

ToRecipients
ToRecipients
No Read-
only

CcRecipients
CcRecipients
No Read-
only

BccRecipients
BccRecipients
No Read-
only

IsReadReceiptRequested
IsReadReceiptRequested
Yes Read-
write
EWS Managed API property EWS element First-class Read-
property for write
the FindItems or
method or read-
the FindItem only
operation?

IsDeliveryReceiptRequested
IsDeliveryReceiptRequested
Yes Read-
write

ConversationIndex
ConversationIndex
Yes Read-
only

ConversationTopic
ConversationTopic
Yes Read-
only

From
From
Yes Read-
write

InternetMessageId
InternetMessageId
Yes Read-
only

IsRead
IsRead
Yes Read-
write

IsResponseRequested
IsResponseRequested
Yes Read-
write

ReplyTo
ReplyTo
No Read-
only

References
References
Yes Read-
write

ReceivedBy
ReceivedBy
Yes Read-
only

ReceivedRepresenting
ReceivedRepresenting
Yes Read-
only

Other properties and elements for email


messages
Not all important email properties and elements are first-class properties and elements.
To get the other properties or elements, you need to add them to your PropertySet if
you're using the EWS Managed API, or use a property path to add them to your EWS
operation call. For example, to retrieve the text body and the MIME content of a
message, create your PropertySet as shown for the Bind or Load method.
C#

PropertySet(BasePropertySet.IdOnly, ItemSchema.TextBody,
ItemSchema.MimeContent);

Or if you're using EWS, add the elements to the AdditionalProperties element in your
GetItem operation request, as shown.

XML

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:TextBody" />

<t:FieldURI FieldURI="item:MimeContent" />

</t:AdditionalProperties>

EmailMessage properties inherited from the EWS Managed API ServiceObject object
cannot be included in a property set for the Bind method; however, all the
ServiceObject properties are readable on the EmailMessage object and are retrieved by
the Bind method.

Table 2. Other email properties and elements

EWS Managed API property EWS element Read-write or read-only

ArchiveTag
ArchiveTag
Read-write

ExtendedProperties
ExtendedProperty
Read-only

IconIndex
IconIndex
Read-only

IsAttachment
Not available Read-only

IsDirty
Not available Read-only

IsNew
Not available Read-only

Item
Item
Read-only

MimeContent
MimeContent
Read-only

Not available MimeContentUTF8


Read-only

NormalizedBody
NormalizedBody
Read-only

PolicyTag
PolicyTag
Read-write

Preview
Preview
Read-write

RetentionDate
RetentionDate
Read-only
EWS Managed API property EWS element Read-write or read-only

Schema
Not available Read-only

Service
Not available Read-only

StoreEntryId
StoreEntryId
Read-only

TextBody
TextBody
Read-only

UniqueBody
UniqueBody
Read-only

See also
Email and EWS in Exchange

Properties and extended properties in EWS in Exchange

Property sets and response shapes in EWS in Exchange

Work with Exchange mailbox items by using EWS in Exchange


Send email messages by using EWS in
Exchange
Article • 01/15/2020 • 7 minutes to read

Learn how to send new or draft email messages, or to send a delayed email message by
using the EWS Managed API or EWS in Exchange.

Whether you are using the EWS Managed API or EWS, you can send email messages in
two ways. You can either send an existing message, such as a message stored in your
Drafts folder, or you can create and send an email in one step. The methods and
operations that you use to send the message are the same whether you're sending a
message immediately, or sending a delayed message.

Table 1. EWS Managed API methods and EWS operations for sending email messages

Task EWS Managed API method EWS operation

Send a new email message EmailMessage.SendAndSaveCopy


CreateItem

Send an existing email message EmailMessage.Send


SendItem

Send a new email message by using the EWS


Managed API
The following code example shows how to use the EmailMessage object to create an
email message and the SendAndSaveCopy method to send the message to the
recipient and save the message in the Sent Items folder.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

C#

// Create an email message and provide it with connection

// configuration information by using an ExchangeService object named


service.

EmailMessage message = new EmailMessage(service);

// Set properties on the email message.

message.Subject = "Company Soccer Team";

message.Body = "Are you interested in joining?";

message.ToRecipients.Add("[email protected]");

// Send the email message and save a copy.

// This method call results in a CreateItem call to EWS.

message.SendAndSaveCopy();

Console.WriteLine("An email with the subject '" + message.Subject + "' has


been sent to '" + message.ToRecipients[0] + "' and saved in the SendItems
folder.");

Send a new email message by using EWS


The following code example shows how to use the CreateItem operation with a
MessageDisposition value of SendAndSaveCopy to create an email message, send the
message to the recipient, and save the message in the Sent Items folder. This is also the
XML request that the EWS Managed API sends when you send a new email message.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SendAndSaveCopy">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="sentitems" />

</m:SavedItemFolderId>

<m:Items>

<t:Message>

<t:Subject>Company Soccer Team</t:Subject>

<t:Body BodyType="HTML">Are you interested in joining?</t:Body>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected] </t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError, which indicates that the email was
created successfully, and the ItemId of the newly created message.
Send a draft email message by using the EWS
Managed API
The following code example shows how to send a message that was stored in the Drafts
folder, as shown in Create an email message by using the EWS Managed API. First, use
the Bind method to retrieve the message, and then use the Send method to send
the email message, as shown in the following code example. Note that this method
does not save the sent message in the Sent Items folder.

In this case, the EmailMessageSchema.Subject and


EmailMessageSchema.ToRecipients properties are added to the PropertySet so that
the values can be included in the console output.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

C#

// As a best practice, create a property set that limits the properties


returned by the Bind method to only those that are required.

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly,


EmailMessageSchema.Subject, EmailMessageSchema.ToRecipients);

// This method call results in a GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, ItemId, propSet);

// Send the email message.

// This method call results in a SendItem call to EWS.

message.Send();

Console.WriteLine("An email with the subject '" + message.Subject + "' has


been sent to '" + message.ToRecipients[0] + "'.");

Send a draft email message by using EWS


The following code examples show how to send a message that was previously stored in
the Drafts folder, as shown in Create an email message by using EWS. First use the
GetItem operation to retrieve the email message to send. Then use the SendItem
operation to send the email message to recipients and save it in the Sent Items folder.

The first message, the GetItem request message, specifies the ItemId of the draft
email message to bind to, and elements in the ItemShape element limit the results to
include in the GetItem response. The ItemShape element has a BaseShape of IdOnly,
and the AdditionalProperties element includes the FieldURI values for the Subject
property from the Item schema and the ToRecipients property from the Message
schema, which means that only the ItemId, Subject , and ToRecipients elements will
be returned to the client in the response. For more information about limiting the values
returned in calls and the meaning of the BaseShape element, see Property sets and
response shapes in EWS in Exchange.

This is also the XML request that is sent by the EWS Managed API when calling the
Bind method. The values of some attributes and elements have been shortened for
readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="message:ToRecipients" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="AAMkADE4=" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The following example shows the XML response that the server returns after it processes
the GetItem operation. The response indicates that the email message was retrieved
successfully, and includes the Subject and ToRecipient elements as requested. The
values of some attributes and elements have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="842"

MinorBuildNumber="10"

Version="V2_8"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:Message>
<t:ItemId Id="AAMkADE4="

ChangeKey="CQAAABYA" />

<t:Subject>Project priorities</t:Subject>

<t:ToRecipients>

<t:Mailbox>

<t:Name>[email protected]</t:Name>

<t:EmailAddress>[email protected]</t:EmailAddress>

<t:RoutingType>SMTP</t:RoutingType>

<t:MailboxType>OneOff</t:MailboxType>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

The second message, the SendItem request message, specifies the ItemId of the email
message to send, as well as the SavedItemFolderId , which specifies the folder in which
to save the sent item.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:SendItem SaveItemToFolder="true">

<m:ItemIds>

<t:ItemId Id="AAMkADE4="

ChangeKey="CQAAABYA" />

</m:ItemIds>

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="sentitems" />

</m:SavedItemFolderId>

</m:SendItem>

</soap:Body>

</soap:Envelope>

The server responds to the SendItem request with a SendItemResponse message that
includes a ResponseCode value of NoError, which indicates that the email was sent
successfully.

Send a delayed email message by using the


EWS Managed API
The following code example shows how to use the EmailMessage object to create an
email message, the ExtendedPropertyDefinition class to create a property definition
for the PidTagDeferredSendTime (0x3FEF0040) property, and the SendAndSaveCopy
method to send a delayed message and save the message in the Sent Items folder.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

C#

// Create a new email message.

EmailMessage message = new EmailMessage(service);

// Specify the email recipient and subject.

message.ToRecipients.Add("[email protected]");

message.Subject = "Delayed email";

// Identify the extended property that can be used to specify when to send
the email.

ExtendedPropertyDefinition PidTagDeferredSendTime = new


ExtendedPropertyDefinition(16367, MapiPropertyType.SystemTime);

// Set the time that will be used to specify when the email is sent.

// In this example, the email will be sent one minute after the next line
executes,

// provided that the message.SendAndSaveCopy request is processed by the


server within one minute.

string sendTime = DateTime.Now.AddMinutes(1).ToUniversalTime().ToString();

// Specify when to send the email by setting the value of the extended
property.

message.SetExtendedProperty(PidTagDeferredSendTime, sendTime);

// Specify the email body.

StringBuilder str = new StringBuilder();

str.AppendLine("The client submitted the SendAndSaveCopy request at: " +


DateTime.Now.ToUniversalTime().ToString() + ".");

str.AppendLine("The email message will be sent at: " + sendTime + ".");

message.Body = str.ToString();

Console.WriteLine("");

Console.WriteLine("The client submitted the SendAndSaveCopy request at: " +


DateTime.Now.ToUniversalTime().ToString() + ".");

Console.WriteLine("The email message will be sent at: " + sendTime + ".");

// Submit the request to send the email message.

message.SendAndSaveCopy();

Send a delayed email message by using EWS


The following code example shows how to use the CreateItem operation with a
MessageDisposition value of SendAndSaveCopy to create an email message, the
ExtendedProperty element to create a property definition for the
PidTagDeferredSendTime (0x3FEF0040) property to set a time to send the message,
and the SavedItemFolderId element to save the sent message in the Sent Items folder.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange207_SP1" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SendAndSaveCopy">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="sentitems" />

</m:SavedItemFolderId>

<m:Items>

<t:Message>

<t:Subject>Delayed email</t:Subject>

<t:Body BodyType="HTML">

The client submitted the SendAndSaveCopy request at: 1/2/2014


9:08:52 PM.

The email message will be sent at: 1/2/2014 9:09:52 PM.

</t:Body>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="16367"

PropertyType="SystemTime" />

<t:Value>2014-01-02T21:09:52.000</t:Value>

</t:ExtendedProperty>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError, which indicates that the email was
created successfully, and the ItemId of the newly created message.

See also
Email and EWS in Exchange

Respond to email messages by using EWS in Exchange


Respond to email messages by using
EWS in Exchange
Article • 09/15/2021 • 7 minutes to read

Learn how to respond to email messages by using the EWS Managed API or EWS in
Exchange.

You can use the EWS Managed API or EWS to respond to messages by replying to them
or forwarding them to recipients.

Table 1. EWS Managed API methods and EWS operations for responding to email
messages

Task EWS Managed API method EWS operation

Reply to an EmailMessage.Reply
CreateItem , where the Items element has
email EmailMessage.CreateReply
a child element of either ReplyToItem or
message ReplyAllToItem .

Forward an EmailMessage.Forward
CreateItem , where the Items element has
email EmailMessage.CreateForward a child element of ForwardItem .
message

Reply to an email message by using the EWS


Managed API
The EWS Managed API provides two methods that you can use to respond to messages:
Reply and CreateReply . The Reply method only takes two parameters: the response
message to prepend to the existing body, and a Boolean value that indicates whether
the response should go to all recipients (true) or just the sender (false). If you need to
add additional recipients to a message, set additional properties on a response, or add
an attachment, use the CreateReply method, which enables you to set all the first-class
properties that are available on an EmailMessage object.

The following code example shows how to use the Reply method to respond to an
email message.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server. The local variable ItemId is the Id of
the item to respond to. The example calls the FindRecentlySent method to verify that
the message was marked as replied to.
C#

// As a best practice, limit the properties returned by the Bind method to


only those that are required.

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly,


ItemSchema.LastModifiedTime);

// Bind to the email message to reply to by using the ItemId.

// This method call results in a GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, ItemId, propSet);

string myReply = "This is the message body of the email reply.";

bool replyToAll = false;

// Send the response message.

// This method call results in a CreateItem call to EWS.

message.Reply(myReply, replyToAll);

// Verify that the response was sent by calling FindRecentlySent.

FindRecentlySent(message);

The following code example shows how to use the CreateReply method to respond to
an email message.

C#

// Bind to the email message to reply to by using the ItemId.

// This method call results in a GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, ItemId,


BasePropertySet.IdOnly);

// Create the reply response message from the original email message.

// Indicate whether the message is a reply or reply all type of reply.

bool replyToAll = true;


ResponseMessage responseMessage = message.CreateReply(replyToAll);

// Prepend the reply to the message body.

string myReply = "This is the message body of the email reply.";

responseMessage.BodyPrefix = myReply;

// Send the response message.

// This method call results in a CreateItem call to EWS.

responseMessage.SendAndSaveCopy();

// Check that the response was sent by calling FindRecentlySent.

FindRecentlySent(message);

If you need to add an attachment to the response message, replace the call to the
SendAndSaveCopy method with the following code.

C#

EmailMessage reply = responseMessage.Save();

reply.Attachments.AddFileAttachment("attachmentname.txt");

reply.Update(ConflictResolutionMode.AutoResolve);

reply.SendAndSaveCopy();

Reply to an email message by using EWS


The following code example shows how to reply to a message by using EWS. Use the
CreateItem operation with the MessageDisposition attribute set to
SendAndSaveCopy to send the message and save the response in the Sent Items folder.
Include either the ReplyAllToItem element as a child of the Items element to reply
to everyone on the message thread, or include the ReplyToItem element to reply only
to the sender.

This is also the XML request that the EWS Managed API sends when calling either the
Reply or the CreateReply method.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version=" Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SendAndSaveCopy">

<m:Items>

<t:ReplyAllToItem>

<t:ReferenceItemId Id="AAMkADE4="

ChangeKey="CQAAABYA" />

<t:NewBodyContent BodyType="HTML">This is the message body of the


email reply.</t:NewBodyContent>

</t:ReplyAllToItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode element value of NoError, which indicates that the
reply was created and sent successfully.

If you need to add an attachment to your response message, call the CreateItem
operation as specified above, but change the MessageDisposition to SaveOnly. Then
call the CreateAttachment operation, followed by the SendItem operation.
Forward an email message by using the EWS
Managed API
The EWS Managed API provides two methods that you can use to forward messages:
Forward and CreateForward . The Forward method only takes two parameters: the
message to prepend to the existing body, and an array or collection of recipients,
depending on the overload you choose to use. If you need to add an attachment to the
message you're forwarding, or set additional properties on the new message, use the
CreateForward method, which enables you to set all the properties that are available on
an EmailMessage object.

The following code example shows how to use the Forward method to forward an email
message to one recipient.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server. The local variable ItemId is the Id of
the item to forward. The example calls the FindRecentlySent method to verify that the
message was marked as forwarded.

C#

// Bind to the email message to reply to by using the ItemId.

// This method call results in a GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, ItemId,


BasePropertySet.IdOnly);

string myForward = "This is the message body of the forwarded email.";

// Send the response message.

// This method call results in a CreateItem call to EWS.

message.Forward(myForward, "[email protected]");

// Verify that the forwarded response was sent by calling FindRecentlySent.

FindRecentlySent(message);

The following code example shows how to use the CreateForward method to forward
an email message to one recipient.

C#

// Bind to the email message to reply to by using the ItemId.

// This method call results in a GetItem call to EWS.

EmailMessage message = EmailMessage.Bind(service, ItemId,


BasePropertySet.IdOnly);

// Create the reply response message from the original email message.

// Indicate whether the message is a reply or reply all type of reply.

ResponseMessage forwardMessage = message.CreateForward();

// Set properties on the email message.

forwardMessage.ToRecipients.Add("[email protected]");

forwardMessage.Body = "Sadie,<br><br>I thought you'd be interested in this


thread.<br><br>-Mack";

// Send and save a copy of the replied email message in the default Sent
Items folder.

forwardMessage.SendAndSaveCopy();
// Verify that the forwarded message was sent by calling FindRecentlySent.

FindRecentlySent(message);

If you need to add an attachment to the forwarded message, replace the call to the
SendAndSaveCopy method with the following code.

C#

EmailMessage forward = forwardMessage.Save();

forward.Attachments.AddFileAttachment("attachmentname.txt");

forward.Update(ConflictResolutionMode.AutoResolve);

forward.SendAndSaveCopy();

Forward an email message by using EWS


The following code example shows how to forward a message by using EWS. Use the
CreateItem operation with the MessageDisposition attribute set to
SendAndSaveCopy to send the message and save the response in the Sent Items folder.
The ForwardItem element indicates that the item is a forwarded message.

This is also the XML request that the EWS Managed API sends when calling either the
Forward or the CreateForward method.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SendAndSaveCopy">

<m:Items>

<t:ForwardItem>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

<t:ReferenceItemId Id="AAAMkADE="

ChangeKey="CQAAABYA" />

<t:NewBodyContent BodyType="HTML">This is the message body of the


forwarded email.</t:NewBodyContent>

</t:ForwardItem>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode element value of NoError, which indicates that the
forwarded message was created and sent successfully.

If you need to add an attachment to your response message, call the CreateItem
operation, but change the MessageDisposition to SaveOnly. Then call the
CreateAttachment operation, followed by the SendItem operation.

Find the message last replied to or forwarded


by using the EWS Managed API
The following code example shows how to find the last verb executed and the time the
last verb was executed on the item specified. This method is called from other EWS
Managed API code examples in this topic to verify that the items you replied to or
forwarded were marked as replied to or forwarded in your Inbox.

The example uses the PidTagLastVerbExecuted (0x10820003) extended property to


determine whether the message was a reply, a reply all, or a forward, and the
PidTagLastVerbExecutionTime (0x10820040) extended property to determine when
the reply or forward was sent.

C#

public static void FindRecentlySent(EmailMessage messageToCheck)

// Create extended property definitions for PidTagLastVerbExecuted and


PidTagLastVerbExecutionTime.

ExtendedPropertyDefinition PidTagLastVerbExecuted = new


ExtendedPropertyDefinition(0x1081, MapiPropertyType.Integer);

ExtendedPropertyDefinition PidTagLastVerbExecutionTime = new


ExtendedPropertyDefinition(0x1082, MapiPropertyType.SystemTime);

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly,


EmailMessageSchema.Subject, PidTagLastVerbExecutionTime,
PidTagLastVerbExecuted);

messageToCheck = EmailMessage.Bind(service, messageToCheck.Id, propSet);

// Determine the last verb executed on the message and display output.

object responseType;

if (messageToCheck.TryGetProperty(PidTagLastVerbExecuted, out
responseType))

object ReplyTime = null;

switch (((Int32)responseType))

case 102: Console.WriteLine("A reply was sent to the '" +


messageToCheck.Subject.ToString() + "' email message at");

break;

case 103: Console.WriteLine("A reply all was sent to the '" +


messageToCheck.Subject.ToString() + "' email message at");

break;

case 104: Console.WriteLine("The '" +


messageToCheck.Subject.ToString() + "' email message was forwarded at");

break;

if (messageToCheck.TryGetProperty(PidTagLastVerbExecutionTime, out
ReplyTime))

Console.WriteLine(((DateTime)ReplyTime).ToString() + ".");

else

Console.WriteLine("No changes were made to '" +


messageToCheck.Subject.ToString() + "'.");

See also
Email and EWS in Exchange

Send email messages by using EWS in Exchange


Move and copy email messages by
using EWS in Exchange
Article • 01/15/2020 • 5 minutes to read

Learn how to move and copy email messages by using the EWS Managed API or EWS in
Exchange.

You can use the EWS Managed API or EWS to move and copy email messages in a
mailbox.

Table 1. EWS Managed API methods and EWS operations for moving and copying
email messages

Task EWS Managed API method EWS operation

Move an email message EmailMessage.Move


MoveItem

Copy an email message EmailMessage.Copy


CopyItem

It's important to note that when you move or copy an email message into a different
folder, a new item is created in the new folder with a unique item ID, and the original
message is deleted. If you're moving or copying an email message between two folders
in the same mailbox, the new item is returned in the response, which gives you access to
the new item ID. However, if you're moving or copying an email message between two
mailboxes or between a mailbox and a public folder, the new item is not returned in the
response. To access the moved message in that scenario, use the EWS Managed API
FindItems method or EWS FindItem operation, create an extended property
definition for the PidTagSearchKey (0x300B0102) property, or create and set a custom
extended property and then search for the custom extended property in the new folder.

Deleting an email message is different than moving an item to the Deleted Items folder.
If you use the EWS Managed API Item.Delete method or the EWS DeleteItem
operation, the item specified in the request is removed from the original folder, and a
copy is placed in the Deleted Items folder with a new item ID. Unlike when you move or
copy any item, the new item is not returned in the Delete method or the DeleteItem
operation response. The steps involved in deleting an email by using the EWS Managed
API or EWS are the same as those for deleting any generic item from the Exchange
store.
Move an email message by using the EWS
Managed API
The following code example shows how to use the EmailMessage.Move method to
move an existing email message from one folder to another.

This example assumes that service is a valid ExchangeService object, and that ItemId
is the Id of the email message to move or copy.

C#

// As a best practice, limit the properties returned by the Bind method to


only those that are required.

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly,


EmailMessageSchema.Subject, EmailMessageSchema.ParentFolderId);

// Bind to the existing item by using the ItemId.

// This method call results in a GetItem call to EWS.

EmailMessage beforeMessage = EmailMessage.Bind(service, ItemId, propSet);

// Move the specified mail to the JunkEmail folder and store the returned
item.

Item item = beforeMessage.Move(WellKnownFolderName.JunkEmail);

// Check that the item was moved by binding to the moved email message

// and retrieving the new ParentFolderId.

// This method call results in a GetItem call to EWS.

EmailMessage movedMessage = EmailMessage.Bind(service, item.Id, propSet);

Console.WriteLine("An email message with the subject '" +


beforeMessage.Subject + "' has been moved from the '" +
beforeMessage.ParentFolderId + "' folder to the '" +
movedMessage.ParentFolderId + "' folder.");

Move an email message by using EWS


The following code example shows how to use the MoveItem operation to move an
email message to the Junk Email folder.

This is also the XML request that is sent by the EWS Managed API when calling the
Move method. The values of some attributes and elements have been shortened for
readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2013" />

</soap:Header>

<soap:Body>

<m:MoveItem>

<m:ToFolderId>

<t:DistinguishedFolderId Id="junkemail" />

</m:ToFolderId>

<m:ItemIds>

<t:ItemId Id="AfwDoAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF25sM1" />

</m:ItemIds>

</m:MoveItem>

</soap:Body>

</soap:Envelope>

The server responds to the MoveItem request with a MoveItemResponse message


that includes a ResponseCode value of NoError, which indicates that the email
message was moved successfully. The response also includes the ItemId for the email
message in the new folder, which is important to store because the ItemId is different in
the new folder.

Copy an email message by using the EWS


Managed API
The following code example shows how to use the EmailMessage.Copy method to
copy an existing email message from one folder to another.

This example assumes that service is a valid ExchangeService object, and that ItemId
is the Id of the email message to copy. The values of some parameters have been
shortened for readability.

C#

// As a best practice, limit the properties returned by the Bind method to


only those that are required.

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly,


EmailMessageSchema.Subject, EmailMessageSchema.ParentFolderId);

// Bind to the existing item by using the ItemId.

// This method call results in a GetItem call to EWS.

EmailMessage originalMessage = EmailMessage.Bind(service, ItemId, propSet);

// Copy the orignal message into another folder in the mailbox and store the
returned item.

Item item = originalMessage.Copy("epQ/3AAA=");

// Check that the item was copied by binding to the copied email message

// and retrieving the new ParentFolderId.

// This method call results in a GetItem call to EWS.

EmailMessage copiedMessage = EmailMessage.Bind(service, item.Id, propSet);

Console.WriteLine("An email message with the subject '" +


originalMessage.Subject + "' has been copied from the '" +
originalMessage.ParentFolderId + "' folder to the '" +
copiedMessage.ParentFolderId + "' folder.");

Copy an email message by using EWS


The following code example shows how to use the CopyItem operation to copy an
email message to different folder in the same mailbox by sending the ItemId of the
email message to move, and specifying the destination folder in the ToFolderId
element.

This is also the XML request that is sent by the EWS Managed API when calling the
Copy method. The values of some attributes and elements have been shortened for
readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2013" />

</soap:Header>

<soap:Body>

<m:CopyItem>

<m:ToFolderId>

<t:FolderId Id="pQ/3AAA=" />

</m:ToFolderId>

<m:ItemIds>

<t:ItemId Id="2TSeSAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF2d+3+" />

</m:ItemIds>

</m:CopyItem>

</soap:Body>

</soap:Envelope>

The server responds to the CopyItem request with a CopyItemResponse message that
includes a ResponseCode value of NoError, which indicates that the email message
was copied successfully. The response also includes the ItemId for the email message in
the new folder, which is important to store because the ItemId is different in the new
folder.
See also
Email and EWS in Exchange

Send email messages by using EWS in Exchange


Work with conversations by using EWS in
Exchange
Article • 09/15/2021 • 12 minutes to read

Learn about how to find conversations, apply actions to conversations, and get items in
conversations by using the EWS Managed API or EWS in Exchange.

In the context of Exchange, conversations are a way to group and manage a related set of
email messages. They can also provide a way to view related messages. Exchange defines
conversations based on the Message-ID value of the first email message in a thread. All
replies and related messages reference the original message's Message-ID header in their
References and In-Reply-To headers.

Additionally, inside the SOAP envelope, for each message received in a mailbox, Exchange
sets specific properties and elements.

Table 1. Conversation properties and elements set on all email messages

EWS Managed API EWS element Description


property

ConversationTopic ConversationTopic Contains a normalized form of the subject value that was
set on the original message. This is the same as the
Thread-Topic message header. This value is read-only.

ConversationIndex ConversationIndex Represents the position of the item in the conversation.


This is the same as the Thread-Index message header.
This value is read-only.

Exchange applies the same ConversationTopic value to replies to the first message and then
updates the ConversationIndex value to represent the message's position relative to the
original message. If the subject of the email thread changes, Exchange applies a new
ConversationTopic value and new ConversationIndex values to the new conversation.

Table 2. EWS Managed API methods and EWS operations for working with conversations

In order to… Use this EWS Managed API method or methods Use this EWS operation

Find ExchangeService.FindConversation
FindConversation

conversations
In order to… Use this EWS Managed API method or methods Use this EWS operation

Apply Conversation.EnableAlwaysCategorizeItems
ApplyConversationAction
conversation Conversation.EnableAlwaysDeleteItems

actions Conversation.EnableAlwaysMoveItems

ExchangeService.CopyItemsInConversations

ExchangeService.DeleteItemsInConversations

ExchangeService.DisableAlwaysCategorizeItemsInConversations
ExchangeService.DisableAlwaysDeleteItemsInConversations

ExchangeService.DisableAlwaysMoveItemsInConversations

ExchangeService.EnableAlwaysCategorizeItemsInConversations

ExchangeService.EnableAlwaysDeleteItemsInConversations

ExchangeService.EnableAlwaysMoveItemsInConversations

ExchangeService.MoveItemsInConversations

ExchangeService.SetFlagStatusForItemsInConversations

ExchangeService.SetReadStateForItemsInConversations

ExchangeService.SetRetentionPolicyForItemsInConversations

Get items in ExchangeService.GetConversationItems


GetConversationItems

one or more
conversations

Find a conversation by using the EWS Managed


API
You can find conversations by using the ExchangeService.FindConversation EWS Managed
API method, as shown in the following example. This example gets the first 10 conversations
in the Inbox folder that have a subject that contains the word "news". The example then writes
the conversation topic, last delivery time, and global unique recipient list to the console
window.

This example assumes that service is a valid ExchangeService object and that the user has
been authenticated to an Exchange server.

C#

static void FindConversation(ExchangeService service)

// Create the view of conversations returned in the response. This view will
return at most 10 results.

ConversationIndexedItemView view = new ConversationIndexedItemView(10);

// Create the query string to search for.

String queryString = "subject:news";

// Search the Inbox for conversations and return a results set with the
specified view.

// This method call results in a FindConversation call to EWS.

ICollection<Conversation> conversations = service.FindConversation(view,


WellKnownFolderName.Inbox, queryString);

// Examine properties on each conversation returned in the response.

foreach (Conversation conversation in conversations)

Console.WriteLine("Conversation Topic: " + conversation.Topic);

Console.WriteLine("Last Delivered: " +


conversation.LastDeliveryTime.ToString());

ApplyConversationActions(service, conversation);

foreach (string GlUniqRec in conversation.GlobalUniqueRecipients)

Console.WriteLine("Global Unique Recipient: " + GlUniqRec);

Console.WriteLine("");

Find a conversation by using EWS


You can find conversations by using the FindConversation EWS operation, as shown in the
following example. This example gets the first ten conversations in the Inbox folder that have
a subject that contains the word "news". This is also the XML request that the EWS Managed
API sends when you use the EWS Managed API to find a conversation.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2013" />

</soap:Header>

<soap:Body>

<m:FindConversation>

<m:IndexedPageItemView MaxEntriesReturned="10"

Offset="0"

BasePoint="Beginning" />

<m:ParentFolderId>

<t:DistinguishedFolderId Id="inbox" />

</m:ParentFolderId>

<m:QueryString>subject:news</m:QueryString>

</m:FindConversation>

</soap:Body>

</soap:Envelope>

The server responds to the FindConversation request with a FindConversationResponse


message that includes a ResponseCode value of NoError to indicate that the operation
completed successfully. The response also includes the only conversation in the mailbox that
has a subject that contains the word "news".
The ItemId, ChangeKey, and ConversationId elements have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="883"

MinorBuildNumber="10"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<FindConversationResponse ResponseClass="Success"

xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">

<ResponseCode>NoError</ResponseCode>

<Conversations>

<Conversation
xmlns="https://schemas.microsoft.com/exchange/services/2006/types">

<ConversationId Id="aO2NM+Q=" />

<ConversationTopic>Today's top news headlines</ConversationTopic>

<UniqueRecipients>

<String>Sadie Daniels</String>

</UniqueRecipients>

<GlobalUniqueRecipients>

<String>Sadie Daniels</String>

</GlobalUniqueRecipients>

<UniqueUnreadSenders>

<String>Ronnie Sturgis</String>

</UniqueUnreadSenders>

<GlobalUniqueUnreadSenders>

<String>Ronnie Sturgis</String>

</GlobalUniqueUnreadSenders>

<UniqueSenders>

<String>Ronnie Sturgis</String>

</UniqueSenders>

<GlobalUniqueSenders>

<String>Ronnie Sturgis</String>

</GlobalUniqueSenders>

<LastDeliveryTime>2014-02-18T20:42:26Z</LastDeliveryTime>

<GlobalLastDeliveryTime>2014-02-18T20:42:26Z</GlobalLastDeliveryTime>

<HasAttachments>false</HasAttachments>

<GlobalHasAttachments>false</GlobalHasAttachments>

<MessageCount>1</MessageCount>

<GlobalMessageCount>1</GlobalMessageCount>

<UnreadCount>1</UnreadCount>

<GlobalUnreadCount>1</GlobalUnreadCount>

<Size>9330</Size>

<GlobalSize>9330</GlobalSize>

<ItemClasses>
<ItemClass>IPM.Note</ItemClass>

</ItemClasses>

<GlobalItemClasses>

<ItemClass>IPM.Note</ItemClass>

</GlobalItemClasses>

<Importance>Normal</Importance>

<GlobalImportance>Normal</GlobalImportance>

<ItemIds>

<ItemId Id="sVCyAAA="

ChangeKey="CQAAAA==" />

</ItemIds>

<GlobalItemIds>

<ItemId Id="sVCyAAA="

ChangeKey="CQAAAA==" />

</GlobalItemIds>

<LastModifiedTime>2014-02-18T20:42:26Z</LastModifiedTime>

<InstanceKey>AQAAAAAAAQABAAAACbFYggAAAAA=</InstanceKey>

<HasIrm>false</HasIrm>

<GlobalHasIrm>false</GlobalHasIrm>

</Conversation>

</Conversations>

<TotalConversationsInView>1</TotalConversationsInView>

<IndexedOffset>1</IndexedOffset>

</FindConversationResponse>

</s:Body>

</s:Envelope>

Apply conversation actions by using the EWS


Managed API
You can apply conversation actions to a conversation by using a number of EWS Managed API
methods, as shown in the following example. This example adds categories to existing items
in a conversation and applies the same categories to future items in the conversation. It also
shows how to enable the automatic moving of items in the conversation to a folder. In this
example, items are moved to the Drafts folder.

This example assumes that service is a valid ExchangeService object and that the user has
been authenticated to an Exchange server.

For a complete list of methods that apply conversation actions, see Table 2.

C#

static void ApplyConversationActions(ExchangeService service, Conversation


conversation)

// Create a list of categories to apply to a conversation.

List<string> categories = new List<string>();

categories.Add("Customer");

categories.Add("System Integrator");

// Apply categorization to all items in the conversation and process the


request

// synchronously after enabling this rule and after all item categorization
has been applied.

// This method call results in an ApplyConversationAction call to EWS.

conversation.EnableAlwaysCategorizeItems(categories, true);

// Apply an always move rule to all items in the conversation and move the
items

// to the Drafts folder. Process the request asynchronously and return the
response.

// immediately. This method call results in an ApplyConversationAction call to


EWS.

conversation.EnableAlwaysMoveItems(WellKnownFolderName.Drafts, false);

Apply conversation actions by using EWS


You can apply conversation actions, such as categorize, delete, and move, by using the
ApplyConversationAction operation, as shown in the following example. This example adds
categories to existing items in a conversation and applies the same categories to future items
in the conversation. It also shows how to enable the automatic moving of items in the
conversation to a folder; in this example, items are moved to the Drafts folder. This is also the
XML request that the EWS Managed API sends when you use the EWS Managed API to apply
conversation actions.

The ConversationId element has been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2013" />

</soap:Header>

<soap:Body>

<m:ApplyConversationAction>

<m:ConversationActions>

<t:ConversationAction>

<t:Action>AlwaysMove</t:Action>

<t:ConversationId Id="jG6WVpg=" />

<t:ProcessRightAway>false</t:ProcessRightAway>
<t:DestinationFolderId>

<t:DistinguishedFolderId Id="drafts" />

</t:DestinationFolderId>

</t:ConversationAction>

</m:ConversationActions>

</m:ApplyConversationAction>

</soap:Body>

</soap:Envelope>

The server responds to the ApplyConversationAction request with a


ApplyConversationActionResponse message that includes a ResponseCode value of
NoError to indicate that the operation completed successfully.

Get items in a single conversation by using the


conversation identifier in the EWS Managed API
You can get items in a conversation by using the ExchangeService.GetConversationItems
EWS Managed API method. This example provides the set of conversation nodes for the first
conversation in the Inbox. The item identifier, subject, and received time for each item are
returned in the response, along with the conversation index and parent conversation index
properties. You can use the conversation index properties to reconstruct the node hierarchy.

In this example, all conversation items in the default Deleted Items and Drafts folders are
ignored.

This example assumes that service is a valid ExchangeService object and that the user has
been authenticated to an Exchange server.

C#

static void GetConversationItemsSingleConversation(ExchangeService service)

try

// Find the first item in the mailbox.

// This method call results in an FindItem call to EWS.

FindItemsResults<Item> results =
service.FindItems(WellKnownFolderName.Inbox,

new ItemView(1));

// Get the conversation identifier of the item.

ConversationId convId = results.Items[0].ConversationId;

// Specify the properties that will be

// returned for the items in the conversation.

PropertySet properties = new PropertySet(BasePropertySet.IdOnly,

ItemSchema.Subject,

ItemSchema.DateTimeReceived);

// Identify the folders to ignore.

Collection<FolderId> foldersToIgnore = new Collection<FolderId>()

{ WellKnownFolderName.DeletedItems, WellKnownFolderName.Drafts };

// Request the conversation items.

// This method call results in an GetConversationItems call to EWS.

ConversationResponse response = service.GetConversationItems(convId,

properties,

null,

foldersToIgnore,

ConversationSortOrder.TreeOrderDescending);

// Get the synchronization state of the conversation.

Console.WriteLine("SyncState: " + response.SyncState);

Collection<Item> items = new Collection<Item>();

// Process each node of conversation items.

foreach (ConversationNode node in response.ConversationNodes)

Console.WriteLine("Parent conversation index: " +


node.ParentConversationIndex);

Console.WriteLine("Conversation index: " + node.ConversationIndex);

Console.WriteLine("Conversation node items:");

// Process each item in the conversation node.

foreach (Item item in node.Items)

Console.WriteLine(" Item ID: " + item.Id.UniqueId);

Console.WriteLine(" Subject: " + item.Subject);

Console.WriteLine(" Received: " + item.DateTimeReceived);

items.Add(item);

// This exception occurs if there is an error with the service.


catch (ServiceResponseException srException)

Console.WriteLine(srException);

We recommend that you cache the SyncState property for subsequent requests to get items
in the conversation.

Get items in many conversations by using the


ConversationRequest object in the EWS Managed
API
You can use the ConversationRequest object and the
ExchangeService.GetConversationItems EWS Managed API method to get items from two
or more conversations. This example provides a set of conversation nodes for the first two
conversations in the Inbox. The item identifier, subject, and the received time for each item
will be returned in the response, along with the conversation index and parent conversation
index properties. You can use the conversation index properties to reconstruct the node
hierarchy. This example assumes that the first two items in the Inbox are from different
conversations.

In this example, all conversation items in the default Deleted Items and Drafts folders are
ignored.
This example assumes that service is a valid ExchangeService object and that the user has
been authenticated to an Exchange server.

C#

static void GetConversationItemsManyConversations(ExchangeService service)

try

// Find the first two items in the Inbox. This item will be used to call
the GetConversationItems operation.

// This method call results in an FindItem call to EWS.

FindItemsResults<Item> results =
service.FindItems(WellKnownFolderName.Inbox, new ItemView(2));

// Get the conversation identifier of the first two items in the Inbox.

ConversationId convId1 = results.Items[0].ConversationId;

ConversationId convId2 = results.Items[1].ConversationId;

// Identify two conversation requests.

ConversationRequest convR1 = new ConversationRequest();

convR1.ConversationId = convId1;

ConversationRequest convR2 = new ConversationRequest();

convR2.ConversationId = convId2;

// Create a collection of conversations to fetch.

Collection<ConversationRequest> conversations = new


Collection<ConversationRequest>();

conversations.Add(convR1);

conversations.Add(convR2);

// Specify the properties that will be returned for the items in the
conversation.

PropertySet properties = new PropertySet(BasePropertySet.IdOnly,

ItemSchema.Subject,

ItemSchema.DateTimeReceived);

// Identify the folders to ignore.

Collection<FolderId> foldersToIgnore = new Collection<FolderId>()

{ WellKnownFolderName.DeletedItems, WellKnownFolderName.Drafts };

// Request the conversation items.

// This method call results in an GetConversationItems call to EWS.

ServiceResponseCollection<GetConversationItemsResponse> responses =

service.GetConversationItems(conversations, properties,
foldersToIgnore,

ConversationSortOrder.TreeOrderDescending);

// Process each conversation.

foreach (GetConversationItemsResponse resp in responses)

// Identify the synchronization state of the conversation.

Console.WriteLine("Sync State: " + resp.Conversation.SyncState);

// Process each node in the conversation.

foreach (ConversationNode node in resp.Conversation.ConversationNodes)

Console.WriteLine("Parent conversation index: " +


node.ParentConversationIndex);

Console.WriteLine("Conversation index: " + node.ConversationIndex);

Console.WriteLine("Conversation node items:");

// Process each item in the conversation node.

foreach (Item item in node.Items)

Console.WriteLine(" Item ID: " + item.Id.UniqueId);

Console.WriteLine(" Subject: " + item.Subject);

Console.WriteLine(" Received: " + item.DateTimeReceived);

// This exception occurs if there is an error with the service.


catch (ServiceResponseException srException)

Console.WriteLine(srException);

As a best practice, we recommend that you return only the properties that the client
application requires, rather than using the FirstClassProperties option for the
BasePropertySet class. We recommend that you cache the SyncState property for subsequent
requests to get items in the conversation.

Get items in conversations by using the


conversation identifier in EWS
You can get items in a conversation by using the GetConversationItems EWS operation. This
example provides a set of conversation nodes for the first conversation in the Inbox. The item
identifier, subject, and received time for each item are returned in the response, along with
the conversation index and parent conversation index properties. You can use the
conversation index properties to reconstruct the node hierarchy.

In this example, all conversation items in the default Deleted Items and Drafts folders are
ignored.

The ConversationId element has been shortened for readability.

To get items from more than one conversation, include additional Conversation elements.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m=https://schemas.microsoft.com/exchange/services/2006/messages

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2013" />

</soap:Header>

<soap:Body>

<m:GetConversationItems>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="item:DateTimeReceived" />

</t:AdditionalProperties>

</m:ItemShape>

<m:FoldersToIgnore>

<t:DistinguishedFolderId Id="deleteditems" />

<t:DistinguishedFolderId Id="drafts" />

</m:FoldersToIgnore>

<m:SortOrder>TreeOrderDescending</m:SortOrder>

<m:Conversations>
<t:Conversation>

<t:ConversationId Id="LUQFH6Q=" />

</t:Conversation>

</m:Conversations>

</m:GetConversationItems>

</soap:Body>

</soap:Envelope>

The server responds to the GetConversationItems request with a


GetConversationItemsResponse message that includes a ResponseCode value of NoError
to indicate that the operation completed successfully. The response also includes the
ConversationNodes in the conversation.

The ItemId, SyncState, and ConversationId elements have been shortened for readability.

XML

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="873"

MinorBuildNumber="9"

Version="V2_9"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetConversationItemsResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetConversationItemsResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Conversation>

<t:ConversationId Id="LUQFH6Q=" />

<t:SyncState>AAAAYAm1</t:SyncState>

<t:ConversationNodes>

<t:ConversationNode>

<t:InternetMessageId>&amp;lt;994051d7c1a346efbfce8dec2cbad509

@SN2SR01MB006.com&amp;gt;</t:InternetMessageId>

<t:ParentInternetMessageId>&amp;lt;faa2b1df30074380abe3527b0cd18ca5

@SN2SR01MB001.com&amp;gt;</t:ParentInternetMessageId>

<t:Items>

<t:Message>

<t:ItemId Id="AYB1NAAA="

ChangeKey="CQAAABYAAAD/oydcA+SPQZGbKWNyvNIZAAAAYCHq" />

<t:Subject>RE: Review Proposal for Tailspin Toys</t:Subject>

<t:DateTimeReceived>2014-01-02T13:15:00Z</t:DateTimeReceived>

</t:Message>

</t:Items>

</t:ConversationNode>

<t:ConversationNode>

<t:InternetMessageId>&amp;lt;faa2b1df30074380abe3527b0cd18ca5

@SN2SR01MB001.com&amp;gt;</t:InternetMessageId>

<t:ParentInternetMessageId>&amp;lt;6a8e7658524b41cda7cdc3f23c1074a5

@SN2SR01MB001.com&amp;gt;</t:ParentInternetMessageId>

<t:Items>

<t:Message>

<t:ItemId Id="lQAAAA=="

ChangeKey="CQAAABYAAAD/oydcA+SPQZGbKWNyvNIZAAAAYAu8" />

<t:Subject>RE: Review Proposal for Tailspin Toys</t:Subject>

<t:DateTimeReceived>2014-01-02T10:02:08Z</t:DateTimeReceived>

</t:Message>

</t:Items>

</t:ConversationNode>

<t:ConversationNode>

<t:InternetMessageId>&amp;lt;bcdb185495834370a874a1e7ebedbb96

@SN2SR01MB005.com&amp;gt;</t:InternetMessageId>

<t:ParentInternetMessageId>&amp;lt;e52a4de6b98d484887e141da094a2ce6

@SN2SR01MB006.com&amp;gt;</t:ParentInternetMessageId>

<t:Items>

<t:Message>

<t:ItemId Id="igAAAA=="

ChangeKey="CQAAABYAAAD/oydcA+SPQZGbKWNyvNIZAAAAYAuj" />

<t:Subject>RE: Review Proposal for Tailspin Toys</t:Subject>

<t:DateTimeReceived>2014-01-02T16:20:10Z</t:DateTimeReceived>

</t:Message>

</t:Items>

</t:ConversationNode>

<t:ConversationNode>

<t:InternetMessageId>&amp;lt;e52a4de6b98d484887e141da094a2ce6

@SN2SR01MB006.com&amp;gt;</t:InternetMessageId>

<t:ParentInternetMessageId>&amp;lt;f0db3ead01db4fe087d98022149aa16f

@SN2SR01MB001.com&amp;gt;</t:ParentInternetMessageId>

<t:Items>

<t:Message>

<t:ItemId Id="iwAAAA=="

ChangeKey="CQAAABYAAAD/oydcA+SPQZGbKWNyvNIZAAAAYAul" />

<t:Subject>RE: Review Proposal for Tailspin Toys</t:Subject>

<t:DateTimeReceived>2014-01-02T15:30:10Z</t:DateTimeReceived>

</t:Message>

</t:Items>

</t:ConversationNode>

<t:ConversationNode>

<t:InternetMessageId>&amp;lt;f0db3ead01db4fe087d98022149aa16f

@SN2SR01MB001.com&amp;gt;</t:InternetMessageId>

<t:ParentInternetMessageId>&amp;lt;88b1884ecaaa4f68b081c009d827e8c6

@SN2SR01MB003.com&amp;gt;</t:ParentInternetMessageId>

<t:Items>

<t:Message>

<t:ItemId Id="jQAAAA=="

ChangeKey="CQAAABYAAAD/oydcA+SPQZGbKWNyvNIZAAAAYAuq" />

<t:Subject>RE: Review Proposal for Tailspin Toys</t:Subject>

<t:DateTimeReceived>2014-01-02T14:20:10Z</t:DateTimeReceived>

</t:Message>

</t:Items>

</t:ConversationNode>

<t:ConversationNode>

<t:InternetMessageId>&amp;lt;88b1884ecaaa4f68b081c009d827e8c6

@SN2SR01MB003.com&amp;gt;</t:InternetMessageId>

<t:ParentInternetMessageId>&amp;lt;faa2b1df30074380abe3527b0cd18ca5

@SN2SR01MB001.com&amp;gt;</t:ParentInternetMessageId>

<t:Items>

<t:Message>

<t:ItemId Id="kAAAAA=="

ChangeKey="CQAAABYAAAD/oydcA+SPQZGbKWNyvNIZAAAAYAux" />

<t:Subject>RE: Review Proposal for Tailspin Toys</t:Subject>

<t:DateTimeReceived>2014-01-02T12:52:09Z</t:DateTimeReceived>

</t:Message>

</t:Items>

</t:ConversationNode>

</t:ConversationNodes>

</m:Conversation>

</m:GetConversationItemsResponseMessage>

</m:ResponseMessages>

</m:GetConversationItemsResponse>

</s:Body>

</s:Envelope>

Version differences
When you are using Exchange Server 2010 Service Pack 1 (SP1), the FindConversation
method has fewer options available, and the FindConversation operation has fewer
elements in the request.
Table 3. Exchange 2010 SP1 version support for FindConversation

EWS Managed API method EWS elements

FindConversation (ViewBase, FolderId)


IndexedPageItemView

SortOrder

ParentFolderId

The GetConversationItems EWS Managed API method and the GetConversationItems


EWS operation were introduced in Exchange Server 2013. Applications that target earlier
versions of Exchange can only apply conversation actions to conversations, as listed in Table 2.

The FindConversation EWS Managed API method and the FindConversation EWS method are
not available in the initial release version of Exchange 2010 or in Exchange 2007.

See also
Email and EWS in Exchange
Use search filters with EWS in Exchange
Exchange 2013: Find conversations in mailboxes programmatically
Exchange 2013: Apply actions to manage conversations in a mailbox
Extract an entity from an email message
by using EWS in Exchange
Article • 01/15/2020 • 7 minutes to read

Learn how to extract information from the body of an email message by using the EWS
Managed API or EWS in Exchange.

You can use the EWS Managed API or EWS to access the addresses, contacts, email
addresses, meeting suggestions, phone numbers, tasks, and URLs that an Exchange
server extracts from email messages. You can then use this information for new
applications or to suggest follow up actions in existing applications. For example, if a
contact entity, meeting suggestion, or task suggestion is identified in an email, your
application can suggest that a new item with prepopulated information be created. By
using extracted entities, you can capitalize on the intent behind the data — and help
users seamlessly integrate their email message content into actionable results.

Entity extraction for addresses, contacts, email addresses, meeting suggestions, phone
numbers, tasks, and URLs is already built in to every item in the Exchange store. If you're
using the EWS Managed API, the Item.EntityExtractionResult property retrieves the
entities for you in an Item.Bind method call. If you're using EWS, the
EntityExtractionResult element gets all the extracted entities for you in a GetItem
operation call. After you retrieve the results of the extracted entities, you can walk
through each entity collection to gather pertinent information. For example, if a meeting
suggestion was extracted, you can retrieve the suggested meeting subject, attendee list,
start time, and end time.

Table 1. EWS Managed API properties and EWS elements that contain extracted
entities

Extracted entity EWS Managed API property EWS element

Addresses EntityExtractionResult.Addresses
Addresses

Contacts EntityExtractionResult.Contacts
Contacts

Email addresses EntityExtractionResult.EmailAddresses


EmailAddresses

Meeting suggestions EntityExtractionResult.MeetingSuggestions


MeetingSuggestions

Phone numbers EntityExtractionResult.PhoneNumbers


PhoneNumbers

Task suggestions EntityExtractionResult.TaskSuggestions


TaskSuggestions

Extracted entity EWS Managed API property EWS element

URLs EntityExtractionResult.Urls
Urls

Because entity extraction relies on natural language recognition, the recognition of


entities can be non-deterministic and success sometimes relies on the context. To
demonstrate how natural language recognition works, the examples in this article use
the following email as input.

From: Ronnie Sturgis

To: Sadie Daniels

Subject: Dinner party

Hi Sadie

Are you free this Friday at 7 to join us for a dinner party at our house?

We're at 789 International Blvd, St Paul MN 55104.

Our number is 612-555-0158 if you have trouble finding it.

Please RSVP to either myself or Mara ([email protected]) before Friday morning. Best
for you organics (http://www.bestforyouorganics.com) will be catering so we can

fully enjoy ourselves!

Also, can you forward this to Magdalena? I don't have her contact information.

See you then!

Ronnie

Extract all entities from an email by using the


EWS Managed API
The following code example shows how to display all the entities extracted by the
server, by using the Item.Bind method, and then enumerating through each of the
extracted entities and their properties.

This example assumes that service is a valid ExchangeService object, and that ItemId
is the Id of the email message to move or copy.

C#
public static void ExtractEntities(ExchangeService service, ItemId ItemId)

// Create a property set that limits the properties returned

// by the Bind method to only those that are required.

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly,


ItemSchema.EntityExtractionResult);

// Get the item from the server.

// This method call results in an GetItem call to EWS.

Item item = Item.Bind(service, ItemId, propSet);

Console.WriteLine("The following entities have been extracted from the


message:");

Console.WriteLine(" ");

// If address entities are extracted from the message, print the


results.

if (item.EntityExtractionResult != null)

if (item.EntityExtractionResult.Addresses != null)

Console.WriteLine("--------------------Addresses----------------
-----------");

foreach (AddressEntity address in


item.EntityExtractionResult.Addresses)

Console.WriteLine("Address: {0}", address.Address);

Console.WriteLine(" ");

// If contact entities are extracted from the message, print the


results.

if (item.EntityExtractionResult.Contacts != null)

Console.WriteLine("--------------------Contacts-----------------
-----------");

foreach (ContactEntity contact in


item.EntityExtractionResult.Contacts)

Console.WriteLine("Addresses: {0}",
contact.Addresses);

Console.WriteLine("Business name: {0}",


contact.BusinessName);

Console.WriteLine("Contact string: {0}",


contact.ContactString);

Console.WriteLine("Email addresses: {0}",


contact.EmailAddresses);

Console.WriteLine("Person name: {0}",


contact.PersonName);

Console.WriteLine("Phone numbers: {0}",


contact.PhoneNumbers);

Console.WriteLine("URLs: {0}", contact.Urls);

Console.WriteLine(" ");

// If email address entities are extracted from the message, print


the results.

if (item.EntityExtractionResult.EmailAddresses != null)

Console.WriteLine("--------------------Email addresses----------
-----------");

foreach (EmailAddressEntity email in


item.EntityExtractionResult.EmailAddresses)

Console.WriteLine("Email addresses: {0}",


email.EmailAddress);

Console.WriteLine(" ");

// If meeting suggestion entities are extracted from the message,


print the results.

if (item.EntityExtractionResult.MeetingSuggestions != null)

Console.WriteLine("--------------------Meeting suggestions------
-----------");

foreach (MeetingSuggestion meetingSuggestion in


item.EntityExtractionResult.MeetingSuggestions)

Console.WriteLine("Meeting subject: {0}",


meetingSuggestion.Subject);

Console.WriteLine("Meeting string: {0}",


meetingSuggestion.MeetingString);
foreach (EmailUserEntity attendee in
meetingSuggestion.Attendees)

Console.WriteLine("Attendee name: {0}",


attendee.Name);

Console.WriteLine("Attendee user ID: {0}",


attendee.UserId);

Console.WriteLine("Start time: {0}",


meetingSuggestion.StartTime);

Console.WriteLine("End time: {0}",


meetingSuggestion.EndTime);

Console.WriteLine("Location: {0}",
meetingSuggestion.Location);

Console.WriteLine(" ");

// If phone number entities are extracted from the message, print


the results.

if (item.EntityExtractionResult.PhoneNumbers != null)

Console.WriteLine("--------------------Phone numbers------------
-----------");

foreach (PhoneEntity phone in


item.EntityExtractionResult.PhoneNumbers)

Console.WriteLine("Original phone string: {0}",


phone.OriginalPhoneString);

Console.WriteLine("Phone string: {0}",


phone.PhoneString);

Console.WriteLine("Type: {0}",
phone.Type);

Console.WriteLine(" ");

// If task suggestion entities are extracted from the message, print


the results.

if (item.EntityExtractionResult.TaskSuggestions != null)

Console.WriteLine("--------------------Task suggestions---------
-----------");

foreach (TaskSuggestion task in


item.EntityExtractionResult.TaskSuggestions)

foreach (EmailUserEntity assignee in task.Assignees)

Console.WriteLine("Assignee name: {0}",


assignee.Name);

Console.WriteLine("Assignee user ID: {0}",


assignee.UserId);

Console.WriteLine("Task string: {0}", task.TaskString);

Console.WriteLine(" ");

// If URL entities are extracted from the message, print the


results.

if (item.EntityExtractionResult.Urls != null)

Console.WriteLine("--------------------URLs---------------------
-----------");

foreach (UrlEntity url in item.EntityExtractionResult.Urls)

Console.WriteLine("URL: {0}", url.Url);

Console.WriteLine(" ");

// If no entities are extracted from the message, print the result.

else if (item.EntityExtractionResult == null)

Console.WriteLine("No entities extracted");

The following output is displayed on the console.

text

The following entities have been extracted from the message:

--------------------Addresses---------------------------

Address: 789 International Blvd, St Paul MN 55104

--------------------Contacts----------------------------

Addresses:

Business name:

Contact string: Mara ([email protected])

Email addresses: [email protected]


Person name: Mara

Phone numbers:

URLs:

--------------------Email addresses---------------------

Email addresses: [email protected]


--------------------Meeting suggestions-----------------

Meeting subject: dinner party

Meeting string: Are you free this Friday at 7 to join us for a dinner
party at our house?

Attendee name: Ronnie Sturgis

Attendee user ID: [email protected]

Attendee name: Sadie Daniels

Attendee user ID: [email protected]

Start time: 10/1/0104 2:00:00 PM

End time: 10/1/0104 2:30:00 PM

Location:

--------------------Phone numbers-----------------------

Original phone string: 612-555-0158

Phone string: 6125550158

Type: Unspecified

--------------------Task suggestions--------------------

Assignee name: Sadie Daniels

Assignee user ID: [email protected]

Task string: Also, can you forward this to Magdalena?

--------------------URLs--------------------------------

URL: http://www.bestforyouorganics.com

Notice that all addresses, contacts, email addresses, phone numbers, tasks, and URLs
were extracted as expected. The meeting suggestion, however, is a bit more complex.
Notice the start time and end time of the meeting suggestion are not what you might
expect. The start time in the email is "this Friday at 7", but the extracted value for the
start time is 10/1/0104 2:00:00 PM. This is because the start time and end time extracted
by the server are encoded dates. For more information about how to interpret dateTime
values in meeting suggestions, see [MS-OXCEXT]: Client Extension Message Object
Protocol .

Extract all entities from an email by using EWS


The following code example shows how to use the GetItem operation and the
EntityExtractionResult element to retrieve the extracted entities from an item.

This is also the XML request that is sent by the EWS Managed API when you use the
Bind method to Extract all entities from an email by using the EWS Managed API.

The value of the ItemId element is shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2013" />

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:EntityExtractionResult" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="sVC5AAA=" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The server responds to the GetItem request with a GetItemResponse message that
includes a ResponseCode value of NoError, which indicates that the email message
was retrieved successfully. The response also includes the EntityExtractionResult for
each extracted entity.

The value of the ItemId element is shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="883"

MinorBuildNumber="10"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:Message>
<t:ItemId Id="sVC5AAA="

ChangeKey="CQAAABYAAAD32nSTjepyT63rYH17n9THAAAOOqJN"
/>

<t:EntityExtractionResult>

<t:Addresses>

<t:AddressEntity>

<t:Position>LatestReply</t:Position>

<t:Address>789 International Blvd, St Paul MN


55104</t:Address>

</t:AddressEntity>

</t:Addresses>

<t:MeetingSuggestions>

<t:MeetingSuggestion>

<t:Position>LatestReply</t:Position>

<t:Attendees>

<t:EmailUser>

<t:Name>Ronnie Sturgis</t:Name>

<t:UserId>[email protected]</t:UserId>

</t:EmailUser>

<t:EmailUser>

<t:Name>Sadie Daniels</t:Name>

<t:UserId>[email protected]</t:UserId>

</t:EmailUser>

</t:Attendees>

<t:Subject>dinner party</t:Subject>

<t:MeetingString>Are you free this Friday at 7 to join


us for a dinner party at our house?</t:MeetingString>

<t:StartTime>0104-10-01T19:00:00Z</t:StartTime>

<t:EndTime>0104-10-01T19:30:00Z</t:EndTime>

</t:MeetingSuggestion>

</t:MeetingSuggestions>

<t:TaskSuggestions>

<t:TaskSuggestion>

<t:Position>LatestReply</t:Position>

<t:TaskString>Also, can you forward this to Magdalena?


</t:TaskString>

<t:Assignees>

<t:EmailUser>

<t:Name>Sadie Daniels</t:Name>

<t:UserId>[email protected]</t:UserId>

</t:EmailUser>

</t:Assignees>

</t:TaskSuggestion>

</t:TaskSuggestions>

<t:EmailAddresses>

<t:EmailAddressEntity>

<t:Position>LatestReply</t:Position>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:EmailAddressEntity>

</t:EmailAddresses>

<t:Contacts>

<t:Contact>

<t:Position>LatestReply</t:Position>

<t:PersonName>Mara</t:PersonName>

<t:EmailAddresses>

<t:EmailAddress>[email protected]</t:EmailAddress>

</t:EmailAddresses>

<t:ContactString>Mara
([email protected]</t:ContactString>

</t:Contact>

</t:Contacts>

<t:Urls>

<t:UrlEntity>

<t:Position>LatestReply</t:Position>

<t:Url>http://www.bestforyouorganics.com</t:Url>

</t:UrlEntity>

</t:Urls>

<t:PhoneNumbers>

<t:Phone>

<t:Position>LatestReply</t:Position>

<t:OriginalPhoneString>612-555-
0158</t:OriginalPhoneString>

<t:PhoneString>6125550158</t:PhoneString>

<t:Type>Unspecified</t:Type>

</t:Phone>

</t:PhoneNumbers>

</t:EntityExtractionResult>

</t:Message>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

Notice that all addresses, contacts, email addresses, phone numbers, tasks, and URLs
were extracted as expected. The meeting suggestion, however, is a bit more complex.
Notice the start time and end time of the meeting suggestion are not what you might
expect. The start time in the email was "this Friday at 7", but the extracted value for the
start time is 10/1/0104 2:00:00 PM. This is because the start time and end time extracted
by the server are encoded dates. For more information about interpreting dateTime
values in meeting suggestions, see [MS-OXCEXT]: Client Extension Message Object
Protocol .

See also
Email and EWS in Exchange
Item.EntityExtractionResult
EntityExtractionResult
Process email messages in batches by
using EWS in Exchange
Article • 01/15/2020 • 12 minutes to read

Learn how to create, get, update, and delete batches of email messages in a single call
by using the EWS Managed API or EWS in Exchange.

You can use the EWS Managed API or EWS to work with batches of email messages to
reduce the number of calls a client makes to an Exchange server. When you use the EWS
Managed API to create, get, update, delete, and send messages in batches, you use
ExchangeService object methods, whereas when you work with single email messages,
you use EmailMessage object methods. If you are using EWS, you use the same
operations to work with both single and batches of email messages.

Table 1. EWS Managed API methods and EWS operations for working with batches of
email messages

In order to… Use this EWS Managed API Use this EWS
method operation

Create email messages in batches ExchangeService.CreateItems


CreateItem

Get email messages in batches ExchangeService.BindToItems


GetItem

Update email messages in ExchangeService.UpdateItems


UpdateItem

batches

Delete email messages in batches ExchangeService.DeleteItems


DeleteItem

In this article, you'll learn how to complete basic tasks for batches of email messages by
using the EWS Managed API or EWS.

Create email messages in batches by using the


EWS Managed API
You can create messages in batches by using the EWS Managed API CreateItems
method, as shown in the following example. This example creates three EmailMessage
objects locally, adds each message to a collection, then calls the CreateItems method on
the collection of messages.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.
C#

public static Collection<ItemId> CreateDraftEmailInBatch(ExchangeService


service)

// These are unsaved local instances of an EmailMessage object.

// Despite the required parameter of an ExchangeService object


(service), no call

// to an Exchange server is made when the objects are instantiated.

// A call to the Exchange server is made when the service.CreateItems()


method is called.

EmailMessage message1 = new EmailMessage(service);

EmailMessage message2 = new EmailMessage(service);

EmailMessage message3 = new EmailMessage(service);

// Set the properties on the first message.

message1.Subject = "Project priorities";

message1.Body = "(1) Buy pizza, (2) Eat pizza";

message1.ToRecipients.Add("[email protected]");

// Set the properties on the second message.

message2.Subject = "Company Soccer Team";

message2.Body = "Are you interested in joining?";

message2.ToRecipients.Add("[email protected]");

// Set the properties on the third message.

message3.Subject = "Code Blast";

message3.Body = "Are you interested in getting together to finish the


methods for the ContosoLive project?";

message3.ToRecipients.Add("[email protected]");

// Add the EmailMessage objects to a collection.

Collection<EmailMessage> messageItems = new Collection<EmailMessage>() {


message1, message2, message3 };

// Create the batch of email messages on the server.

// This method call results in an CreateItem call to EWS.

ServiceResponseCollection<ServiceResponse> response =
service.CreateItems(messageItems, WellKnownFolderName.Drafts,
MessageDisposition.SaveOnly, null);

// Instantiate a collection of item IDs to populate from the values that


are returned by the Exchange server.

Collection<ItemId> itemIds = new Collection<ItemId>();

// Collect the item IDs from the created email messages.

foreach (EmailMessage message in messageItems)

try

itemIds.Add(message.Id);

Console.WriteLine("Email message '{0}' created successfully.",


message.Subject);

catch (Exception ex)

// Print out the exception and the last eight characters of the
item ID.

Console.WriteLine("Exception while creating message {0}: {1}",


message.Id.ToString().Substring(144), ex.Message);

// Check for success of the CreateItems method call.

if (response.OverallResult == ServiceResult.Success)

Console.WriteLine("All locally created messages were


successfully saved to the Drafts folder.");

Console.WriteLine("\r\n");

// If the method did not return success, print the result message for
each email.

else

int counter = 1;

foreach (ServiceResponse resp in response)

// Print out the result and the last eight characters of the
item ID.

Console.WriteLine("Result (message {0}), id {1}: {2}", counter,


itemIds[counter - 1].ToString().Substring(144), resp.Result);

Console.WriteLine("Error Code: {0}", resp.ErrorCode);

Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);

Console.WriteLine("\r\n");

counter++;

return itemIds;

Note that the example only saves the messages in the Drafts folder; it does not send the
messages. For more about how to send the messages, see Send email messages in
batches by using the EWS Managed API.

Create email messages in batches by using EWS


You can create email messages in batches by using the CreateItem EWS operation, as
shown in the following code example. This is also the XML request that the EWS
Managed API sends when you use the EWS Managed API to create email messages in
batches.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SaveOnly">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="drafts" />

</m:SavedItemFolderId>

<m:Items>

<t:Message>

<t:Subject>Project priorities</t:Subject>

<t:Body BodyType="HTML">(1) Buy pizza, (2) Eat pizza</t:Body>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

<t:Message>

<t:Subject>Company Soccer Team</t:Subject>

<t:Body BodyType="HTML">Are you interested in joining?</t:Body>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

<t:Message>

<t:Subject>Code Blast</t:Subject>

<t:Body BodyType="HTML">Are you interested in getting together to


finish the methods for the ContosoLive project?</t:Body>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected]</t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError for each of the new messages, which
indicates that each email was created and saved successfully.

Note that the example only saves the messages in the Drafts folder; it does not send the
messages. For more about how to send the messages, see Send email messages in
batches by using EWS.
Send email messages in batches by using the
EWS Managed API
You use the same code to send email messages in batches that you use to create email
messages in batches, except that a few of the CreateItems method parameters
change. So, to send email messages by using the EWS Managed API, use the code you
use to create email messages in batches, and replace the call to the CreateItems
method with the call in the following example. In this example, the messages are created
in the Sent Items folder, and the message disposition is changed to
MessageDisposition.SendAndSaveCopy , so that the message is sent, and not just
saved locally.

C#

// Create and send the batch of email messages on the server.

// This method call results in an CreateItem call to EWS.

ServiceResponseCollection<ServiceResponse> response =
service.CreateItems(messageItems, WellKnownFolderName.SentItems,
MessageDisposition.SendAndSaveCopy, null);

Send email messages in batches by using EWS


You use the same code to send email messages in batches that you use to create email
messages in batches, except that a few of the attribute values change for the CreateItem
operation. So, to send email messages by using EWS, use the code you use to create
email message in batches, and change the MessageDisposition value to
"SendAndSaveCopy", and change the DistinguishedFolderId to "sentitems", as shown
in the following code example.

XML

<m:CreateItem MessageDisposition="SendAndSaveCopy">

<m:SavedItemFolderId>
<t:DistinguishedFolderId Id="sentitems" />
</m:SavedItemFolderId>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError for each of the new messages, which
indicates that each email was created and sent successfully.
Get email messages in batches by using the
EWS Managed API
You can get email messages in batches by using the EWS Managed API BindToItems
method, as shown in the following example.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

C#

public static Collection<EmailMessage> BatchGetEmailItems(ExchangeService


service, Collection<ItemId> itemIds)

// Create a property set that limits the properties returned by the Bind
method to only those that are required.

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly,


EmailMessageSchema.Subject, EmailMessageSchema.ToRecipients);

// Get the items from the server.

// This method call results in a GetItem call to EWS.

ServiceResponseCollection<GetItemResponse> response =
service.BindToItems(itemIds, propSet);

// Instantiate a collection of EmailMessage objects to populate from the


values that are returned by the Exchange server.

Collection<EmailMessage> messageItems = new Collection<EmailMessage>();

foreach (GetItemResponse getItemResponse in response)

try

Item item = getItemResponse.Item;

EmailMessage message = (EmailMessage)item;

messageItems.Add(message);

// Print out confirmation and the last eight characters of the


item ID.

Console.WriteLine("Found item {0}.",


message.Id.ToString().Substring(144));

catch (Exception ex)

Console.WriteLine("Exception while getting a message: {0}",


ex.Message);

// Check for success of the BindToItems method call.

if (response.OverallResult == ServiceResult.Success)

Console.WriteLine("All email messages retrieved successfully.");

Console.WriteLine("\r\n");

return messageItems;

Get email messages in batches by using EWS


You can get email messages in batches by using the GetItem EWS operation and the
code in the following example. This is also the XML request that the EWS Managed API
sends when you use the EWS Managed API to get email messages in batches.

The ItemId and ChangeKey attributes have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="message:ToRecipients" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="m4NxAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKB0" />

<t:ItemId Id="m4NyAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKB1" />

<t:ItemId Id="m4NzAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKB2" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The server responds to the GetItem request with a GetItemResponse message that
includes the first class properties for each of the requested messages.
Update email messages in batches by using the
EWS Managed API
You can get email messages in batches by using the EWS Managed API UpdateItems
method, as shown in the following example.

For a list of writable email message properties, see Email properties and elements in
EWS in Exchange.

For details about how to send a draft message after it's been updated, see Sending
email messages by using the EWS Managed API.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

C#

public static Collection<EmailMessage> BatchUpdateEmailItems(ExchangeService


service, Collection<EmailMessage> messageItems)

// Update the subject of each message locally.

foreach (EmailMessage message in messageItems)

// Update the Subject of the email.

message.Subject = "Updated subject at " + DateTime.Now;

// Print out confirmation with the last eight characters of the item
ID and the email subject.

Console.WriteLine("Updated local email message {0} with the subject


'{1}'.", message.Id.ToString().Substring(144), message.Subject);

// Send the item updates to the server.

// This method call results in an UpdateItem call to EWS.

ServiceResponseCollection<UpdateItemResponse> response =
service.UpdateItems(messageItems, WellKnownFolderName.Drafts,
ConflictResolutionMode.AutoResolve, MessageDisposition.SaveOnly, null);

// Check for success of the UpdateItems method call.

if (response.OverallResult == ServiceResult.Success)

Console.WriteLine("All email messages updated successfully.\r\n");

// If the method did not return success, print the result message for
each email.

else

Console.WriteLine("All emails were not successfully saved on the


server.\r\n");

int counter = 1;

foreach (ServiceResponse resp in response)

Console.WriteLine("Result for (message {0}): {1}", counter,


resp.Result);

Console.WriteLine("Error Code: {0}", resp.ErrorCode);

Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);

counter++;

return messageItems;

Update email messages in batches by using


EWS
You can update email messages in batches by using the GetItem EWS operation, as
shown in following code example. This is also the XML request that the EWS Managed
API sends when you use the EWS Managed API to update email messages in batches.

For a list of writable email message elements, see Email properties and elements in EWS
in Exchange.

For details about how to send a draft message after it's been updated, see Send a draft
email message by using EWS.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:UpdateItem MessageDisposition="SaveOnly"

ConflictResolution="AutoResolve">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="drafts" />

</m:SavedItemFolderId>

<m:ItemChanges>

<t:ItemChange>

<t:ItemId Id="m4OVAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKCy" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:Message>

<t:Subject>Updated subject at 1/17/2014 2:58:09


PM</t:Subject>

</t:Message>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

<t:ItemChange>

<t:ItemId Id="m4OWAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKCz" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:Message>

<t:Subject>Updated subject at 1/17/2014 2:58:09


PM</t:Subject>

</t:Message>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

<t:ItemChange>

<t:ItemId Id="m4OXAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKC0" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:Message>

<t:Subject>Updated subject at 1/17/2014 2:58:09


PM</t:Subject>

</t:Message>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

</m:ItemChanges>

</m:UpdateItem>

</soap:Body>

</soap:Envelope>

The server responds to the UpdateItem request with an UpdateItemResponse


message that includes a ResponseCode value of NoError, which indicates that each of
the updates was saved successfully on the server. Any conflicts are reported in the
ConflictResult element.

Delete email messages in batches by using the


EWS Managed API
You can delete messages in batches by using the EWS Managed API DeleteItems
method, as shown in the following example.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.
C#

public static void BatchDeleteEmailItems(ExchangeService service,


Collection<ItemId> itemIds)

// Delete the batch of email message objects.

// This method call results in an DeleteItem call to EWS.

ServiceResponseCollection<ServiceResponse> response =
service.DeleteItems(itemIds, DeleteMode.SoftDelete, null,
AffectedTaskOccurrence.AllOccurrences);

// Check for success of the DeleteItems method call.

// DeleteItems returns success even if it does not find all the item
IDs.

if (response.OverallResult == ServiceResult.Success)

Console.WriteLine("Email messages deleted successfully.\r\n");

// If the method did not return success, print a message.

else

Console.WriteLine("Not all email messages deleted


successfully.\r\n");

Delete email messages in batches by using EWS


You can delete email messages in batches by using the DeleteItem EWS operation, as
shown in the following code example. This is also the XML request that the EWS
Managed API sends when you use the EWS Managed API to delete email messages in
batches.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:DeleteItem DeleteType="SoftDelete"

AffectedTaskOccurrences="AllOccurrences">

<m:ItemIds>

<t:ItemId Id="m4OkAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKDE" />

<t:ItemId Id="m4OlAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKDF" />

<t:ItemId Id="m4OmAAA="

ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKDG" />

</m:ItemIds>

</m:DeleteItem>

</soap:Body>

</soap:Envelope>

The server responds to the DeleteItem request with a DeleteItemResponse message


that includes a ResponseCode value of NoError for each item that was removed. Note
that the operation also returns success if the item ID could not be found.

Verifying that a batch process completed


successfully
When one or more email messages in a batched request can't be processed as
requested, an error is returned for each email message that failed, and the rest of the
emails in the batch are processed as expected. Failures in batch processing can occur if
the item was deleted, and therefore can't be sent, retrieved, or updated, or if the item
moved to a different folder, and therefore has a new item ID, and cannot be modified
with the item ID sent. The information in this section shows how to get error details
about failures in batch processing of email message.

To verify the success of a batch process by using the EWS Managed API, you can check
that the OverallResult property of the ServiceResponseCollection is equal to
ServiceResult.Success . If so, all the emails were processed successfully. If the
OverallResult is not equal to ServiceResult.Success, one or more of the emails were not
processed successfully. Each of the objects returned in the ServiceResponseCollection
contains the following properties:

ErrorCode

ErrorDetails

ErrorMessage

ErrorProperties

Result

These properties contain information about why the email messages could not be
processed as requested. The examples in this article print out the Result, ErrorCode, and
ErrorMessage for each failed message. You can use these results to investigate the issue.

For EWS, to verify the success of a batched process, check the ResponseClass attribute
for each item being processed. The following is the basic structure of the
ResponseMessageType, the base type from which all response messages are derived.

XML

<ResponseMessage ResponseClass="Success | Warning | Error">

<MessageText/>

<ResponseCode/>

<DescriptiveLinkKey/>

<MessageXml/>

</ResponseMessage>

The ResponseClass attribute is set to Success if the email was processed successfully, or
Error if the email was not processed successfully. For email messages, you will not
encounter a Warning during batch processing. If the ResponseClass is Success, the
ResponseCode element that follows is also always set to NoError. If the
ResponseClass is Error, you need to check the values of the MessageText ,
ResponseCode, and MessageXml elements to determine what caused the problem.
DescriptiveLinkKey is currently unused.

See also
Email and EWS in Exchange

Send email messages by using EWS in Exchange

Respond to email messages by using EWS in Exchange

Move and copy email messages by using EWS in Exchange

Throttling implications for EWS batch requests


Folders and items in EWS in Exchange
Article • 01/15/2020 • 9 minutes to read

Learn about folders and mailbox items and how your EWS Managed API or EWS client represents
them.

Folders are the organizing element of an Exchange mailbox. Folders can contain mailbox items,
such as email messages, contacts, appointments, meetings, and tasks, or they can contain other
folders. Exchange includes different types of folders, but the folder types are similar to each other.
The main difference between them is the type of item they contain.

Items, however, have unique types. Each item type has a different set of properties or schema to
define it. In this article, we'll discuss the types of folders and items that are available and the
differences between them.

Folders
Folders all derive from the same base class or base type, the Folder class in the EWS Managed
API, or the Folder type in EWS. The following figure shows the EWS Managed API classes and
EWS types.

Figure 1. EWS Managed API folder classes and EWS folder types

The primary difference between each of the folder classes and folder types is that you can only
create a certain type of item in each type of folder. One other difference is in how the client
displays information in a folder. For example, Exchange allows you to create appointments in the
Calendar folder. You can move other types of items into the Calendar folder after you create
them, but Outlook won't display them. Outlook only displays calendar items such as
appointments and meetings in the Calendar folder, even if another type of item exists in the
folder.

Table 1. EWS Managed API folder classes and EWS folder types
EWS Managed EWS type FolderClass Contains Notes
API class value

Folder
Folder
IPF.Note Email This is the generic folder class or type
messages or for the following EWS Managed API
folders. WellKnownFolderName folders and
EWS DistinguishedFolderId folders:

Root (IPM subtree)


NonIpmSubtree
Inbox
Deleted Items
Drafts
Journal
Notes
Outbox
Sent Items
Message Folder
Junk Email
Voice Mail

CalendarFolder CalendarFolder IPF.Appointment Appointments When a user responds to a meeting


and meetings. request, the appointment is added to
the EWS Managed API
WellKnownFolderName.Calendar or
the EWS
DistinguishedFolderId.CalendarFolder
only. These are the only folders that
support automatic interaction with
meeting requests and responses.

This folder class or folder type supports


the use of calendar views to return
appointments and meetings based on a
start date and an end date by using the
EWS Managed API Folder.FindItem
method and the CalendarView class,
or the EWS FindItem operation and
the CalendarView element.

ContactsFolder ContactsFolder IPF.Contact Contacts and None.


distribution
lists.

SearchFolder
SearchFolder
IPF.Note Contents are The items that meet the search criteria
determined are not actually contained in the search
by a folder; instead, they are located
restriction or elsewhere in the mailbox.
filter. Search To ensure that Search folders are
folders do not available in Outlook, create them in the
have Finder folder.
subfolders.
EWS Managed EWS type FolderClass Contains Notes
API class value

TasksFolder
TasksFolder
IPF.Task Contains work None.
items to
complete.

Folder structure
Folders provide a mailbox structure. This includes the IPM Subtree, known as the Top of
Information Store in EWS, where most users interact with their mailbox, as well as system folders
that most users never see, which are in the Non-IPM Subtree or Root in EWS. The following figure
shows the folder structure for a user and indicates which folders are for the user's items and
which are system folders.

Figure 2. Item and system folders in a mailbox

Well-known folders
Of the folders in a mailbox, some are special folders. These equate to well-known folders in the
EWS Managed API, or distinguished folders in EWS. Some of these folders have restrictions on the
folder name, where they are located in the folder structure, and whether they can be deleted.
Other "generic" (non-special) folders do not have the same restrictions. It is important for you to
be familiar with the following well-known or distinguished folders because they are the root
system, user, and search folders, and are applicable to most implementations.

Table 2. Primary well-known and distinguished folders

Friendly EWS Managed API EWS DistinguishedFolderId values Description


name WellKnownFolderName values
Friendly EWS Managed API EWS DistinguishedFolderId values Description
name WellKnownFolderName values

Root (Non- WellKnownFolderName.Root DistinguishedFolderId.root Contains the


IPM root folder
Subtree) of a mailbox,
also known
as the Non-
IPM Subtree.
This folder
has no
parent, and
you cannot
move, copy,
rename, or
delete it.
Each
message
store
contains only
one root
folder.

Top of WellKnownFolderName.MsgFolderRoot DistinguishedFolderId.msgfolderroot Contains the


Information Inbox and
Store (IPM other user
Subtree) folders.

Finder WellKnownFolderName.SearchFolders DistinguishedFolderId.searchfolders. Contains


(Search search
folders) folders that
are visible in
Outlook.

For a complete list of the EWS Managed API WellKnownFolderName property values, see the
WellKnownFolderName enumeration. For a complete list of the EWS DistinguishedFolderId
values, see DistinguishedFolderId .

Folder properties
In the EWS Managed API, the folder properties are all derived from the base Folder class. And
in EWS, all folders use the folder elements that are available on the Folder type. Most of the
folder-related properties and elements are straightforward (parent folder ID, display name, and so
on), but a few require a little more explanation.

The following caveats apply to the EWS Managed API Folder.FolderClass property or the EWS
FolderClass element:

If set, the value of the property or element must agree with the derived class or type of the
folder. For example, the FolderClass property or element can't indicate that the folder is a
Contacts folder while the class or type of the folder indicates the folder is a Calendar folder.
You can either create folders of a specific type without setting the FolderClass property or
element, or you can create a folder with the generic folder type and specify the FolderClass
property or element. Both options create the same result.

After you set the FolderClass value by creating a specific type of folder or by setting the
FolderClass property or element itself, you cannot change it. For example, you cannot
change an IPF.Note folder to an IPF.Contact folder. You can, however, change it to an
IPF.Note.Contoso folder.

Any FolderClass value that does not use one of the predefined prefixes is treated as an
IPF.Note folder. For example, a FolderClass value of IAmAFolderClass is treated as an
IPF.Note folder.

The folder class value is extensible. This means that the default FolderClass values listed in Table 1
are treated as prefixes and you can add custom values. For example, you can create a folder with
a FolderClass value of IPF.Contact.Contoso, and it is treated as a Contacts folder.

You can determine what permissions the client has on the folders, such as delete, read, and
modify, by using the EWS Managed API Folder.EffectiveRights property or the EWS
EffectiveRights element.

Public folders
Public folders are designed for shared access and provide an easy and effective way to collect,
organize, and share information with other people in your workgroup or organization. You can
also use public folders to archive distribution group content. For in-depth information about
public folders, see Public folder access with EWS in Exchange.

Hidden folders
All the folders that Exchange creates at the root of the mailbox are hidden, and you can use the
EWS Managed API or EWS to hide additional folders under the Top of Information Store. For more
information about hidden folders, see Work with hidden folders by using EWS in Exchange.

Search folders
Search folders are just like regular folders, except that they have a property or element that
defines the search filter. You can create search folders in any folder in an Exchange mailbox, and
you create them in the same way that you create any other folder. However, for a search folder to
appear in Outlook, Outlook Web App, or Outlook Live, SearchFolder objects that you create by
using the EWS Managed API must be located in the WellKnownFolderName.SearchFolders
folder, and SearchFolder types that you create by using EWS must be located in the
DistinguishedFolderId.SearchFolders folder. If the search folder is created in a different location,
it is still available and you can view it in custom client applications.
Items
EWS in Exchange uses Items to represent individual email messages, appointments, meetings,
contacts, distribution lists, tasks, posts, and other items, in a mailbox. Items are either strongly
typed, which means that they have a specific associated class or schema, or not strongly typed,
also known as generic items. Generic items are Item objects in the EWS Managed API and
Item types in EWS. Common items like email messages, contacts, distribution lists, posts, and
tasks are strongly typed, and you can set specific schematized properties or elements on them.

Table 3. Strongly typed items

EWS Managed API item type EWS item element

Appointment
CalendarItem

Contact
Contact

ContactGroup
DistributionList

EmailMessage
Message

PostItem
PostItem

Task
Task

EWS Managed API strongly typed items derive from the base Item class. However, you usually
work with one of the derived types listed in Table 3, and not with the Item class directly. When
you work with the ItemCollection class, however, you might work directly with instances of the
Item class. In that case, you should implement logic that determines the type of item in the store
that the instance of the Item class represents. To work with that item, you should bind to the item
by using an instance of the class that represents the item.

Items in folders
Some folders have restrictions about the types of items that they can contain. These are
restrictions that the Exchange mailbox database applies to folders, not client view limitations.

Table 4. Item restrictions for folders

EWS Managed EWS Folder type Restriction


API Folder class

Base Folder Folder


You can only create new EWS Managed API EmailMessage objects
class
and PostItem objects, or EWS Message types or PostItem types,
in the generic folders. You can move other item types into generic
folders, but the client might not display them.
EWS Managed EWS Folder type Restriction
API Folder class

CalendarFolder CalendarFolder You can only create new EWS Managed API Appointment objects
and EWS CalendarItem types in the Calendar folder. You can
move other item types into the Calendar folder, but the client might
not display them.

ContactsFolder ContactsFolder You can only create new EWS Managed API Contact and
ContactGroup objects, or EWS Contact types or
DistributionList types in the Contacts folder. You can move other
item types into the Contacts folder, but the client might not display
them

SearchFolder
SearchFolder
No restrictions. Items are not actually located in the Search folder;
they are located elsewhere in the mailbox.

TasksFolder
TasksFolder
You can only create new EWS Managed API Task objects or EWS
Task types in the Tasks folder. You can move other item types into
the Tasks folder, but the client might not display them

Upgrading from earlier product versions


Folders have for the most part remained unchanged in earlier and current product versions. Note,
however, that earlier versions of Exchange use managed folders to perform messaging records
management (MRM). Exchange Online, Exchange Online as part of Office 365, and versions of
Exchange starting with Exchange 2013 use retention policies for MRM. You can upgrade managed
folders to use retention policies .

Items have not changed in earlier and current product versions.

In this section
Work with folders by using EWS in Exchange

Work with hidden folders by using EWS in Exchange

Work with Exchange mailbox items by using EWS in Exchange

Delete items by using EWS in Exchange

Export and import items by using EWS in Exchange

See also
Develop web service clients for Exchange
Start using web services in Exchange
EWS client design overview for Exchange
Work with folders by using EWS in
Exchange
Article • 02/11/2022 • 12 minutes to read

Learn how to create, get, update, and delete folders by using the EWS Managed API or
EWS in Exchange.

EWS in Exchange uses folders to structure and organize mailboxes. You can create new,
get, update, and delete folders by using the EWS Managed API or EWS. Each of the
methods or operations listed in the following table is performed on a Folder object, a
Folder type, or one of the derived folder classes or types.

Table 1. Methods and operations for creating, getting, updating and deleting folders

In order to… EWS Managed API method EWS operation

Create a folder Folder.Save CreateFolder

Create a folder hierarchy Not available CreateFolderPath

Get a folder Folder.Bind GetFolder

Get a folder hierarchy Folder.FindFolders FindFolder

Update a folder Folder.Update UpdateFolder

Delete a folder Folder.Delete DeleteFolder

Create a folder by using the EWS Managed API


The following code example shows how to use the Folder class to create a new
generic folder with a DisplayName of "Custom Folder" and a FolderClass property
value of IPF.Note. The Folder.Save method saves the folder as a child folder of the
Inbox folder.

These examples assume that service is a valid ExchangeService object and that the
user has been authenticated to an Exchange server.

C#

// Create a custom folder.

Folder folder = new Folder(service);

folder.DisplayName = "Custom Folder";

folder.FolderClass = "IPF.Note";

// Save the folder as a child folder of the Inbox.

folder.Save(WellKnownFolderName.Inbox);

To create a different type of folder, such as a CalendarFolder , ContactsFolder ,


SearchFolder , or TasksFolder , create a new instance of the specific class (instead of
the generic Folder class) and do not set the FolderClass property. For example, the
following code example shows how to create a new TasksFolder .

C#

// Create a custom Tasks folder.

TasksFolder folder = new TasksFolder(service);

folder.DisplayName = "Custom Tasks";

// Save the folder as a child folder in the Inbox folder.

// This method call results in a CreateFolder call to EWS.

folder.Save(WellKnownFolderName.Inbox);

If you try to create an instance of a specific class and also set the FolderClass property,
the ErrorNoFolderClassOverride error is thrown.

Note that you cannot batch the creation of multiple folders in a single method call by
using the EWS Managed API.

Create a folder by using EWS


You can create a single folder or multiple of folders by using EWS.

To create a single folder, send a CreateFolder operation request message. The


CreateFolder operation request indicates that the parent folder is the Inbox, the
DisplayName is "Custom Folder", and the FolderClass element value is IPF.Note.

This is also the XML request that the EWS Managed API sends when you create a new
folder and call the Folder.Save method.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:CreateFolder>

<m:ParentFolderId>

<t:DistinguishedFolderId Id="inbox" />

</m:ParentFolderId>

<m:Folders>

<t:Folder>

<t:FolderClass>IPF.Note</t:FolderClass>

<t:DisplayName>Custom Folder</t:DisplayName>

</t:Folder>

</m:Folders>

</m:CreateFolder>

</soap:Body>

</soap:Envelope>

The server responds to the CreateFolder request with a CreateFolderResponse


message that includes a ResponseCode value of NoError, which indicates that the
folder was created successfully, and the FolderId of the newly created message.

To create multiple folders, include multiple Folder elements in the CreateFolder


operation request message. All the new folders must be in the same parent folder.

Create a folder hierarchy by using EWS


You can create a folder hierarchy in a single call by using the EWS CreateFolderPath
operation. The same functionality is not available in the EWS Managed API. Instead, if
you are using the EWS Managed API, you can create folders one by one, as shown in
Create a folder by using EWS.

7 Note

The EWS Managed API does not implement this functionality.

Get a folder by using the EWS Managed API


The following code example shows how to use the Folder.Bind method to get the
Inbox folder. As a best practice, limit the properties returned to only those required for
your application. This example limits the return properties to only include the Id
property by creating a PropertySet object and applying the IdOnly value to the
BasePropertySet property.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.
C#

// As a best practice, limit the properties returned to only those that are
required.

// In this scenario, you only need the FolderId.

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly);

// Bind to an existing folder and get only the properties specified in the
PropertySet.

// This method call results in a GetFolder call to EWS.

Folder rootfolder = Folder.Bind(service, WellKnownFolderName.Inbox,


propSet);

If you need to return additional properties, add properties from the FolderSchema
class to the PropertySet, or use one of the overloaded Bind methods that returns all
first class properties.

Note that you cannot get multiple folders at one time by using the EWS Managed API.
You have to call the Bind method on each folder separately.

Get a folder by using EWS


You can get a single folder or multiple folders by using EWS.

To get a single folder, send a GetFolder operation request message to the server. In
the following example, the BaseShape is set to IdOnly, so only the FolderId of the
specified folder is returned. The FolderIds element indicates that the folder to retrieve
is the Inbox folder.

This is also the XML request that the EWS Managed API sends when you bind to a folder
by using the Folder.Bind method.

To get multiple folders, include multiple FolderIds elements in the GetFolder


operation request message.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:GetFolder>

<m:FolderShape>

<t:BaseShape>IdOnly</t:BaseShape>

</m:FolderShape>

<m:FolderIds>

<t:DistinguishedFolderId Id="inbox" />

</m:FolderIds>

</m:GetFolder>

</soap:Body>

</soap:Envelope>

The following XML example shows the GetFolderResponse message that is sent from
the server to the client in response to the GetFolder operation request. It only contains
the FolderId value of the Inbox folder. The values of some attributes and elements
have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="800"

MinorBuildNumber="16"

Version="V2_6"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"/>

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetFolderResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetFolderResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Folders>

<t:Folder>

<t:FolderId Id="AAAENAAA="
ChangeKey="AQAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAEkbCr"/>

</t:Folder>

</m:Folders>

</m:GetFolderResponseMessage>

</m:ResponseMessages>

</m:GetFolderResponse>

</s:Body>

</s:Envelope>

Get a folder hierarchy by using the EWS


Managed API
The following code example shows how to retrieve the subfolders for a specified root
folder. This example retrieves the subfolders of the MsgFolderRoot folder, which is the
root of the IPM Subtree (where your mailbox folders and items are stored).

In this example, a FolderView class object is created to limit the results of the
Folder.FindFolders method response. This scenario limits the properties to return to
the following: Id , DisplayName , and the extended property that indicates whether
the folder is a hidden folder. Set the FolderView.Traversal value to Deep to perform a
recursive search so that the server retrieves the subfolders, and set the root folder to
MsgFolderRoot, so that the server returns all the user's folders (and the server does not
return system folders in the Non-IPM Subtree).

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server.

C#

// Create a new folder view, and pass in the maximum number of folders to
return.

FolderView view = new FolderView(folderViewSize);

// Create an extended property definition for the PR_ATTR_HIDDEN property,

// so that your results will indicate whether the folder is a hidden folder.

ExtendedPropertyDefinition isHiddenProp = new


ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);

// As a best practice, limit the properties returned to only those required.

// In this case, return the folder ID, DisplayName, and the value of the
isHiddenProp

// extended property.

view.PropertySet = new PropertySet(BasePropertySet.IdOnly,


FolderSchema.DisplayName, isHiddenProp);

// Indicate a Traversal value of Deep, so that all subfolders are retrieved.

view.Traversal = FolderTraversal.Deep;

// Call FindFolders to retrieve the folder hierarchy, starting with the


MsgFolderRoot folder.

// This method call results in a FindFolder call to EWS.

FindFoldersResults findFolderResults =
service.FindFolders(WellKnownFolderName.MsgFolderRoot, view);

Get a folder hierarchy by using EWS


The following XML examples show how to use the FindFolder operation to retrieve a
folder hierarchy by using EWS. This example retrieves the msgfolderroot folder, which is
the root of the IPM Subtree, and all its subfolders. The Traversal attribute is set to Deep
so that the server performs a recursive search of the folder hierarchy and only returns
folders and subfolders under the specified root in the response. In this example, the
BaseShape element is set to IdOnly so that the server only returns the FolderId
element. To make the output easier to understand, include the DisplayName element in
your results by including it in the AdditionalProperties element in the request, along
with the ExtendedFieldURI value for the PR_ATTR_HIDDEN property, so that you know
whether the folders are hidden folders.

This is also the XML request that the EWS Managed API sends when you call the
FindFolders method.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:FindFolder Traversal="Deep">

<m:FolderShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="folder:DisplayName" />

<t:ExtendedFieldURI PropertyTag="4340"

PropertyType="Boolean" />

</t:AdditionalProperties>

</m:FolderShape>

<m:IndexedPageFolderView MaxEntriesReturned="100"

Offset="0"

BasePoint="Beginning" />

<m:ParentFolderIds>

<t:DistinguishedFolderId Id="msgfolderroot" />

</m:ParentFolderIds>

</m:FindFolder>

</soap:Body>

</soap:Envelope>

The following XML example shows the FindFolderResponse message that is sent from
the server to the client in response to the FindFolder operation request. It contains only
the FolderId , the DisplayName , and the value of the PR_ATTR_HIDDEN extended
property for all the subfolders under the msgrootfolder folder. If the Value element is
set to true, the folder should be hidden in the client view.
This is also the XML response that the EWS Managed API sends when you get multiple
folders by using the FindFolder method. The values of some attributes and elements
have been shortened for readability, and some folders have not been included for
brevity.

XML

<?xml version="1.0" encoding="utf-8"?><s:Envelope


xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="815"

MinorBuildNumber="6"

Version="V2_7"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"/>

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:FindFolderResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:FindFolderResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootFolder IndexedPagingOffset="16"

TotalItemsInView="16"

IncludesLastItemInRange="true">

<t:Folders>
<t:CalendarFolder>

<t:FolderId Id="AAAEOAAA="

ChangeKey="AgAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAAAAA3"/>

<t:DisplayName>Calendar</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean"/>

<t:Value>false</t:Value>

</t:ExtendedProperty>

</t:CalendarFolder>

<t:ContactsFolder>

<t:FolderId Id="AAAEPAAA="

ChangeKey="AwAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAAAAA4"/>

<t:DisplayName>Contacts</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean"/>

<t:Value>false</t:Value>

</t:ExtendedProperty>

</t:ContactsFolder>

<t:ContactsFolder>

<t:FolderId Id="AAAUKAAA="

ChangeKey="AwAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAAAAS5"/>

<t:DisplayName>Recipient Cache</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean"/>

<t:Value>true</t:Value>

</t:ExtendedProperty>

</t:ContactsFolder>

<t:Folder>

<t:FolderId Id="AAAUJAAA="

ChangeKey="AQAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAAAASx"/>

<t:DisplayName>Conversation Action Settings</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean"/>

<t:Value>true</t:Value>

</t:ExtendedProperty>

</t:Folder>

</t:Folders>

</m:RootFolder>

</m:FindFolderResponseMessage>

</m:ResponseMessages>

</m:FindFolderResponse>

</s:Body>

</s:Envelope>

Update a folder by using the EWS Managed


API
The following code example shows how to update the display name of a folder by using
the EWS Managed API.

First, create a PropertySet to limit the number of properties that the server returns in
the Folder.Bind response. We recommend that you use the IdOnly BasePropertySet
to reduce calls to the Exchange database. Next, use the Bind method to bind to the
folder to update. Then, update the DisplayName property, and use the
Folder.Update method to save the changes.
In this example, we assume that service is a valid ExchangeService object and that the
user has been authenticated to an Exchange server. The local variable folderId is the Id
of the folder to update.

C#

// As a best practice, only include the ID value in the PropertySet.

PropertySet propertySet = new PropertySet(BasePropertySet.IdOnly);


// Bind to an existing folder and get the FolderId.

// This method call results in a GetFolder call to EWS.

Folder folder = Folder.Bind(service, folderId, propertySet);

// Update the display name of the folder.

folder.DisplayName = "Updated folder name";

// Save the updates.

// This method call results in an UpdateFolder call to EWS.

folder.Update();

Update a folder by using EWS


The following XML examples show how to update the display name of a folder by using
EWS.

First, send a GetFolder operation request message to get the folder to update, as
shown in Get a folder hierarchy by using EWS.

Next, send an UpdateFolder operation request message to the server to update a


folder. The UpdateFolder operation request updates the DisplayName to "Updated
Custom Folder".

This is also the XML request that the EWS Managed API sends when you update a folder
by using the Folder.Update method. The values of some attributes and elements have
been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:UpdateFolder>

<m:FolderChanges>
<t:FolderChange>

<t:FolderId Id="OrV9ZAAA="
ChangeKey="AQAAABYAAABVzRdyy/cHS4XTC9itCRdUAAAOrXWb" />

<t:Updates>

<t:SetFolderField>

<t:FieldURI FieldURI="folder:DisplayName" />

<t:Folder>

<t:DisplayName>Updated Custom Folder</t:DisplayName>

</t:Folder>

</t:SetFolderField>

</t:Updates>

</t:FolderChange>

</m:FolderChanges>

</m:UpdateFolder>

</soap:Body>

</soap:Envelope>

The server responds to the UpdateFolder request with a UpdateFolderResponse


message that includes the a ResponseCode value of NoError, and the FolderId of
the folder that was updated with an updated ChangeKey attribute value.

Delete a folder by using the EWS Managed API


This article provides a basic example that shows you how to delete a folder by using the
EWS Managed API. For more details about deleting folders, see Deleting items by using
EWS in Exchange.

To delete a folder by using the EWS Managed API, first, use the Folder.Bind method to
bind to the service object to the folder to delete. Next, use the Folder.Delete method
to delete the folder by using the HardDelete deletion mode.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server. The local variable folderId is the Id of
the folder to delete.

C#

// Bind to an existing folder and get all its properties.

// This method call results in a GetFolder call to EWS.

Folder folder = Folder.Bind(service, folderId);

// HardDelete the folder.

// This method call results in a DeleteFolder call to EWS.

folder.Delete(DeleteMode.HardDelete);

Delete a folder by using EWS


This article provides a basic XML example that shows you how to delete a folder by
using EWS. For more details about deleting folders, see Deleting items by using EWS in
Exchange.

To delete a folder by using EWS, first, send a GetFolder operation request message to
get the folder to update as shown in Get a folder by using EWS.

Next, send a DeleteFolder operation request message to the server to delete the
folder. The DeleteFolder operation request indicates that the DeleteType is HardDelete
and it includes the FolderId of the folder to delete.

This is also the XML request that the EWS Managed API sends when you delete a folder
by using the Folder.Delete method. The values of some attributes and elements have
been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:DeleteFolder DeleteType="HardDelete">

<m:FolderIds>

<t:FolderId Id="OrV9ZAAA="
ChangeKey="AQAAABYAAABVzRdyy/cHS4XTC9itCRdUAAAOrXWf" />

</m:FolderIds>

</m:DeleteFolder>

</soap:Body>

</soap:Envelope>

The server responds to the DeleteFolder request with a DeleteFolderResponse


message that includes the a ResponseCode value of NoError, which indicates that the
folder deletion was successful.

Next steps
After you have retrieved the folders on the server, or made changes to folders, you
might want to synchronize your folder hierarchy or subscribe to notifications about
folder changes on the server.
See also
Folders and items in EWS in Exchange
Work with Exchange mailbox items by using EWS in Exchange
Deleting items by using EWS in Exchange
Develop web service clients for Exchange
Work with hidden folders by using EWS
in Exchange
Article • 03/15/2022 • 7 minutes to read

Learn how to make a folder hidden and find hidden folders by using the EWS Managed
API or EWS in Exchange.

With one exception, folders in the root of an Exchange mailbox (the non-IPM subtree)
are hidden from the user. Conversely, all folders in the MsgFolderRoot (the IPM subtree)
are visible to the user. So how do you hide a folder under the MsgFolderRoot? It's not
that tricky — it comes down to just one property, the PidTagAttributeHidden
(0x10F4000B) extended property. When this property is set to true, Outlook or another
client that uses the property to determine folder visibility will hide the folder from the
user's view. Because this is an extended property, it's more complex to use than your
average folder property, so this article will walk you through the main scenarios.

Table 1. EWS Managed API methods and EWS operations for working with hidden
folders

Task EWS Managed API method EWS operation

Hide a folder Folder.Bind followed by GetFolder followed by


Folder.Update UpdateFolder

Find hidden FindFolders


FindFolder

folders

Are you wondering what the one exception is — that is, what folder in the root IS visible
to users? It's the Finder folder (also known as the SearchFoldersWellKnownFolder
enumeration value, or the searchfoldersDistinguishedFolderId element value), which
contains users' search folders. Search folders created in the Finder folder are visible to
Outlook users. If you need to create a search folder that is not visible to users, move it
under the root folder to hide it. Unlike for other folders, setting the
PidTagAttributeHidden property to true will not hide a search folder in the Finder
folder.

Hide a folder by using the EWS Managed API


You can make an existing folder a hidden folder by changing the
PidTagAttributeHidden extended property to true. First, create an extended property
definition for the property. Next, use the Bind method to get to the folder, then
update the value of the PidTagAttributeHidden property to true, and use the Update
method to save the changes.

This example assumes that service is a valid ExchangeService object for the mailbox
owner, that the user has been authenticated to an Exchange server, and that folderId is
a valid Folder.Id that identifies the folder to hide.

C#

private static void MakeHidden(FolderId folderId, ExchangeService service)

// Create an extended property definition for the PidTagAttributeHidden


property.

ExtendedPropertyDefinition isHiddenProp = new


ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);

PropertySet propSet = new PropertySet(isHiddenProp);

// Bind to a folder and retrieve the PidTagAttributeHidden property.

Folder folder = Folder.Bind(service, folderId, propSet);

// Set the PidTagAttributeHidden property to true.

folder.SetExtendedProperty(isHiddenProp, true);

// Save the changes.

folder.Update();

Hide a folder by using EWS


You can use EWS to make an existing folder a hidden folder by changing the
PidTagAttributeHidden extended property to true. First, use the GetFolder
operation to get to the folder, then retrieve the PidTagAttributeHidden property by
including the ExtendedFieldURI element, and setting the PropertyTag value to 4340
and the PropertyType value to Boolean.

This is also the XML request that the EWS Managed API sends when you use the Bind
method to get a folder before making it a hidden folder.

The FolderId value is shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:GetFolder>

<m:FolderShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:ExtendedFieldURI PropertyTag="4340"

PropertyType="Boolean" />

</t:AdditionalProperties>

</m:FolderShape>

<m:FolderIds>

<t:FolderId Id="IQywAAAA==" />

</m:FolderIds>

</m:GetFolder>

</soap:Body>

</soap:Envelope>

The server responds to the GetFolder request with a GetFolderResponse message that
includes a ResponseCode element value of NoError, which indicates that the folder
was retrieved successfully. The response also includes a Value for the
ExtendedProperty . In this example, the Value is set to false, which means that the
folder is currently not hidden.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="898"

MinorBuildNumber="23"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetFolderResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetFolderResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Folders>

<t:Folder>

<t:FolderId Id="IQywAAAA=="

ChangeKey="AQAAABYAAAD32nSTjepyT63rYH17n9THAAAAABED" />

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"
PropertyType="Boolean" />

<t:Value>false</t:Value>

</t:ExtendedProperty>

</t:Folder>

</m:Folders>

</m:GetFolderResponseMessage>

</m:ResponseMessages>

</m:GetFolderResponse>

</s:Body>

</s:Envelope>

To change the value of the ExtendedProperty to true, use the UpdateFolder


operation. Include the ExtendedProperty, ExtendedFieldURI, and Value elements for
the PidTagAttributeHidden extended property, and set the Value element to true to
hide the folder.

This is also the XML request that the EWS Managed API sends when you use the Update
method to update a folder to make it a hidden folder.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:UpdateFolder>

<m:FolderChanges>
<t:FolderChange>

<t:FolderId Id="IQywAAAA=="

ChangeKey="AQAAABYAAAD32nSTjepyT63rYH17n9THAAAAABED"
/>

<t:Updates>

<t:SetFolderField>

<t:ExtendedFieldURI PropertyTag="4340"

PropertyType="Boolean" />

<t:Folder>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="4340"

PropertyType="Boolean" />

<t:Value>true</t:Value>

</t:ExtendedProperty>

</t:Folder>

</t:SetFolderField>

</t:Updates>

</t:FolderChange>

</m:FolderChanges>

</m:UpdateFolder>

</soap:Body>

</soap:Envelope>

The server responds to the UpdateFolder request with an UpdateFolderResponse


message that includes a ResponseCode element value of NoError, which indicates
that the folder was updated successfully, and is now hidden.

Find all hidden folders by using the EWS


Managed API
You can find all hidden folders under a parent folder by creating an extended property
definition for the PidTagAttributeHidden extended property, and then using the
FindFolders method to find folders with a PidTagAttributeHidden value that is set to
true. This example uses the MsgFolderRoot, also known as the Top of Information Store,
or IPM Subtree, as the parent folder to search under.

This example assumes that service is a valid ExchangeService object for the mailbox
owner, and that the user has been authenticated to an Exchange server.

C#

private static void FindHiddenFolders(ExchangeService service)

// Create an extended property definition for the PidTagAttributeHidden


property.

ExtendedPropertyDefinition isHiddenProp = new


ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);

// Create a folder view to retrieve up to 100 folders and

// retrieve only the PidTagAttributeHidden and the display name.

FolderView folderView = new FolderView(100);

folderView.PropertySet = new PropertySet(isHiddenProp,


FolderSchema.DisplayName);

// Indicate a Traversal value of Deep, so that all subfolders are


retrieved.

folderView.Traversal = FolderTraversal.Deep;

// Find all hidden folders under the MsgFolderRoot.

// This call results in a FindFolder call to EWS.

FindFoldersResults findFolder =
service.FindFolders(WellKnownFolderName.MsgFolderRoot,

new SearchFilter.IsEqualTo(isHiddenProp, true), folderView);

// Display the folder ID and display name of each hidden folder.

foreach (Folder folder in findFolder)

Console.WriteLine("FolderId: {0}", folder.Id);

Console.WriteLine("DisplayName: {0}", folder.DisplayName);


Console.WriteLine("\r\n");

Find all hidden folders by using EWS


You can use EWS to find all hidden folders under an existing folder by calling the
FindFolder operation and searching for folders whose PidTagAttributeHidden
extended property is set to true. To do this, include an IsEqualTo Restriction that
searches for the ExtendedFieldURI element for the PidTagAttributeHidden property (
PropertyTag value to 4243 and the PropertyType value to Boolean), as shown in the
following request. This example uses the MsgFolderRoot, also known as the Top of
Information Store, or IPM Subtree, as the parent folder to search under.

This is also the XML request that the EWS Managed API sends when you use the
FindFolders method to find all hidden folders.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Central Standard Time" />

</t:TimeZoneContext>

</soap:Header>

<soap:Body>

<m:FindFolder Traversal="Deep">

<m:FolderShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:ExtendedFieldURI PropertyTag="4340"

PropertyType="Boolean" />

<t:FieldURI FieldURI="folder:DisplayName" />

</t:AdditionalProperties>

</m:FolderShape>

<m:IndexedPageFolderView MaxEntriesReturned="100"

Offset="0"

BasePoint="Beginning" />

<m:Restriction>

<t:IsEqualTo>

<t:ExtendedFieldURI PropertyTag="4340"

PropertyType="Boolean" />

<t:FieldURIOrConstant>

<t:Constant Value="true" />

</t:FieldURIOrConstant>

</t:IsEqualTo>

</m:Restriction>

<m:ParentFolderIds>

<t:DistinguishedFolderId Id="msgfolderroot" />

</m:ParentFolderIds>

</m:FindFolder>

</soap:Body>

</soap:Envelope>

The server responds to the FindFolder request with a FindFolderResponse message


that includes a ResponseCode element value of NoError, which indicates that the
folder search was successful, as well as all the hidden folders under the root message
folder.

The FolderId values are shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="898"

MinorBuildNumber="23"

Version="V2_10"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" />

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:FindFolderResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:FindFolderResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:RootFolder IndexedPagingOffset="6"

TotalItemsInView="6"

IncludesLastItemInRange="true">

<t:Folders>
<t:ContactsFolder>

<t:FolderId Id="IBHgAAAA=="

ChangeKey="AwAAABYAAAD32nSTjepyT63rYH17n9THAAAAAACz" />

<t:DisplayName>{06967759-274D-40B2-A3EB-D7F9E73727D7}
</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean" />

<t:Value>true</t:Value>

</t:ExtendedProperty>

</t:ContactsFolder>

<t:ContactsFolder>

<t:FolderId Id="IBHwAAAA=="

ChangeKey="AwAAABYAAAD32nSTjepyT63rYH17n9THAAAAAAC7" />

<t:DisplayName>{A9E2BC46-B3A0-4243-B315-60D991004455}
</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean" />

<t:Value>true</t:Value>

</t:ExtendedProperty>

</t:ContactsFolder>

<t:ContactsFolder>

<t:FolderId Id="IBIQAAAA=="

ChangeKey="AwAAABYAAAD32nSTjepyT63rYH17n9THAAAAAADO" />

<t:DisplayName>GAL Contacts</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean" />

<t:Value>true</t:Value>

</t:ExtendedProperty>

</t:ContactsFolder>

<t:ContactsFolder>

<t:FolderId Id="IBHQAAAA=="

ChangeKey="AwAAABYAAAD32nSTjepyT63rYH17n9THAAAAAACa" />

<t:DisplayName>Recipient Cache</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean" />

<t:Value>true</t:Value>

</t:ExtendedProperty>

</t:ContactsFolder>

<t:Folder>

<t:FolderId Id="HAAAAA=="

ChangeKey="AQAAABYAAAD32nSTjepyT63rYH17n9THAAAAAACS" />

<t:DisplayName>Conversation Action Settings</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean" />

<t:Value>true</t:Value>

</t:ExtendedProperty>

</t:Folder>

<t:Folder>

<t:FolderId Id="IQywAAAA=="

ChangeKey="AQAAABYAAAD32nSTjepyT63rYH17n9THAAAeZIBf" />

<t:DisplayName>TestFolder</t:DisplayName>

<t:ExtendedProperty>

<t:ExtendedFieldURI PropertyTag="0x10f4"

PropertyType="Boolean" />

<t:Value>true</t:Value>

</t:ExtendedProperty>

</t:Folder>

</t:Folders>

</m:RootFolder>

</m:FindFolderResponseMessage>

</m:ResponseMessages>

</m:FindFolderResponse>

</s:Body>

</s:Envelope>

After you have hidden or unhidden folders, you might want to get the folder hierarchy
or synchronize the folder hierarchy. The examples that show you how to get a folder
hierarchy by using the EWS Managed API or get a folder hierarchy by using EWS also
indicate which folders in the hierarchy are hidden.

See also
Folders and items in EWS in Exchange

Work with folders by using EWS in Exchange

Work with search folders by using EWS in Exchange


Work with Exchange mailbox items by
using EWS in Exchange
Article • 01/15/2020 • 14 minutes to read

Learn how to create, get, update, and delete items by using the EWS Managed API or
EWS in Exchange.

You can use the EWS Managed API or EWS to work with items in a mailbox. You can use
generic items — EWS Managed API Item objects or EWS Item types — to perform
some operations (getting an item or deleting an item by using the item's identifier);
however, most of the time you'll have to use a strongly typed item to perform a get or
update operation because you'll need access to the properties that are specific to the
strongly typed item.

For example, you can't use a generic item to retrieve an item that contains a start and
end date - you need an EWS Managed API Appointment object or an EWS
CalendarItem type to do that. And if you're using the EWS Managed API, you always
have to create strongly typed items, because the generic Item class does not have a
constructor. If you're working with an item that is not strongly typed, you can always use
the base Item class to work with the item.

Table 1. EWS Managed API methods and EWS operations for working with items

In order EWS Managed API method EWS


to… operation

Create a None. You can only create specific item types by using the EWS CreateItem

generic item Managed API; you cannot create generic items.

Get an item Item.Bind


GetItem

Update an Item.Update
UpdateItem
item

Delete an Item.Delete
DeleteItem

item

In this article, you'll learn when you can use the generic base class and when you need
to use a strongly typed item to complete your task. The code examples will show you
how to use the base class, and what to do when you can't use the base class or it
doesn't fit your needs.
Create an item by using the EWS Managed API
The EWS Managed API does not have a publicly available constructor for the Item
class, so you must use the constructor for the specific item type you want to create in
order to create an item. For example, use the EmailMessage class constructor to
create a new email message, and the Contact class constructor to create a new
contact. Likewise, the server never returns generic Item objects in responses; all generic
items are returned as EmailMessage objects.

When you know the type of item to create, you can complete the task in just a few
steps. The steps are similar for all item types:

1. Initialize a new instance of one of the Item classes with the ExchangeService
object as a parameter.

2. Set properties on the item. The schemas are different for each item type, so
different properties are available for different items.

3. Save the item, or save and send the item.

For example, you can create an EmailMessage object, set the Subject , Body , and
ToRecipients properties, and then send it by using the
EmailMessage.SendAndSaveCopy method.

C#

// Create an email message and provide it with connection

// configuration information by using an ExchangeService object named


service.

EmailMessage message = new EmailMessage(service);

// Set properties on the email message.

message.Subject = "Company Soccer Team";

message.Body = "Are you interested in joining?";

message.ToRecipients.Add("[email protected]");

// Send the email message and save a copy.

// This method call results in a CreateItem call to EWS.

message.SendAndSaveCopy();

To learn how to create a meeting or appointment item by using the EWS Managed API,
see Create appointments and meetings by using EWS in Exchange 2013.

Create an item by using EWS


You can create a generic item or a strongly typed item by using EWS. The steps are
similar for all item types:
1. Use the CreateItem operation to create an item in the Exchange store.

2. Use the Items element to contain one or more items to create.

3. Set properties on the item.

For example, you can create an email message and send it by using the code in the
following example. This is also the XML request that the EWS Managed API sends when
you call the SendAndSaveCopy method.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:CreateItem MessageDisposition="SendAndSaveCopy">

<m:SavedItemFolderId>

<t:DistinguishedFolderId Id="sentitems" />

</m:SavedItemFolderId>

<m:Items>

<t:Message>

<t:Subject>Company Soccer Team</t:Subject>

<t:Body BodyType="HTML">Are you interested in joining?</t:Body>

<t:ToRecipients>

<t:Mailbox>
<t:EmailAddress>[email protected] </t:EmailAddress>

</t:Mailbox>

</t:ToRecipients>

</t:Message>

</m:Items>

</m:CreateItem>

</soap:Body>

</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message


that includes a ResponseCode value of NoError, which indicates that the email was
created successfully, and the ItemId of the newly created message.

To learn how to create a meeting or appointment item by using EWS, see Create
appointments and meetings by using EWS in Exchange 2013.
Get an item by using the EWS Managed API
To use the EWS Managed API to get an item if you know the Item.Id of the item to
retrieve, you simply call one of the Bind methods on the item, and the item is
retrieved. As a best practice, we recommend that you limit the properties returned to
only those that are required. This example returns the item Id property and the Subject
property.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server. The local variable itemId is the Id of
the item to update.

C#

// As a best practice, limit the properties returned to only those that are
required.

PropertySet propSet = new PropertySet(BasePropertySet.IdOnly,


ItemSchema.Subject);

// Bind to the existing item by using the ItemId.

// This method call results in a GetItem call to EWS.

Item item = Item.Bind(service, itemId, propSet);

If you're searching for an item that meets specific criteria, do the following:

1. Bind to the folder that contains the items to get.

2. Instantiate a SearchFilter.SearchFilterCollection or a PropertySet to filter the


items to return.

3. Instantiate an ItemView or CalendarView object to specify the number of items


to return.

4. Call the ExchangeService.FindItems or ExchangeService.FindAppointments


method.

For example, if you want to retrieve unread email messages in the Inbox, use the code in
the following example. This example uses a SearchFilterCollection to limit the results of
the FindItems method to unread messages, and limits the ItemView to limit results to
one item. This particular code only works on EmailMessage objects because the
EmailMessageSchema.IsRead value is part of the SearchFilter.

C#

// Bind the Inbox folder to the service object.

Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);

// The search filter to get unread email.

SearchFilter sf = new
SearchFilter.SearchFilterCollection(LogicalOperator.And, new
SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));

ItemView view = new ItemView(1);

// Fire the query for the unread items.

// This method call results in a FindItem call to EWS.

FindItemsResults<Item> findResults =
service.FindItems(WellKnownFolderName.Inbox, sf, view);

Alternatively, you can use a PropertySet to limit the results of the search as shown in
the following code example. This example uses the FindAppointments method to
retrieve up to five appointments that occur in the next 30 days. This code of course only
works on calendar items.

C#

// Initialize values for the start and end times, and the number of
appointments to retrieve.

DateTime startDate = DateTime.Now;

DateTime endDate = startDate.AddDays(30);

const int NUM_APPTS = 5;

// Bind the Calendar folder to the service object.

// This method call results in a GetFolder call to EWS.

CalendarFolder calendar = CalendarFolder.Bind(service,


WellKnownFolderName.Calendar, new PropertySet());

// Set the start and end time and number of appointments to retrieve.

CalendarView cView = new CalendarView(startDate, endDate, NUM_APPTS);

// Limit the properties returned to the appointment's subject, start time,


and end time.

cView.PropertySet = new PropertySet(AppointmentSchema.Subject,


AppointmentSchema.Start, AppointmentSchema.End);

// Retrieve a collection of appointments by using the calendar view.

// This method call results in a FindAppointments call to EWS.

FindItemsResults<Appointment> appointments =
calendar.FindAppointments(cView);

Note that the information the server returns in the Bind method response is different
than the information that the server returns for a FindItem or FindAppointment method
response. The Bind method can return all the schematized properties, whereas the
FindItem and FindAppointment methods do not return all the schematized properties.
So if you need full access to the item, you'll have to use the Bind method. If you don't
have the item Id of the item you'd like to retrieve, use the FindItem or
FindAppointment methods to retrieve the Id, and then use the Bind method to retrieve
the properties you need.

To learn how to get a meeting or appointment item by using the EWS Managed API, see
Get appointments and meetings by using EWS in Exchange.
Get an item by using EWS
If you know the ItemId of the item to retrieve, you can get the item by using the
GetItem operation.

The following example shows the XML request to get the Subject of an item with a
specific ItemId. This is also the XML request that the EWS Managed API sends when
calling the Bind method on an ItemId. The values of some attributes and elements
have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2013" />

</soap:Header>

<soap:Body>

<m:GetItem>

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

</t:AdditionalProperties>

</m:ItemShape>

<m:ItemIds>

<t:ItemId Id="GJc/NAAA=" />

</m:ItemIds>

</m:GetItem>

</soap:Body>

</soap:Envelope>

The following example shows the XML response that the server returns after it processes
the GetItem operation. The response indicates the item was retrieved successfully. The
values of some attributes and elements have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">

<s:Header>

<h:ServerVersionInfo MajorVersion="15"

MinorVersion="0"

MajorBuildNumber="815"

MinorBuildNumber="6"

Version="V2_7"

xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"/>

</s:Header>

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<m:GetItemResponse
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">

<m:ResponseMessages>

<m:GetItemResponseMessage ResponseClass="Success">

<m:ResponseCode>NoError</m:ResponseCode>

<m:Items>

<t:Message>
<t:ItemId Id="GJc/NAAA="
ChangeKey="CQAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAGJd9Z"/>

<t:Subject>Company Soccer Team</t:Subject>

</t:Message>

</m:Items>

</m:GetItemResponseMessage>

</m:ResponseMessages>

</m:GetItemResponse>

</s:Body>

</s:Envelope>

If you do not know the ItemId of the item you want to retrieve, you can use the
FindItem operation to find the item. In order to use the FindItem operation, you must
first identify the folder that you're searching. You can identify the folder by using its
DistinguinguishedFolderName or by using the FolderId . You can use either the
FindFolder or SyncFolderHierarchy operations to get the FolderId you need. Then
use the FindItem operation to search that folder for results that match the search filter.
Unlike the EWS Managed API, EWS does not provide a separate find operation for
appointments. The FindItem operation retrieves items of all types.

The following example shows the XML FindItem operation request that is sent to the
server to find appointments in the Calendar folder that occur in the next 30 days. The
values of some attributes and elements have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"

xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"

xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2007_SP1" />

</soap:Header>

<soap:Body>

<m:FindItem Traversal="Shallow">

<m:ItemShape>

<t:BaseShape>IdOnly</t:BaseShape>

<t:AdditionalProperties>

<t:FieldURI FieldURI="item:Subject" />

<t:FieldURI FieldURI="calendar:Start" />

<t:FieldURI FieldURI="calendar:End" />

</t:AdditionalProperties>

</m:ItemShape>

<m:CalendarView MaxEntriesReturned="5" StartDate="2013-10-


16T17:04:28.722Z" EndDate="2013-11-15T18:04:28.722Z" />

<m:ParentFolderIds>

<t:FolderId Id="AAAEOAAA="
ChangeKey="AgAAABYAAAAqRr3mNdNMSasqx/o9J13UAAAAAAA3" />

</m:ParentFolderIds>

</m:FindItem>

</soap:Body>

</soap:Envelope>

The server responds to the FindItem request with a FindItemResponse message that
includes the ResponseCode value of NoError, which indicates that the operation
completed successfully. If any calendar items meet the filtering criteria, they are included
in the response.

Note that the information the server returns in the GetItem operation response is
different than the information the server returns in a FindItem or FindAppointment
operation response. The GetItem operation can return all the schematized properties,
whereas the FindItem and FindAppointment operations do not return all the
schematized properties. So if you need full access to the item, you'll have to use the
GetItem operation. If you don't have the ItemId of the item you'd like to retrieve, use
the FindItem or FindAppointment operations to retrieve the ItemId, and then use the
GetItem operation to retrieve the elements you need.

To learn how to get a meeting or appointment item by using EWS, see Get
appointments and meetings by using EWS in Exchange.

Update an item by using the EWS Managed API


The steps to update an item by using the EWS Managed API are similar for all item
types; however, the item properties are different for each item type, and the Update
method has many overloaded methods to choose from. To update an item:

1. Use the Bind method to get the latest version of the item, unless you already
have it. To update properties specific to a strongly typed item, you'll have to bind
to that item type. To update properties available on the generic item type, you can
bind to the Item object.

2. Update the properties on the item.

3. Call the Update method.

For example, you can update the subject of an email by using the generic item type, as
shown in the code in the following example.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server. The local variable itemId is the Id of
the item to update.

C#

// Bind to the existing item, using the ItemId.

// This method call results in a GetItem call to EWS.

Item item = Item.Bind(service, itemId);

// Update the Subject of the email.

item.Subject = "New subject";

// Save the updated email.

// This method call results in an UpdateItem call to EWS.

item.Update(ConflictResolutionMode.AlwaysOverwrite);

To learn how to update a meeting or appointment item by using the EWS Managed API,
see Update appointments and meetings by using EWS in Exchange.

Update an item by using EWS


To update an item by using EWS, do the following:

1. Use the GetItem operation to get the latest version of the item, unless you
already have it.

2. Use the UpdateItem operation to specify fields to update and assign new values
to those fields.
The following example shows the XML UpdateItem operation request that is sent to the
server to update the Subject value of the email message. The values of some
attributes and elements have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010_SP1" />

</soap:Header>

<soap:Body>

<m:UpdateItem MessageDisposition="SaveOnly"
ConflictResolution="AlwaysOverwrite">

<m:ItemChanges>

<t:ItemChange>

<t:ItemId Id="APdZjAAA="
ChangeKey="CQAAABYAAAAqRr3mNdNMSasqx/o9J13UAAAAPdgr" />

<t:Updates>

<t:SetItemField>

<t:FieldURI FieldURI="item:Subject" />

<t:Message>

<t:Subject>New subject</t:Subject>

</t:Message>

</t:SetItemField>

</t:Updates>

</t:ItemChange>

</m:ItemChanges>

</m:UpdateItem>

</soap:Body>

</soap:Envelope>

The server responds to the UpdateItem request with a UpdateItemResponse message


that includes the a ResponseCode value of NoError, which indicates that the item
update was successful.

To learn how to update a meeting or appointment item by using EWS, see Update
appointments and meetings by using EWS in Exchange.

Delete an item by using the EWS Managed API


You can delete items by moving them to the Deleted Items folder or to the dumpster. If
you know the ItemId of the item to delete, just call the Delete method on the item.

If you need to find the item before deleting it, do the following:
1. Call the FindItems or FindAppointments method to find the item to delete.

2. Instantiate a PropertySet and limit it to the properties to return, or use a


SearchFilterCollection to find specific items.

3. Instantiate an ItemView or CalendarView to specify the number of items to


return.

4. Call the Delete method.

For example, the following code shows how to move an email message to the Deleted
Items folder.

This example assumes that service is a valid ExchangeService object and that the user
has been authenticated to an Exchange server. The local variable itemId is the Id of
the item to update.

C#

// Bind to the existing item, using the ItemId.

// This method call results in a GetItem call to EWS.

Item item = Item.Bind(service, itemId);

// Delete the item by moving it to the Deleted Items folder.

// This method call results in a DeleteItem call to EWS.

item.Delete(DeleteMode.MoveToDeletedItems);

For more details about deleting items, see Deleting items by using EWS in Exchange. To
learn how to delete a meeting or appointment item by using the EWS Managed API, see
Delete appointments and cancel meetings by using EWS in Exchange.

Delete an item by using EWS


You can delete an item by using the DeleteItem operation.

The following example shows the XML request that is sent to the server to move the
email message to the Deleted Items folder. The values of some attributes and elements
have been shortened for readability.

XML

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<t:RequestServerVersion Version="Exchange2010_SP1" />

</soap:Header>

<soap:Body>

<m:DeleteItem DeleteType="MoveToDeletedItems">

<m:ItemIds>

<t:ItemId Id="APdZjAAA="
ChangeKey="CQAAABYAAAAqRr3mNdNMSasqx/o9J13UAAANIFzC" />

</m:ItemIds>

</m:DeleteItem>

</soap:Body>

</soap:Envelope>

The server responds to the DeleteItem request with a DeleteItemResponse message


that includes the a ResponseCode value of NoError, which indicates that the item
deletion was successful.

For more details about deleting items, see Deleting items by using EWS in Exchange. To
learn how to delete a meeting or appointment item by using EWS, see Delete
appointments and cancel meetings by using EWS in Exchange.

Move or copy items to another mailbox


You can move or copy items between mailboxes by using the ExportItems and
UploadItems operations. To learn more, see Exporting and importing items by using
EWS in Exchange.

See also
Folders and items in EWS in Exchange
Work with folders by using EWS in Exchange
Deleting items by using EWS in Exchange
Deleting items by using EWS in
Exchange
Article • 09/14/2022 • 7 minutes to read

Find out how you can use the EWS Managed API or EWS in Exchange to delete items
either by moving them to the Deleted Items folder or to the dumpster.

Have you ever asked yourself what the difference is between moving items to the
Deleted Items folder, and moving them to the dumpster? You might be curious about
the different options for handling deleted items and how to implement those options in
your application. Exchange Web Services (EWS) includes three options for handling
deleted items. This article will hopefully clear up any confusion you might have about
the differences between them.

Deleting items - what are my options?


Before you can understand the overall landscape for deleting items, it's important to
recognize the difference between the following:

The Deleted Items folder - When you delete items in a mailbox, this is where they
go.

The dumpster (aka the Recoverable Items folder) - When you remove items from a
mailbox, this is where they go.

Figures 1 and 2 show what the deletion process looks like for items and folders in a
mailbox.

Figure 1. Process for deleting items from a mailbox


Figure 2. Process for deleting folders from a mailbox

You can delete items and folders three different ways, depending on how "permanent"
you would like the deletion to be.

Table 1: Options for deleting items by using EWS


Option What happens

Move This is the least permanent way to delete items.

to the
Deleted This is like putting a piece of paper in the recycle bin by your desk. You can easily grab
Items it if you need it again.

folder
You can use any deletion operation that implements the move to the Deleted Items
folder option to perform this action.

You can also use the MoveItem operation ( Item.Move() ) or the MoveFolder
operation ( Folder.Move() ) to move an item or folder to the Deleted Items folder.

Soft The item is moved to the Deletions folder in the dumpster.

delete
This is like emptying your recycle bin into your curbside container. You can still access
the item if you need to, it's just a little harder.

For more about the dumpster (also called the Recoverable Items folder) and scenarios
such as eDiscovery or litigation holds, see Recoverable Items Folder on TechNet.

Soft deletions aren't recommended for applications that target Exchange 2007. In
Exchange 2007, soft deletions are handled by setting a bit on the item to indicate that it
will be moved to the dumpster at an unspecified time.

Soft delete traversals, or searches of items that have been soft deleted via the FindItem
operation , are not supported in Exchange Online, Exchange Online as part of Office
365, and versions of Exchange starting with Exchange 2010.

NOTE: Folders cannot be soft deleted.

Hard The item or folder is permanently deleted.

delete
Hard-deleted items are placed in the Purges folder of the dumpster. This is like when
the recycling truck empties your curbside recycle container. The items cannot be
accessed from an email client like Outlook or Outlook Web App, and, unless there is a
hold set on the mailbox, the items will be permanently deleted after a set period of
time.

You can read more about item retention in the article Configure Deleted Item Retention
and Recoverable Items Quotas .

NOTE: Folders are not placed in the Purges folder when they are hard deleted. Hard-
deleted folders are removed from the mailbox.

The move to the Deleted Items folder and the hard delete options are transactional,
which means that by the time the web service call finishes, the item has been moved to
the Deleted Items folder or the dumpster.
To help you better understand the ecosystem of folders that are used to store deleted
items, the following figure shows the hierarchy of folders that can contain deleted items.
The folder names are as they appear in the DistinguishedFolderIdNameType schema
type, or the WellKnownFolderName enumeration in the EWS Managed API.

Figure 3. Hierarchy of folders that contain deleted items

Table 2: Folders that contain deleted items

Folder name Introduced Description


in

deleteditems Exchange The default Deleted Items folder. Items remain


2007 in this folder until they are soft- or hard-deleted
or until a retention period has been exceeded.
Then they are moved to a folder in the
dumpster. Deleted folders are placed in the
Deleted Items folder, and when they are soft- or
hard-deleted, they are permanently removed
from the mailbox and are not recoverable.

recoverableitemsroot Exchange The root of the dumpster, or the Recoverable


2010 Items folder. Dumpster access was implemented
in EWS in Exchange 2010. The display name for
this folder is "Recoverable Items".
Folder name Introduced Description
in

recoverableitemsdeletions Exchange The main dumpster folder for a mailbox. Soft-


2010 deleted items and items moved from the
Deleted Items folder by a retention policy are
placed in this folder. The display name for this
folder is "Deletions".

recoverableitemsversions Exchange Where older versions of an item are stored. Old


2010 versions of an item are created when an item is
updated. Draft item versions are not saved to
this folder. The display name of this folder is
"Versions".

recoverableitemspurges Exchange Where items that are removed from the


2010 Deletions folder are stored. All store hard-
deleted items are moved to this folder. The
display name for this folder is "Purges".

archiveddeletedtitems Exchange The default Deleted Items folder for an archive


2010 mailbox.

archiverecoverablesitemsroot Exchange The root dumpster folder for an archive


2010 mailbox. Archived items that are soft-deleted
are moved to a subfolder in this folder.

archiverecoverableitemsdeletions Exchange The main dumpster folder for an archive


2010 mailbox. Archived items moved to the dumpster
are placed here.

archiverecoverableitemsversions Exchange Where older versions of archived items are


2010 stored.

archiverecoverableitemspurges Exchange Where items that are hard-deleted from the


2010 archive Deletions folder in the dumpster are
stored. All store hard-deleted archived items are
moved to this folder.

How do I delete items?


Use one of the following to indicate whether to move an item to the Deleted Items
folder or perform a soft delete or a hard delete:

The DisposalType simple type, if you use EWS to access Exchange.

The DeleteMode enumeration , if you use the EWS Managed API.


You can use a number of different EWS operations or EWS Managed API methods to
delete items and folders from a mailbox.

Table 3: EWS operations and EWS Managed API methods for deleting items

EWS operation EWS Managed API method Introduced What it does


in

DeleteFolder Folder.Delete method


Exchange Deletes
operation
2007 folders from a
mailbox. With
EWS, you can
batch delete
folders. With
the EWS
Managed API,
you can only
delete a
single folder
per call.

DeleteItem operation
Item.Delete method
Exchange Deletes items
2007 from a
ExchangeService.DeleteItems mailbox.
method

EmptyFolder operation Folder.Empty method


Exchange Deletes all the
2010 items in a
folder, and,
optionally,
deletes all
subfolders in
a folder.

ApplyConversationAction Conversation.EnableAlwaysDeleteItems Exchange Sets a delete


operation
method
2010 processing
action on
Conversation.DeleteItems method
email
messages in a
conversation
so that they
are deleted.

DeleteUserConfiguration UserConfiguration.Delete method


Exchange Deletes a
operation
2010 folder
associated
item and
moves it to
the dumpster.
EWS operation EWS Managed API method Introduced What it does
in

CreateItem operation
Appointment.Accept method
Exchange Indirectly
2007 moves an
Appointment.AcceptTentatively item to the
method
Deleted Items
folder
Appointment.CancelMeeting whenever a
method
response to a
meeting
Appointment.Decline
request is
sent or the
MeetingRequest.Accept method
response is
set on the
MeetingRequest.AcceptTentatively appointment.

method

The deletion
Meeting