Quantcast
Channel: Outlook dev blog
Viewing all 108 articles
Browse latest View live

Autodiscover for Exchange ActiveSync developers

$
0
0

This post is part of an ongoing series that covers Microsoft Exchange ActiveSync for developers.

Autodiscover is a process by which a Microsoft Exchange Server client can determine the URL of the Microsoft Exchange ActiveSync endpoint by using only a mailbox SMTP address and user credentials. During the Autodiscover process, the client uses the mailbox SMTP address to determine the Autodiscover service endpoint URL and sends a request to the Autodiscover service that includes the mailbox SMTP address. A successful call to the Autodiscover service results in a response that contains the Exchange ActiveSync endpoint URL that the client will use to access the mailbox. This not only simplifies initial client configuration for the end user, but also gives the client a mechanism by which to recover from errors and respond to changes in the Microsoft Exchange environment automatically.

In this blog post, I describe the Autodiscover process from the perspective of an Exchange ActiveSync client developer, including the following:

  • The process of finding and calling the Autodiscover service.
  • The specific requests and responses that are used during the Autodiscover process.
  • When clients should call Autodiscover. 

 

Note

The following information, covered in this blog post, is important for the Exchange ActiveSync Logo Program:

·        Full implementation of the Autodiscover algorithm

·        The use of Autodiscover to recover from transient connection errors

·        The handling of the X-MS-Location header in 451 redirect responses

·        The handling of 302 redirect responses

 

For more information about the logo program, see Exchange ActiveSync Logo Program on Microsoft TechNet.

 

Finding and calling the Autodiscover service

A client needs only an email address and user credentials to successfully find and call the Autodiscover service. The client should parse the email address to get the domain information, which is everything to the right of the “@” character.

In the following procedure, woodgrovebank.com is the domain from the email address chris@woodgrovebank.com. If the domain information includes a subdomain, such as sales.woodgrovebank.com, the client should use the sales.woodgrovebank.com subdomain first and then, if the procedure fails, try again using the domain woodgrovebank.com. The client uses this domain to construct the Autodiscover service endpoint URLs.

The following procedure describes the Autodiscover process for Exchange ActiveSync clients.

Tip

A client can minimize the user input needed by only asking for the email address and password in step 1. If the user account is not provisioned for a UPN logon, more input may be required. In this case, a 401 error response will be returned, and the client should collect the domain and user name from the user and resubmit the request.

1. The client sends an Autodiscover request to https://woodgrovebank.com/autodiscover/autodiscover.xml and does one of the following:

  • If the Autodiscover attempt succeeds, the client proceeds to step 5.
  • If the Autodiscover attempt fails, the client proceeds to step 2.

2. The client sends an Autodiscover request to https://autodiscover.woodgrovebank.com/autodiscover/autodiscover.xml, and does one of the following:

  • If the Autodiscover attempt succeeds, the client proceeds to step 5.
  • If the Autodiscover attempt fails, the client proceeds to step 3.

3. The client sends an unauthenticated GET method request to http://autodiscover.woodgrovebank.com/autodiscover/autodiscover.xml. (Note that this is a non-SSL endpoint).The client does one of the following:

  • If the GET request returns a 302 redirect response, it gets the redirection URL from the Location HTTP header, and validates it as described in the section “Redirect responses”. The client then does one of the following:
    • If the redirection URL is valid, the client tries the URL, and does one of the following:
      • If the attempt succeeds, the client proceeds to step 5.
      • If the attempt fails, the client proceeds to step 4.
    • If the redirection URL is not valid, the client proceeds to step 4.
  • If the GET request does not return a 302 redirect response, the client proceeds to step 4.

4. The client performs a DNS query for an SRV record for _autodiscover._tcp.woodgrovebank.com. The query might return multiple records. The client selects only records that point to an SSL endpoint and that have the highest priority and weight. One of the following occurs:

  • If no such records are returned, the client proceeds to step 6.
  • If records are returned, the application randomly chooses a record in the list, and validates the endpoint that it points to by following the process described in the section “Redirect Response”. The client then does one of the following:
    • If the redirection URL is valid, it tries the URL, and one of the following occurs:
      • If the attempt succeeds, the client proceeds to step 5.
      • If the attempt fails, the client proceeds to step 6.
    • If the redirection URL is not valid, the client proceeds to step 6.

5. When a valid Autodiscover request succeeds, the following takes place:

  • If the server responds with an HTTP 302 redirect, the client validates the redirection URL according to the process defined in the section “Redirect responses”, and does one of the following:
    • If the redirection URL is valid, the client tries the URL, and does one of the following:
      • If the attempt succeeds, the client resumes step 5 from the beginning.
      • If the attempt fails, the client proceeds to step 6.
    • If the redirection URL is not valid, the client proceeds to step 6.
  • If the server responds with a valid Autodiscover response, the client does one of the following:
    • If the value of the Action element is "Redirect", it gets the redirection email address from the Redirect element, and returns to step 1 using this new email address.
    • If the value of the Action element is "Settings", the client has successfully received the requested configuration settings for the specified user. The client does not need to proceed to step 6.

6. If the client cannot contact the Autodiscover service, the client should ask the user for the Exchange server name and use it to construct an Exchange ActiveSync URL, similar to the following: http://servername/Microsoft-Server-ActiveSync. The client should try to use this URL for future requests.

Tip

The client can perform steps 1-4 in any order or in parallel to expedite the process, but it must wait for responses to finish at each step before proceeding. Given that many organizations prefer to use the URL in step 2 to set up Autodiscover, the client might try this step first.

 

 

 

Autodiscover requests and responses

The preceding procedure mentions Autodiscover requests and responses. Microsoft Exchange publishes a "plain old XML" (POX) endpoint for the Autodiscover service. (For more information, see Autodiscover Reference (POX) on MSDN.) These responses can be quite large. Because Exchange ActiveSync is a mobile protocol, a more concise Autodiscover schema called "mobilesync" is defined specifically for Exchange ActiveSync clients.

The following is an example of an Exchange ActiveSync Autodiscover request.

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

<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006">

     <Request>

            <EMailAddress>chris@woodgrovebank.com</EMailAddress>

            <AcceptableResponseSchema>

             http://schemas.microsoft.com/exchange/autodiscover/mobilesync/

             responseschema/2006

            </AcceptableResponseSchema>

     </Request>

</Autodiscover>

 

Successful response

A successful Exchange ActiveSync response contains URL settings for Exchange ActiveSync. Settings in the Exchange ActiveSync Autodiscover response can contain two server sections: one with the type “MobileSync”, which is the Exchange ActiveSync endpoint URL, and one with the type “CertEnroll”, which is used to obtain a client certificate for SSL negotiation. (For more information about this response, see [MS-ASCMD] ActiveSync Command Reference Protocol Specification section 4.2.4.)

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

<Autodiscover

xmlns:autodiscover="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006">

    <autodiscover:Response>

        <autodiscover:Culture>en:us</autodiscover:Culture>

        <autodiscover:User>

            <autodiscover:DisplayName>Chris Gray</autodiscover:DisplayName>

            <autodiscover:EMailAddress>chris@woodgrovebank.com</autodiscover:EMailAddress>

        </autodiscover:User>

        <autodiscover:Action>

            <autodiscover:Settings>

                <autodiscover:Server>

                    <autodiscover:Type>MobileSync</autodiscover:Type>

                    <autodiscover:Url>

                        https://loandept.woodgrovebank.com/Microsoft-Server-ActiveSync

                    </autodiscover:Url>

                    <autodiscover:Name>

                 https://loandept.woodgrovebank.com/Microsoft-Server-ActiveSync

             </autodiscover:Name>

                </autodiscover:Server>

                <autodiscover:Server>

                    <autodiscover:Type>CertEnroll</autodiscover:Type>

                    <autodiscover:Url>https://cert.woodgrovebank.com/CertEnroll</autodiscover:Url>

                    <autodiscover:Name />

                   <autodiscover:ServerData>CertEnrollTemplate</autodiscover:ServerData>

                </autodiscover:Server>

            </autodiscover:Settings>

        </autodiscover:Action>

    </autodiscover:Response>

</Autodiscover>

Redirect responses

Redirection to a different URL can be in the form of an HTTP 302 response. In the following example, an Autodiscover request is being redirected to a different URL. The client should try to send an Autodiscover request to the URL in the response. If the request sent to the redirect location fails, the client should stop and inform the user that Autodiscover has failed.

HTTP/1.1 302 Found

Location: https://autodiscover.us.woodgrovebank .com/autodiscover/autodiscover.xml

Important

The client should always validate the URL received in the redirect response to ensure that it does not redirect to non-SSL endpoints or SSL endpoints with invalid certificates.

 

Steps 3 and 4 in the procedure in the section "Finding and calling the Autodiscover service" describe an unauthenticated, non-SSL, GET request and a DNS lookup, respectively. Because both of these redirection mechanisms can be spoofed, it is important for the Exchange ActiveSync client to properly validate the redirection. Beyond the validation described, in this case the client should also prompt the user to validate the service provider and name on the certificate of the endpoint.

 

For more information, see Implementing an Autodiscover Client in Microsoft Exchange on MSDN.

 

 

 

Redirects can also come from within the details of an Autodiscover response, as shown in the following example. In this case, the client is being directed to start the Autodiscover process over with a new email address.

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

<Autodiscover xmlns:autodiscover="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006">

    <autodiscover:Response>

        <autodiscover:Culture>en:us</autodiscover:Culture>

        <autodiscover:User>

           <autodiscover:DisplayName>Chris Gray</autodiscover:DisplayName>

           <autodiscover:EMailAddress>chris@woodgrovebank.com</autodiscover:EMailAddress>

        </autodiscover:User>

        <autodiscover:Action>

           <autodiscover:Redirect>chris@loandept.woodgrovebank.com </autodiscover:Redirect>

        </autodiscover:Action>

    </autodiscover:Response>

</Autodiscover>

The client should start from step 1 in the procedure with the email address from the redirect response, chris@loandept.woodgrovebank.com.

Important

The client should look out for redirections to the same email or URL that it is already using – also known as “circular” redirections. If a circular redirection is detected, the client should not follow it and instead should move to the next step. To avoid getting into an infinite “redirection loop”, the client should also track the total number of redirections and fail after 10.

 

Error responses

Errors can come in the form of HTTP 403 or 404 error responses, or in the Error section of an Autodiscover response. The client should consider these errors permanent and move on to the next step in the Autodiscover URL location process. An HTTP 401 response indicates that authentication failed. The client can choose to present the user an opportunity to enter credentials again.

Error responses from Autodiscover can indicate a problem with the request the client sent or a problem on the server side. In the following example, there was a problem contacting the directory service on the server side. Because this error is on the server side, the client should continue on to the next step in the Autodiscover URL location process. The client can also choose to retry this request, as the error might be transient.

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

<Autodiscover xmlns:autodiscover="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006">

    <autodiscover:Response>

        <autodiscover:Culture>en:us</autodiscover:Culture>

        <autodiscover:User>

           <autodiscover:EMailAddress>chris@woodgrovebank.com</autodiscover:EMailAddress>

       </autodiscover:User>

       <autodiscover:Action>

           <autodiscover:Error>

               <Status>1</Status>

               <Message>The directory service could not be reached</Message>

               <DebugData>MailUser</DebugData>

           </autodiscover:Error>

       </autodiscover:Action>

    </autodiscover:Response>

</Autodiscover>

Error responses can also indicate problems with the Autodiscover request sent by the client. The following example shows an error code 600 response, which indicates an invalid request. A 601 response would indicate that the requested schema version is not supported by the server.

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

<Autodiscover

xmlns:autodiscover="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006">

   <autodiscover:Response>

      <autodiscover:Error Time="16:56:32.6164027" Id="1054084152">

          <autodiscover:ErrorCode>600</autodiscover:ErrorCode>

          <autodiscover:Message>Invalid Request</autodiscover:Message>

          <autodiscover:DebugData />

      </autodiscover:Error>

   </autodiscover:Response>

</Autodiscover>

When should the client perform Autodiscover?

Because Autodiscover requires only an email address and password, using Autodiscover can make the initial configuration of an email account easy for a user. After performing Autodiscover in an initial account configuration, the device should cache the Exchange ActiveSync URL that is returned in the successful response.

Tip

While the client should cache the Exchange ActiveSync URL that is retrieved through the Autodiscover process, we recommend that, regardless of any error responses, the URL be refreshed once every 24 hours. Performing Autodiscover periodically ensures that the client is using the most efficient Microsoft Exchange URL for a given mailbox.

Autodiscover is equally important after the initial configuration of the email client as a method for recovering from transient errors. If the client receives HTTP 401, 403, 404, or 500 responses, timeouts, or any response that indicates a DNS lookup failure, it should run Autodiscover to see if it gets a new URL. For more information, see [MS-ASHTTP] ActiveSync HTTP Protocol Specification section 3.1.5.2.1.

The client can also receive an HTTP 451 redirect response, as specified in [MS-ASHTTP] ActiveSync HTTP Protocol Specification section 3.1.4.2.2. This response indicates that the client sent a request to a URL that is no longer the optimum endpoint URL for the mailbox the client is trying to access. This can occur when a mailbox moves from one Active Directory site to another. For more information, see Understanding Proxying and Redirection on Microsoft TechNet. The client will continue to receive the 451 error until it sends requests to the new endpoint.

Typically, the 451 response contains an X-MS-Location header that indicates the new Exchange ActiveSync URL for the client to use. When this header is present, the client does not need to use Autodiscover to get the new URL; it can use the URL from the header. However, the X-MS-Location header is optional. If the header is not present, the client should perform Autodiscover to get a new Exchange ActiveSync URL. The following example shows a 451 error response.

HTTP/1.1 451

Date: Tue, 08 Dec 2009 19:43:24 GMT

Server: Microsoft-IIS/7.0

X-Powered-By: ASP.NET

X-AspNet-Version: 2.0.50727

X-MS-Location: https://mail.woodgrovebank .com/Microsoft-Server-ActiveSync

Cache-Control: private

Content-Length: 0

A 302 redirect response is expected and should be followed only during the Autodiscover process. If the client receives a 302 redirect in response to a command, such as FolderSync, it should not follow the redirect. Instead, the client should go through the Autodiscover process again to get a new URL.

Important

When the client performs Autodiscover to attempt to recover from a transient error condition, it should not discard the original Exchange ActiveSync URL that is stored in the cache until it confirms that the new URL works. We recommend that the client perform Autodiscover, determine whether the URL that is retrieved is different than the URL that was cached before the error, try the new URL if it is different, and if the URL works, replace the cached URL with the new URL. This ensures that the client maintains a URL to retry in the event that Autodiscover fails.

 

Related Resources

[MS-ASCMD]: ActiveSync Command Reference Protocol Specification

[MS-ASHTTP]: ActiveSync HTTP Protocol Specification

Understanding Proxying and Redirection

Understanding the Autodiscover Service

Understanding Exchange ActiveSync Autodiscover

Autodiscover and Exchange 2007

 

Post written by: Matt Stehle, Microsoft Corporation


Client access server affinity and network load balancing considerations for programmatic access to Exchange Online

$
0
0

Network load balancing for Microsoft Exchange Online as part of Microsoft Office 365 ensures that tenant client access loads are properly balanced. Network load balancing also has implications for Client Access server affinity. Some stateful client features require Client Access server affinity. This is because some state information is cached on Client Access servers. Both Exchange Web Services (EWS) and MAPI clients include ways to maintain Client Access server affinity through the network load balancers.

Client Access server affinity and Exchange Web Services

Client Access server affinity is important for EWS. Using the Client Access server that services a mailbox improves both performance and function. Using a Client Access server that does not service the particular mailbox to handle a request can negatively affect performance, and in some cases, the request might fail. Requests for features such as event notification subscriptions require stateful information, and state information is maintained on the Client Access server that services the mailbox. Client Access server affinity is required to maintain state information about which notifications have been delivered to the client. For example, if the notification request is not sent to the correct Client Access server, the server will respond with the ErrorSubscriptionNotFound error.

The key to maintaining Client Access server affinity for EWS is the exchangecookiecookie. The exchangecookie cookie associates a client with a specific Client Access server — specifically, the Client Access server that services the target mailbox. The network load balancer uses the exchangecookiecookie to maintain Client Access server affinity for a client. The first response that the client receives from the server will contain the exchangecookiecookie. For all subsequent EWS client requests for that mailbox, the exchangecookie cookie must persist, in order to maintain Client Access server affinity. The client should preserve the cookie after each response, because in some cases the cookie might change mid-session. The exchangecookie cookie should persist for use in all future requests.

Clients that use the EWS Managed API 1.1 and the EWS Java API 1.1 do not have to manage the exchangecookiecookie as this is done automatically. If you create a custom client, make sure that the exchangecookie cookie persists for each mailbox you are accessing.

Client Access server affinity and MAPI

MAPI Client Access server affinity is maintained through the network load balancer by the OutlookSession session. You can maintain Client Access server affinity for a client by using a single OutlookSession session for the client. The client cannot rely on state information maintained on the Client Access server if subsequent sessions are opened since different sessions are not necessarily handled by the same Client Access server that handled a previous session.

Working with meeting requests in Exchange ActiveSync

$
0
0

This post is part of an ongoing series that covers Microsoft Exchange ActiveSync for developers. 

In this post, we are using Exchange ActiveSync protocol version 14.1. Where applicable, we note differences between protocol versions.


Meeting requests are important for information workers who use Microsoft Exchange. Meeting requests inform attendees of a meeting, automatically book meeting time on the organizer's and attendees' calendars, provide reminders for meetings, and enable the booking of conference rooms. This post provides information for developers about working with meeting requests, including the following topics:


  • How meeting requests are created by using Exchange ActiveSync.
  • How invitees' Exchange ActiveSync clients interpret meeting requests.

 

Note:   Other topics related to calendaring with Exchange ActiveSync, such as recurring meetings; delegation; and meeting responses, updates, and cancellations, will be covered in future blog posts.


The following figure shows an overview of the meeting request process and the two key scenarios involved. In this example, Exchange ActiveSync user Alice requests a meeting with Bob from her Exchange ActiveSync client. Bob sees the meeting request on his Exchange ActiveSync device.


clip_image002[4]

Figure 1:   Meeting request process

Scenario 1: Organizer creates meeting request by using an Exchange ActiveSync client

A meeting starts out as a meeting request. The meeting organizer requests that attendees agree to participate in the meeting at a specified date, time, and location. Meeting requests are composed of the following two elements:


1.      A calendar item that reflects the proposed meeting on the organizer's and invitees' calendars.

2.      An invitation email sent by the organizer to invitees to notify them of the proposed meeting and solicit their responses.

In order for a user to create meeting requests, an Exchange ActiveSync client must do the following:


  • Add a new calendar event to the organizer's calendar that includes the meeting details.
  • Send an email to prospective attendees that includes the meeting details and response options.

After the Exchange ActiveSync client sends an email message that includes the meeting invitation, the Exchange server sends the invitation and saves a copy in the Sent Items folder. The following figure shows the client requests and server responses when a user, Alice, creates a meeting request from her Exchange ActiveSync client. The syncing of the Sent Items folder is optional.

meeting request 6

 

Figure 2:   Sending a meeting request from an Exchange ActiveSync client

Adding meeting details to the organizer's calendar

Important:  The client must sync the Calendar folder before the user can create meeting requests. This adds the calendar item to the organizer's calendar. The organizer's mailbox requires the calendar item to reconcile responses to the meeting request.


Request to create the calendar item

When a user organizes a new meeting on the Exchange ActiveSync client, the client must create a meeting item on the organizer's calendar. The client adds the new calendar item to the Calendar collection. The calendar item contains all the meeting details, including meeting attendees. The following example shows an Exchange ActiveSync Sync command XML request that adds a meeting to Alice's calendar when she organizes a meeting and invites Bob.


<?xmlversion="1.0"encoding="utf-8"?>

<Sync>

  <Collections>

    <Collection>

      <SyncKey>85086007</SyncKey>

      <CollectionId>2</CollectionId>

      <Commands>

        <Add>

          <ClientId>1574070035</ClientId>

          <ApplicationData>

             <calendar:TimeZone>4AEAAFAAYQBjAGkAZgBpAGMAIABTAHQAYQBuAGQAYQByAGQAIABUAGkAbQBlAAA

             AAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAA

             IAAAAAAAAAAAAAAFAAYQBjAGkAZgBpAGMAIABEAGEAeQBsAGkAZwBoAHQAIABUAGkAbQBlAAAAAAA

             AAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAA  AAAAAAAxP///w==</calendar:TimeZone>

            <calendar:DtStamp>20110504T152200Z</calendar:DtStamp>

            <calendar:StartTime>20110510T170000Z</calendar:StartTime>

            <calendar:Subject>Quarterly Planning</calendar:Subject>

            <calendar:UID>A3561BDAAE8E4B30AC255FD3F31A3AD700000000000000000000000000000000</calendar:UID>

            <calendar:Attendees>

              <calendar:Attendee>

                <calendar:Email>bob@contoso.com</calendar:Email>

                <calendar:Name>Bob</calendar:Name>

                <calendar:AttendeeStatus>0</calendar:AttendeeStatus>

                <calendar:AttendeeType>1</calendar:AttendeeType>

              </calendar:Attendee>

            </calendar:Attendees>

            <calendar:Location>Office</calendar:Location>

            <calendar:EndTime>20110510T180000Z</calendar:EndTime>

            <airsyncbase:Body>

              <airsyncbase:Type>3</airsyncbase:Type>

              <airsyncbase:Data>Let's meet to plan the budget for the next quarter.

            </airsyncbase:Data>

            </airsyncbase:Body>

            <calendar:Sensitivity>0</calendar:Sensitivity>

            <calendar:BusyStatus>2</calendar:BusyStatus>

            <calendar:AllDayEvent>0</calendar:AllDayEvent>

            <calendar:Reminder>5</calendar:Reminder>

            <calendar:MeetingStatus>1</calendar:MeetingStatus>

          </ApplicationData>

        </Add>

      </Commands>

    </Collection>

  </Collections>

</Sync>

 

For a list of and information about the Calendar schema elements for Exchange ActiveSync, see [MS-ASCAL]:  ActiveSync Calendar Class Protocol Specification section 2.2.2.


In the meeting request, the Exchange ActiveSync client must specify the start time and end time of the proposed event; this information is included in the StartTime and EndTime elements. Both dates have to be valid values of the dateTime type, as described in [MS-ASDTYPE]: ActiveSync Data Types section 2.3. All dates must be specified in Coordinated Universal Time (UTC), without any punctuation separators. Optionally, the client can use the DtStamp element to specify when the calendar item was created.

The client should specify the time zone in the request. If the time zone is not specified, the Exchange server uses its current  time zone for the meeting. For more information about the format of the time zone, see [MS-ASDTYPE]section 2.6.4.

Optionally, the client can mark the organizer's calendar by specifying the BusyStatus element. The following are the possible values for the BusyStatus element:


·        0 – Free

·        1 – Tentative

·        2 – Busy

·        3 – Out of office

If the organizer did not explicitly specify his or her attendance status, the client should use a value of 2 for the BusyStatus element to mark the meeting status as busy. If the client does not provide this value, the server uses a busy status by default.


Important:   As a best practice, the client should always provide a value for the optional UID element. The UID element value is a random hexadecimal ID that the client generates when it creates the calendar item. The maximum length of the UID element value is 300 characters. We strongly recommend that the Exchange ActiveSync client include the UID element because it helps to map the calendar item to the email notifications sent for the meeting. This enables the organizer to track meeting updates and responses to the meeting request.


The client should provide a MeetingStatus element for meetings. When the client saves a meeting to the organizer's calendar, it should set the value of this element to 1, which indicates that the item is a meeting.


A meeting must include the Attendees element, which contains a collection of Attendee elements. Each Attendee element must include at least one Email and one Name element; these contain the name and email address of the attendee. Optionally, the Attendee element can include values for the AttendeeStatus and AttendeeType elements. When the meeting is created, the AttendeeStatus element contains a value of 0. This value changes when attendees respond to the meeting request. If present, the AttendeeType element must be set to one of the following values:


·        1 – Required

·        2 – Optional

·        3 – Resource

Server response to the request to create the calendar item

The Exchange server sends a response to the Exchange ActiveSync client's request. The response indicates the status of the Calendar Sync command operation as well as the status of the individual meeting request. If the item was added correctly (as indicated by a Status element value of 1 in the response for both the item and the collection), the server issues a ServerId element value for the item in lieu of the temporary ClientId element value that the client assigned to it, as shown in the following example.


HTTP/1.1 200 OK

Content-Type: application/vnd.ms-sync.wbxml

 

<?xmlversion="1.0"encoding="utf-8"?>

<Sync>

  <Collections>

    <Collection>

      <SyncKey>1042177286</SyncKey>

      <CollectionId>2</CollectionId>

      <Status>1</Status>

      <Responses>

        <Add>

          <ClientId>1574070035</ClientId>

          <ServerId>2:9</ServerId>

          <Status>1</Status>

        </Add>

      </Responses>

    </Collection>

  </Collections>

</Sync>

 

The client has to associate the newly issued ServerId value with this calendar item. For more information about status response values, see [MS-ASCMD]: ActiveSync Command Reference Protocol Specification.


Note:  Exchange ActiveSync clients should not allow the organizer to respond to meetings that he or she organized

Informing attendees of the meeting details by email notification

The email notification must make it clear to the recipients that its purpose is to inform them of the meeting request. It can also optionally solicit invitee responses to the request, and automatically block the meeting time on prospective attendees' calendars.


Client request to send the meeting email message

Exchange ActiveSync clients use the SendMail command to send MIME-formatted email messages to the server, including calendaring information structured according to a known calendaring format.

The iCalendar format is the most common calendaring format; this format is supported by a variety of clients. The following example shows the Exchange ActiveSync SendMail request that Alice's Exchange ActiveSync client sends.

 

POST /Microsoft-Server-ActiveSync/default.eas?Cmd=SendMail&User=Alice&DeviceId=ABCDEFGH&DeviceType=SmartPhone HTTP/1.1

Content-Length: 2100

Content-Type: application/vnd.ms-sync.wbxml

Host: mail.contoso.com

User-Agent: SmartPhone

 

 

RequestBody :

<?xmlversion="1.0"encoding="utf-8" ?>

<SendMailxmlns="ComposeMail:">

  <ClientId>1248</ClientId>

  <SaveInSentItems/>

  <Mime>MIME-Version: 1.0

    Subject: Quarterly Planning

     Thread-Topic: Quarterly Planning

     To: Bob <bob@contoso.com>

      Content-Type: multipart/alternative;

      boundary="---Next Part---"

 

-----Next Part---

Content-Transfer-Encoding: quoted-printable

Content-Type: text/plain; charset="utf-8"

 

Let's discuss the budget for the next quarter.

 

-----Next Part---

Content-Type: text/calendar; charset="utf-8"; method=REQUEST

Content-Transfer-Encoding: base64

 

QkVHSU46VkNBTEVOREFSDQpNRVRIT0Q6UkVRVUVTVA0K… <Abbreviated>

 

-----Next Part---

</Mime>

</SendMail>

 

The email message contains multiple parts. The message may contain a plain text part, which includes the body text of the meeting request. Several different calendar request formats are available for meeting request messages. Microsoft Exchange supports the iCalendar and TNEF formats. Each of these formats are included in a separate MIME part in the meeting request message. (For more information about MIME, see RFC 2045, RFC 2046, and RFC 2047.) Most clients use the iCalendar format for the meeting request, encoded in base64. Meeting requests have a content type of text/calendar with the method parameter set to “REQUEST”. The following section provides more detail about the iCalendar format.

iCalendar format

The iCalendar format is a file format (extension .ics, .ical) that represents calendaring information such as meeting requests, meeting responses, and free/busy information. For more information about this format, see RFC 2445,RFC 5546, and [MS-OXCICAL]: iCalendar to Appointment Object Conversion Protocol Specification.

This standard enables users of different calendaring systems (including clients and servers) to exchange calendaring information. iCalendar information is transported across the Internet in MIME format. The MIME body that contains the iCalendar information has a content type of text/calendar. The following example shows a typical iCalendar meeting request.


BEGIN:VCALENDAR

METHOD:REQUEST

PRODID: SmartPhone

VERSION:2.0

BEGIN:VTIMEZONE

TZID:Pacific Standard Time

BEGIN:STANDARD

DTSTART:20000101T020000

TZOFFSETFROM:-0700

TZOFFSETTO:-0800

RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11

END:STANDARD

BEGIN:DAYLIGHT

DTSTART:20000101T020000

TZOFFSETFROM:-0800

TZOFFSETTO:-0700

RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3

END:DAYLIGHT

END:VTIMEZONE

BEGIN:VEVENT

UID:A3561BDAAE8E4B30AC255FD3F31A3AD700000000000000000000000000000000

ORGANIZER:MAILTO:alice@contoso.com

ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION:MAILTO:bob@contoso.com

STATUS:CONFIRMED

X-MICROSOFT-CDO-ALLDAYEVENT:FALSE

BEGIN:VALARM

ACTION:DISPLAY

TRIGGER:-PT15M

END:VALARM

SUMMARY: Quarterly Planning

LOCATION:

DTSTART;TZID=Pacific Standard Time:20110510T100000

DTEND;TZID=Pacific Standard Time:20110510T110000

DTSTAMP:20110504T152200Z

LAST-MODIFIED:20110504T152200Z

CLASS:PUBLIC

END:VEVENT

END:VCALENDAR

 

Important:  The UID element value that is included in the iCalendar request email message must match the UID value that is saved with the meeting item on the organizer's calendar.


Server response to the client request to send the meeting email message

The response to SendMail command has no XML body (Content-Length = 0) if the SendMail command finishes successfully, as shown in the following example.


HTTP/1.1 200 OK

MS-Server-ActiveSync: 14.1

 

The server first responds to the SendMail request from the organizer's Exchange ActiveSync client, and then tries to send the message to the attendees. For this reason, a positive response to the SendMail request does not guarantee that the message was sent out successfully. The Exchange ActiveSync client can still receive a non-delivery report notification if the mail recipients are not found. For more information about the SendMail status values, see [MS-ASCMD] section 2.2.3.152.13. Non-delivery report responses should be handled in the same way that email responses are handled.


Before the Exchange server sends the email message, it interprets the iCalendar information and structures the message to the attendees to reflect that it is a meeting request.

Saving the meeting notification in Sent Items

Note:  Exchange ActiveSync clients should not save meeting request messages directly to the local Sent Items folder; instead, clients should use the SaveInSentItems element in the SendMail request to automatically save the messages on the server. It is not possible to reconcile the local Sent Items folder with the server's Sent Items folder by using the Sync command. Items in the server's Sent Items folder can be added to the client by using the Sync command, but items that are in the Exchange ActiveSync client's local Sent Items folder cannot be added to the server.


After the Exchange ActiveSync client submits the meeting request email to the server, the Exchange server sends the email message to all the invited attendees. In addition, the Exchange server parses the iCalendar information that is embedded in the email. This way, it adds the email message to the Sent Items folder as the appropriate type; that is, a meeting request. The next time the Exchange ActiveSync client syncs the Sent Items folder, the meeting request email message will be added to the Sent Items folder on the client.

Client request to sync the Sent Items folder

The client syncs the Sent Items folder as shown in the following example.


POST /Microsoft-Server-ActiveSync?Cmd=Sync&User=alice&DeviceId=ABCDEFGH&DeviceType=SmartPhone HTTP/1.1

Content-Type: application/vnd.ms-sync.wbxml

MS-ASProtocolVersion: 14.1

User-Agent: ASOM

Host: mail.contoso.com

 

<?xmlversion="1.0"encoding="utf-8"?>

<Syncxmlns="AirSync:">

  <Collections>

    <Collection>

      <SyncKey>612092836</SyncKey>

      <CollectionId>10</CollectionId>

      <DeletesAsMoves>1</DeletesAsMoves>

      <GetChanges>1</GetChanges>

      <WindowSize>512</WindowSize>

    </Collection>

  </Collections>

</Sync>

 

Server response to the request to sync the Sent Items folder

The server adds a new item with the MessageClass element set to IPM.Schedule.Meeting.Request, as shown in the following example. This item contains all the meeting details.


HTTP/1.1 200 OK

Content-Type: application/vnd.ms-sync.wbxml

 

<?xmlversion="1.0"encoding="utf-8" ?>

<Syncxmlns="AirSync:">

  <Collections>

    <Collection>

      <SyncKey>333054644</SyncKey>

      <CollectionId>10</CollectionId>

      <Status>1</Status>

      <Commands>

        <Add>

          <ServerId>10:20</ServerId>

          <ApplicationData>

            <email:To>"Bob" &lt;bob@contoso.com&gt;</email:To>

            <email:From>"Alice" &lt;alice@contoso.com&gt;</ email:From>

            <email:Subject>Quarterly Planning</email:Subject>

            <email:DateReceived>2011-05-10T18:52:57.298Z</A2:DateReceived>

            <email:DisplayTo>”Bob”</ email:DisplayTo>

            <email:ThreadTopic>Quarterly Planning</email:ThreadTopic>

            <email:Importance>1</email:Importance>

            <email:Read>1</email:Read>

            <airsyncbase:Body>

              <airsyncbase:Type>1</airsyncbase:Type>

              <airsyncbase:EstimatedDataSize>117</airsyncbase:EstimatedDataSize>

              <airsyncbase:Truncated>1</airsyncbase:Truncated>

            </airsyncbase:Body>

            <email:MessageClass>IPM.Schedule.Meeting.Request</email:MessageClass>

            <email:MeetingRequest>

               <email:AllDayEvent>0</email:AllDayEvent>

               <email:StartTime>2011-05-10T19:00:00.000Z</email:StartTime>

               <email:DtStamp>2011-05-10T18:52:58.770Z</email:DtStamp>

               <email:EndTime>2011-05-10T20:00:00.000Z</email:EndTime>

               <email:Location>Office</email:Location>

               <email:Organizer>"Alice" &lt;alice@contoso.com&gt;</ email:Organizer>

               <email:Sensitivity>0</email:Sensitivity>        

               <email:TimeZone>4AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

               AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAIAAAAAAAAA

               AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

               AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAAAAxP///w==</email:TimeZone>

               <email:GlobalObjId>BAAAAIIA4AB0xbcQGoLgCAAAAAAAAAAAAAAAAAAAAAAAAAAATQA

AAHZDYWwtVWlkAQAAAEEzNTYxQkRBQUU4RTRCMzBBQzI1NUZEM0YzMUEzQUQ3MDAw

MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAA</email:GlobalObjId>

<email:MeetingMessageType>1</email:MeetingMessageType>

            </email:MeetingRequest>

            <email:InternetCPID>20127</email:InternetCPID>

            <email:Flag />

            <email:ContentClass>urn:content-classes:calendarmessage</email:ContentClass>

            <airsyncbase:NativeBodyType>1</airsyncbase:NativeBodyType>

            <email2:ConversationId>A0B01C50859A444590FE77CF0568F16E</email:ConversationId>

            <email2:ConversationIndex>01CC0F437A</email:ConversationIndex>

            <email2:Sender>"Alice" &lt;alice@contoso.com&gt;</ email:Sender>

            <email:Categories />

          </ApplicationData>

        </Add>

      </Commands>

    </Collection>

  </Collections>

</Sync>

 

The meeting request email that is sent to the attendees is of type IPM.Schedule.MeetingRequest and contains a MeetingRequest container. (For more information about the MeetingRequest container, see [MS-ASEMAIL]: ActiveSync E-Mail Class Protocol Specification section 2.2.2.14). This container describes the properties of the meeting. In addition, it now contains the GlobalObjId element value that was assigned to the meeting item by the server.


The GlobalObjId element value identifies the meeting request and allows the client to determine whether it corresponds to an existing object in the Calendar. For more information about the GlobalObjId element, see [MS-ASEMAIL] section 2.2.2.14.15. The UID element value assigned to the calendar item by the Exchange ActiveSync client is included in the GlobalObjId element value that the server returns. The GlobalObjId element value does not change when the meeting is updated. This enables the client to identify which meeting a particular notification corresponds to.


This meeting request message that is added to the organizer's Sent Items folder should not expose any response options to the user because it is in the organizer's mailbox.

Scenario 2: A meeting invitee receives a meeting request on the Exchange ActiveSync client

When an organizer sends a meeting request, the invitees' Exchange ActiveSync client must be able to receive the request, interpret it, and present it to the invitee as a meeting invitation. The meeting request should appear in the invitee's Inbox, and a placeholder Calendar item for the meeting should appear on the invitee's Calendar. The invitee should be able to accept, tentatively accept, or decline the meeting request, either from the meeting invitation or from the Calendar placeholder item, and send his or her response the meeting organizer.


The following figure shows the operations involved in sending a meeting request to an Exchange ActiveSync client. In this example, Bob is the meeting invitee.


clip_image006[4]

Figure 3:   Sending a meeting request to an Exchange ActiveSync client

Adding the meeting request to the invitee's Inbox

When the meeting invitation first arrives in the invitee's mailbox, it is in the form of a meeting request in the Inbox.


Receiving the meeting request

The Exchange ActiveSync client receives the meeting request upon issuing a Sync command request for the invitee's Inbox. We recommend that Exchange ActiveSync clients request body items in HTML format by setting the BodyPreference element to 2. HTML provides rich content formatting that the client can then render. The meeting request is shown in the following example.


POST /Microsoft-Server-ActiveSync?Cmd=Sync&User=bob&DeviceId=HGFEDCBA&DeviceType=SmartPhone HTTP/1.1

Content-Type: application/vnd.ms-sync.wbxml

MS-ASProtocolVersion: 14.1

User-Agent: ASOM

Host: mail.contoso.com

 

<?xmlversion="1.0"encoding="utf-8"?>

<Syncxmlns="AirSync:">

  <Collections>

    <Collection>

      <SyncKey>1530765051</SyncKey>

      <CollectionId>6</CollectionId>

      <DeletesAsMoves>1</DeletesAsMoves>

      <GetChanges>1</GetChanges>

      <WindowSize>512</WindowSize>

     <Options>

        <airsyncbase:BodyPreference>

          <airsyncbase:Type>2</airsyncbase:Type>

        </airsyncbase:BodyPreference>

      </Options>

    </Collection>

  </Collections>

</Sync>

 

Server response to the Sync command request

The organizer's Exchange server converts the item's iCalendar information and parses it into a message class of IPM.Schedule.Meeting.Request, which is then synced to the invitee's Inbox, as shown in the following example.


Note:  The Exchange ActiveSync client should not attempt any iCalendar content conversion. The Exchange server converts the iCalendar format into the appropriate message class. If the message cannot be converted, it will be delivered as an attachment.

 

HTTP/1.1 200 OK

Content-Type: application/vnd.ms-sync.wbxml

 

<?xmlversion="1.0"encoding="utf-8"?>

<Sync>

  <Collections>

    <Collection>

      <SyncKey>1473331151</SyncKey>

      <CollectionId>6</CollectionId>

      <Status>1</Status>

      <Commands>

        <Add>

          <ServerId>6:17</ServerId>

          <ApplicationData>

            <email:To>"Bob" &lt;bob@contoso.com&gt;</ email:To>

            <email:From>"Alice" &lt;alice@contoso.com&gt;</email:From>

            <email:Subject>Quarterly Planning</email:Subject>

            <email:DateReceived>20110504T152300Z</email:DateReceived>

            <email:DisplayTo>Bob </A2:DisplayTo>

            <email:ThreadTopic>Quarterly Planning</A2:ThreadTopic>

            <email:Importance>1</A2:Importance>

            <email:Read>0</A2:Read>

            <airsyncbase:Body>

              <airsyncbase:Type>2</airsyncbase:Type>

              <airsyncbase:EstimatedDataSize>800</airsyncbase:EstimatedDataSize>

              <airsyncbase:Data>

                &lt;html&gt;

                &lt;head&gt;

                &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt;

                &lt;meta name="Generator" content="Microsoft Exchange Server"&gt;

                &lt;!-- converted from rtf --&gt;

                &lt;style&gt;&lt;!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px  

                solid; } --             

                &gt;&lt;/style&gt;

                &lt;/head&gt;

                &lt;body&gt;

                &lt;font face="Times New Roman" size="3"&gt;&lt;&gt;&lt;a  

                name="BM_BEGIN"&gt;&lt;/a&gt;

                &lt;div&gt;&lt;font face="Courier New"&gt;[When]: Tuesday,May 10, 2011 9:00 PM-10:00 PM.

                [(UTC-08:00) Pacific 

                Time (US &amp;amp; Canada)]&lt;br&gt;

 

                [Where]: Office&lt;br&gt;

 

                &lt;br&gt;

 

                *~*~*~*~*~*~*~*~*~*&lt;br&gt;

 

                &lt;/font&gt;&lt;/div&gt;

                &lt;div&gt;&lt;font face="Tahoma" size="2"&gt;&lt;&gt;Let's meet to

                plan the budget for the next quarter.&lt;&gt;&lt;/font&gt;&lt;/div&gt;

                &lt;&gt;&lt;/font&gt;

                &lt;/body&gt;

                &lt;/html&gt;

              </airsyncbase:Data>

            </airsyncbase:Body> 

            <email:MessageClass>IPM.Schedule.Meeting.Request</email:MessageClass>

            <email:MeetingRequest>

              <email:AllDayEvent>0</email:AllDayEvent>

              <email:StartTime>20110510T170000Z</email:StartTime>

              <email:DtStamp>20110504T152200Z </email:DtStamp>

              <email:EndTime>20110510T180000Z</email:EndTime>

              <email:InstanceType>0</email:InstanceType>

              <email:Location>Office</email:Location>

              <email:Organizer>"Alice " &lt;alice@contoso.com&gt;</ email:Organizer>

              <email:ResponseRequested>1</email:ResponseRequested>

              <email:Sensitivity>0</email:Sensitivity>

              <email:BusyStatus>2</email:BusyStatus>             

              <email:TimeZone>4AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

               AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAIAAAAAAAAAAAAAAAA

               AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

               AAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAAAAxP///w==</email:TimeZone>

               <email:GlobalObjId>BAAAAIIA4AB0xbcQGoLgCAAAAAAAAAAAAAAAAAAAAAAAAAAATQAAAHZDYWwtV

               WlkAQAAAEEzNTYxQkRBQUU4RTRCMzBBQzI1NUZEM0YzMUEzQUQ3MDAwMDAwMDA

               wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAA</email:GlobalObjId>

              <email:MeetingMessageType>1</email:MeetingMessageType>

            </email:MeetingRequest>

            <email:InternetCPID>28591</A2:InternetCPID>

            <email:Flag />

            <email:ContentClass>urn:content-classes:calendarmessage</email:ContentClass>

            <airsyncbase:NativeBodyType>1</airsyncbase:NativeBodyType>

            <email2:ConversationId>AF47F6E22518E64C800FFEA6B901B139</email2:ConversationId>

            <email2:ConversationIndex>CC0F434BDC</email2:ConversationIndex>

            <email:Categories />

          </ApplicationData>

        </Add>

      </Commands>

    </Collection>

  </Collections>

</Sync>


The MeetingRequest element is an optional container element. The MeetingRequest element is included when the message is a meeting request and the Exchange ActiveSync client's user is an attendee. The MeetingRequest element is not included in the message content of calendar items in the Calendar folder or in regular email messages. If a message contains the MeetingRequest element, the client can respond to the meeting request by using the MeetingResponse command. For more information about this command, see [MS-ASCMD] section2.2.2.9.


The GlobalObjId element is a required child element of the MeetingRequest element. GlobalObjId is defined as an element in the Email namespace. Clients that need to determine whether the GlobalObjId element for a meeting request corresponds to an existing Calendar object in the Calendar folder have to convert the GlobalObjId element value to a UID element value to make the comparison. For information about how this conversion is done, see [MS-ASEMAIL] section 2.2.2.14.15.


MeetingMessageType is a new element that was added in version 14.1 of the Exchange ActiveSync protocol. The MeetingMessageType element further defines the type of the meeting request. For information about this element, see [MS-ASEMAIL] section 2.2.2.14.17.

Client request to sync the Calendar folder

The invitee's (Bob's) Exchange ActiveSync client issues a Sync request for the Calendar folder, similar to the one shown in the following example.


POST /Microsoft-Server-ActiveSync?Cmd=Sync&User=bob&DeviceId=HGFEDCBA&DeviceType=SmartPhone HTTP/1.1

Content-Type: application/vnd.ms-sync.wbxml

MS-ASProtocolVersion: 14.1

User-Agent: ASOM

Host: mail.contoso.com

 

<?xmlversion="1.0"encoding="utf-8"?>

<Syncxmlns="AirSync:">

  <Collections>

    <Collection>

      <SyncKey>1085571025</SyncKey>

      <CollectionId>2</CollectionId>

    </Collection>

  </Collections>

</Sync>

 

Tentative meeting added to invitee's calendar

In Microsoft Exchange Server 2007 (which corresponds to Exchange ActiveSync protocol version 12.0) and later versions, the server parses the meeting request received in the invitee's Inbox and adds a tentative meeting to the invitee's calendar to mark the time of the proposed meeting. This tentative meeting is synced to the client.

Server response to the request to Sync the Calendar folder

Based on the meeting request that the Exchange server received, the server created a meeting item in Bob's Calendar folder with the UID element value previously specified by the organizer. Syncing the Calendar collection adds the meeting to the invitee's calendar.


Note:   By default, Microsoft Exchange processes meeting requests and automatically add tentative meetings to the invitee's calendar. The Exchange ActiveSync client should not try to create the meeting item, as that will lead to conflicts between the calendar on the device and the calendar on the server. The administrator can disable tentative meeting creation by running the following Windows PowerShell command:

Set-CalendarProcessing -AddNewRequestsTentatively $false -Identity '<domain>/<user>'

In addition, by default, Microsoft Exchange only processes internal meeting requests . The Exchange administrator can allow external meetings to be processed by running the following Windows PowerShell command:

Set-CalendarProcessing -ProcessExternalMeetingMessages $true -Identity '<domain>/<user>'

If the administrator or the user has not changed the default behavior, any meetings received from senders outside the organization will not be processed and will not automatically be added as tentative meetings to the invitee's calendar.



The calendar item contains a UID element value that the organizer's client had set, which correlates to the meeting request in the Inbox via the GlobalObjIdelement.


HTTP/1.1 200 OK

Content-Type: application/vnd.ms-sync.wbxml

 

<?xmlversion="1.0"encoding="utf-8"?>

<Sync>

  <Collections>

    <Collection>

      <SyncKey>665677459</SyncKey>

      <CollectionId>2</CollectionId>

      <Status>1</Status>

      <Commands>

        <Add>

          <ServerId>2:24</ServerId>

          <ApplicationData>

            <calendar:TimeZone>4AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAIAAAAAAA

             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAA

             AAxP///w==</calendar:TimeZone>

            <calendar:DtStamp>20110504T152200Z </calendar:DtStamp>

            <calendar:StartTime>20110510T180000Z</calendar:StartTime>

            <calendar:Subject>Quarterly Planning</calendar:Subject>            

            <calendar:UID>A3561BDAAE8E4B30AC255FD3F31A3AD700000000000000000

             000000000000000</calendar:UID>

            <calendar:OrganizerName>Alice </calendar:OrganizerName>

            <calendar:OrganizerEmail>alice@contoso.com</calendar:OrganizerEmail>

            <calendar:Attendees>

              <calendar:Attendee>

                <calendar:Email>bob@contoso.com</calendar:Email>

                <calendar:Name>Bob </calendar:Name>

                <calendar:AttendeeType>1</calendar:AttendeeType>

              </calendar:Attendee>

            </calendar:Attendees>

            <calendar:Location>Office</calendar:Location>

            <calendar:EndTime>20110510T190000Z</calendar:EndTime>

            <airsyncbase:Body>

              <airsyncbase:Type>2</airsyncbase:Type>

              <airsyncbase:EstimatedDataSize>585</airsyncbase:EstimatedDataSize>

              <airsyncbase:Data>

                &lt;html&gt;

                &lt;head&gt;

                &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt;

                &lt;meta name="Generator" content="Microsoft Exchange Server"&gt;

                &lt;!-- converted from rtf --&gt;

                &lt;style&gt;&lt;!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px  

                solid; } --             

                &gt;&lt;/style&gt;

                &lt;/head&gt;

                &lt;body&gt;

                &lt;font face="Times New Roman" size="3"&gt;&lt;&gt;&lt;a  

                name="BM_BEGIN"&gt;&lt;/a&gt;

                &lt;div&gt;                &lt;font face="Tahoma" size="2"&gt;&lt;&gt;Let's meet to

                plan the budget for the next quarter.&lt;&gt;&lt;/font&gt;&lt;/div&gt;

                &lt;&gt;&lt;/font&gt;

                &lt;/body&gt;

                &lt;/html&gt;

              </airsyncbase:Data>

            </airsyncbase:Body>

          <calendar:Sensitivity>0</calendar:Sensitivity>

            <calendar:BusyStatus>2</calendar:BusyStatus>

            <calendar:AllDayEvent>0</calendar:AllDayEvent>

            <calendar:Reminder>15</calendar:Reminder>

            <calendar:MeetingStatus>3</calendar:MeetingStatus>

            <airsyncbase:NativeBodyType>1</airsyncbase:NativeBodyType>

            <calendar:ResponseRequested>1</calendar:ResponseRequested>

            <calendar:ResponseType>5</calendar:ResponseType>

          </ApplicationData>

        </Add>

     </Commands>

    </Collection>

  </Collections>

</Sync>

 

The meeting that is added to the invitee's Calendar collection contains all the properties of the calendar item on the organizer's Calendar, as well as the following additional elements:


·        OrganizerName

·        OrganizerEmail

·        ResponseRequested

·        MeetingStatus

·        ResponseType

The value of the ResponseRequested element comes from the PARTSTATparameter value of "NEEDS-ACTION" in the original iCalendar meeting request.


When the invitee receives the meeting request, the MeetingStatus element is set to 3, which indicates that the meeting was received, and the ResponseType element is set to 5, to indicate that the invitee has not yet responded to the meeting request. After the invitee responds, the server updates these values to reflect the new status. Stay tuned for our next blog post, "Working with meeting responses in Exchange ActiveSync", for more information about meeting responses.

Summary

Creating meeting requests and interpreting them from an Exchange ActiveSync client is critical to ensuring a successful calendaring experience for Exchange ActiveSync client users. It is important to use the correct iCalendar format to create meeting requests and to remember not to try to process incoming iCalendar requests on the client, but instead to allow the Exchange server to process the requests.  

Related Resources

[MS-ASEMAIL]: ActiveSync E-Mail Class Protocol Specification

[MS-ASCAL]: ActiveSync Calendar Class Protocol Specification

[MS-ASCMD]: ActiveSync Email Command Reference Protocol Specification

[MS-ASDTYPE]: ActiveSync Data Types

[MS-OXGLOS]: Exchange Server Protocols Master Glossary

[MS-OXCICAL]: iCalendar to Appointment Object Conversion Protocol Specification

RFC 2045, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies"

RFC 2046, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types"

RFC 2047, "MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text"

RFC 2445, "Internet Calendaring and Scheduling Core Object Specification"

RFC 5546, "iCalendar Transport-Independent Interoperability Protocol (iTIP)"

 

Post authored by: Katarzyna Puchala, Microsoft Corporation

    Working with meeting responses in Exchange ActiveSync

    $
    0
    0

    This post is part of an ongoing series that covers Microsoft Exchange ActiveSync for developers. This post applies to Exchange ActiveSync protocol version 14.1. Where applicable, differences between protocol versions are noted.

    The ability to respond to meeting requests is an important aspect of collaboration and communication for Microsoft Exchange users. Responses to meeting requests inform meeting organizers of invitees' attendance status and automatically book the time on attendees' Calendars. This post provides information for developers about working with meeting responses, including the following topics:


    • How the Exchange ActiveSync client responds to meeting requests.
    • How the Exchange ActiveSync client should interpret responses to meetings organized by the client user.

     

    For information about working with meeting requests, see the blog post Working with Meeting Requests in Exchange ActiveSync.


    Note:   Other topics related to calendaring with Exchange ActiveSync, such as recurring meetings; delegation; and meeting responses, updates, and cancellations, will be covered in future blog posts.


    The following figure shows an overview of the meeting response process and the two key scenarios involved. In this example, Exchange ActiveSync user Bob has received a meeting invitation from the organizer, Alice, on his Exchange ActiveSync client. Bob responds to the meeting request using his Exchange ActiveSync device and Alice can verify his response status using her device.


    clip_image002

    Figure 1:   Meeting response process


    This post does not cover adding the meeting request email message to the invitee's Inbox and a creating tentative placeholder item on the invitee's Calendar. For information about the meeting request process, see Working with Meeting Requests in Exchange ActiveSync.


    Scenario 1: Invitee uses an Exchange ActiveSync client to respond to a meeting request

    In our example, an invitee, Bob, finds a meeting request from Alice waiting in his Inbox, and a placeholder Calendar item tentatively marking the time of the meeting on his Calendar. Bob can choose to accept, tentatively accept, or decline the meeting and send his response to the organizer from either the meeting invitation in his Inbox or the Calendar placeholder item. Bob accepts the meeting request by using the options provided by the meeting request email displayed on his Exchange ActiveSync client. The Exchange server then deletes the meeting request from his Inbox and changes the status of the placeholder Calendar item from tentative to busy. In addition, the Exchange ActiveSync client sends a meeting acceptance notification to the organizer. A copy of this message appears in Bob's Sent Items folder.


    The following figure shows the Exchange ActiveSync client meeting response process.

     


    clip_image004

    Figure 2:   Exchange ActiveSync client meeting response process


    Responding to meeting requests involves the following steps:

    1. The user, in this case Bob, accepts the meeting from his Exchange ActiveSync client by using the options exposed in the meeting request. Upon doing so, the following takes place:
      1. The server deletes the meeting request email message from his Inbox.
      2. The server deletes the tentative meeting from his Calendar and adds an accepted meeting in its place.

    Note:   If Bob's Exchange server is not configured to process incoming meeting requests automatically, a tentative meeting placeholder item does not appear on his Calendar. In this case, the server does not delete any Calendar item, and the MeetingResponse command cannot be sent from the Calendar folder; it can be used on the meeting request in the Inbox only.

    1. When Bob issues a Sync command on Calendar folder, the tentative meeting is deleted from the Calendar by the Exchange  server, and a new accepted meeting is added.

    Note:   If Bob syncs his Deleted Items folder, a copy of the original meeting item is added to that folder. (This step is not shown in Figure 2 and is not described in this blog post.)

    1. Bob's client sends an email message to the organizer that indicates his acceptance.
    2. The server adds a copy of the meeting acceptance email message in Bob's Sent Items folder. If Bob syncs his Sent Items folder, a copy of the notification will appear there.

     

     When the ResponseRequested element is set to 1, the Exchange ActiveSync client allows the user to act on the meeting request from both the Inbox and the Calendar item.

    Responding to meeting requests from the Inbox

    When the client displays a meeting request message in a user's Inbox, the user has the option to accept, tentatively accept, or decline the meeting invitation. After the user selects a response, the client sends a MeetingResponse command to the server.


    MeetingResponse command

    The following example shows a MeetingResponse command request.

    POST /Microsoft-Server-ActiveSync?Cmd=MeetingResponse&User=Bob&DeviceId=ABCDEF&DeviceType=SmartPhone HTTP/1.1

    Content-Type: application/vnd.ms-sync.wbxml

    MS-ASProtocolVersion: 14.1

    User-Agent: ASOM

    Host: mail.contoso.com

     

    <?xmlversion="1.0"encoding="utf-8"?>

    <MeetingResponsexmlns="MeetingResponse:">

      <Request>

        <UserResponse>1</UserResponse>

        <CollectionId>6</CollectionId>

        <RequestId>6:17</RequestId>

      </Request>

    </MeetingResponse>

     

     


    The RequestId element specifies the server ID of the meeting request in the Inbox collection. The UserResponse element can contain one of the values listed in the following table.


    UserResponse element value

    Invitee response

    Server action

    1

    Accepted

    The server deletes the corresponding Calendar entry and creates a new Calendar entry with the "Accepted" status.

    2

    Tentative

    The server deletes the corresponding Calendar entry and creates a new Calendar entry with the "TentativelyAccepted" status.

    3

    Declined

    The server deletes the corresponding Calendar entry.

     

    Server response to the MeetingResponse command

    After the MeetingResponse command has finished, the server automatically deletes the meeting request item from the Inbox. The following example shows the server response.

    HTTP/1.1 200 OK

    MS-Server-ActiveSync: 14.0

     

    <?xmlversion="1.0"encoding="utf-8" ?>

    <MeetingResponsexmlns="MeetingResponse:">

      <Result>

        <RequestId>6:17</RequestId>

        <Status>1</Status>

        <CalendarId>2:25</CalendarId>

      </Result>

    </MeetingResponse>

     

    The RequestId element specifies the meeting request that the client is responding to. If the meeting invitation is accepted or tentatively accepted, the server adds or updates the corresponding Calendar item and returns the item's server ID in the CalendarId element of the response.


    The following table lists the possible values for the Status element.


    Status element value

    Server response

    Client action

    1

    Success

    The request succeeded.

    2

    InvalidMeetingRequest

    This response indicates that the request is invalid. The client should not retry the request, as it is unlikely to succeed.

     

    The server sends this response if the item sent to the server is not a valid meeting.

    3

    ErrorOccurredOnMailbox

    This error is returned when client sync state is missing or corrupt on the server. The client can retry once right away, but should retry slowly after that, about once an hour. If the request still fails after an extended period, the client should stop retrying.

    4

    ErrorOccurredOnExchangeServer

    This error indicates that the meeting request can't be processed. The meeting request may be missing, the meeting may have been canceled, or this may be a delegate meeting to which the user can't respond. If the client retries the request, it is unlikely to succeed.

     


    Note:   The Exchange ActiveSync client should handle the response to the MeetingResponse command in the same way that it handles the status responses to email commands.


    When an invitee responds from the Inbox item, the Exchange server deletes the meeting invitation from the Inbox. The invitee can, however, change their response to the meeting request from the Calendar item with new MeetingResponse command. If the user declines the meeting, the server deletes the Calendar item, and it can no longer be used to respond to the meeting request.


    The Exchange server automatically deletes the email invitation from the Inbox after the user has responded to the request. When the Exchange ActiveSync client syncs the Deleted Items folder, the deleted item is automatically added to the Deleted Items folder on the client.


    Responding to meeting requests from the Calendar folder

    Users respond to a meeting request from the Calendar folder in the same way that they respond to the request from the Inbox. The client uses the MeetingResponse command, but in this case, the RequestId element value indicates the Calendar item. This option is only available in Exchange ActiveSync version 14.0 and later versions. Just like when the user responds from the Inbox, the meeting request item in the Inbox is automatically deleted by the server when the user responds from the Calendar item.


    Replacing the placeholder Calendar item with a new item

    When the user responds to the meeting request, the original tentative Calendar item is deleted. If the user declines the meeting request, the server does not add a new item to the Calendar. If the useraccepts or tentatively accepts the meeting request, the server creates a new Calendar item with the status as indicated by the user. The following example shows the sync process for the Calendar collection, after the user has accepted the meeting request. The original meeting item is deleted, and new item with a status of Accepted is added in its place. The UID element value of the new accepted item is identical to the value of the tentative placeholder item.

    HTTP/1.1 200 OK

    Content-Type: application/vnd.ms-sync.wbxml

     

    <?xmlversion="1.0"encoding="utf-8"?>

    <Sync>

      <Collections>

        <Collection>

          <SyncKey>1598194209</SyncKey>

          <CollectionId>2</CollectionId>

          <Status>1</Status>

          <Commands>

            <Add>

              <ServerId>2:25</ServerId>

              <ApplicationData>

                <calendar:TimeZone>4AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

                  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAA

                  IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

                  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAA

                  AAAAAAxP///w==</calendar:TimeZone>

                <calendar:DtStamp>20110510T185139Z</calendar:DtStamp>

                <calendar:StartTime>20110510T170000Z</calendar:StartTime>

                <calendar:Subject>Quarterly Planning</calendar:Subject>

                <calendar:UID>A3561BDAAE8E4B30AC255FD3F31A3AD7000000000000000000000

                  00000000000</calendar:UID>

                <calendar:OrganizerName>Alice </calendar:OrganizerName>

                <calendar:OrganizerEmail>alice@contoso.com</calendar:OrganizerEmail>

                <calendar:Attendees>

                  <calendar:Attendee>

                    <calendar:Email>bob@contoso.com</calendar:Email>

                    <calendar:Name>Bob </calendar:Name>

                    <calendar:AttendeeType>1</calendar:AttendeeType>

                  </calendar:Attendee>

                </calendar:Attendees>

                <calendar:Location>Office</calendar:Location>

                <calendar:EndTime>20110510T180000Z</calendar:EndTime>

                <airsyncbase:Body>

                  <airsyncbase:Type>1</airsyncbase:Type>

                  <airsyncbase:EstimatedDataSize>127</airsyncbase:EstimatedDataSize>

                  <airsyncbase:Truncated>1</airsyncbase:Truncated>

                </airsyncbase:Body>

                <calendar:Sensitivity>0</calendar:Sensitivity>

                <calendar:BusyStatus>2</calendar:BusyStatus>

                <calendar:AllDayEvent>0</calendar:AllDayEvent>

                <calendar:Reminder>15</calendar:Reminder>

                <calendar:MeetingStatus>3</calendar:MeetingStatus>

                <airsyncbase:NativeBodyType>3</airsyncbase:NativeBodyType>

                <calendar:ResponseRequested>1</calendar:ResponseRequested>

                <calendar:AppointmentReplyTime>20110506T165252Z</AppointmentReplyTime>

                <calendar:ResponseType>3</calendar:ResponseType>

              </ApplicationData>

            </Add>

            <Delete>

              <ServerId>2:24</ServerId>

            </Delete>

         </Commands>

        </Collection>

      </Collections>

    </Sync>

     

    The client has to sync the Calendar folder after the user accepts or tentatively accepts a meeting request in order for the new Calendar item to appear on the user's Calendar.


    Deleting the Calendar item when the meeting is declined

    If the user declines the meeting, the Exchange server automatically deletes the corresponding Calendar item. The client must not delete the Calendar item on behalf of the user.


    When a user declines a meeting request, the response does not contain a meetingresponse:CalendarId element because the server deletes the corresponding Calendar item.


    Sending response notifications

    The client sends a notification to the meeting organizer if the user chooses to send a response. The client uses the SendMail command to send the notification. The client should send the email notification only after the MeetingResponse command finishes successfully; otherwise, the invitee's Calendar and the status information that the invitee reports to the organizer will be in conflict. If the ResponseRequested element is set to 0 (false) on the meeting request, the client does not expose an option to the user to send a response notification to the organizer.


    The client indicates its response in the subject of the email message, as well by using an iCalendar reply command, as shown in the following example.


    POST /Microsoft-Server-ActiveSync?Cmd=SendMail&User=Bob&DeviceId=ABCDEF&DeviceType=SmartPhone HTTP/1.1

    Content-Type: application/vnd.ms-sync.wbxml

    MS-ASProtocolVersion: 14.0

    Host: mail.contoso.com

     

    <?xmlversion="1.0"encoding="utf-8" ?>

    <SendMailxmlns="ComposeMail:">

      <ClientId>13554</ClientId>

      <SaveInSentItems/>

      <Mime>

        Subject: Accepted: Quarterly Planning

        From: Bob@contoso.com

        Content-Type: multipart/alternative;

        boundary=NextPart

        To: Alice  <Alice@contoso.com>

     

    --NextPart

    Content-Type: text/plain;

                        charset=us-ascii

    Sure, I will be there!

     

    --NextPart

    Content-Type: text/calendar;

                        charset=utf-8;

                        name=meeting.ics;

                        method=REPLY

    Content-Transfer-Encoding: quoted-printable

     

    BEGIN:VCALENDAR…<more iCalendar content follows>

     

    </Mime>

    </SendMail>

     

    The following table lists the possible response types.


    Response type

    Email /subject

    iCalendar reply method

    Accepted

    Accepted: <meeting request subject>

    ATTENDEE;PARTSTAT=ACCEPTED:MAILTO:<organizer>

    TenativelyAccepted

    Tenative: <meeting request subject>

    ATTENDEE;PARTSTAT=TENTATIVE:MAILTO:<organizer>

    Declined

    Declined: <meeting request subject>

    ATTENDEE;PARTSTAT=DECLINED:MAILTO:<organizer>

     


    Meeting updates

    If the organizer makes updates to the meeting, the Exchange ActiveSync client might receive multiple meeting notification email messages. All mail items that are related to the same meeting have the same GlobalObjId element value (for the email notification) and the same UID element value (for the Calendar item). If the Exchange ActiveSync client receives multiple updates that share the same ID, it is important for the client to enable the user to respond to the most recent item only based on the DtStamp value.


    Scenario 2: Organizer uses an Exchange ActiveSync client to verify the meeting response status

    After the invitees have responded to the meeting request, the organizer might want to determine the status of the responses. The organizer can view the responses in the Inbox as they arrive from individual invitees. In addition, the Exchange server automatically parses the invitee responses and updates the Calendar item accordingly. The organizer can view the response status on the Calendar item based on updates from the server to the Exchange ActiveSync client.


    Syncing meeting responses in the organizer's Inbox

    As invitees respond to the meeting request, the organizer's Exchange ActiveSync client runs a Sync command on the Inbox folder to discover the responses, as shown in the following example.

     

    HTTP/1.1 200 OK

    Content-Type: application/vnd.ms-sync.wbxml

     

    <?xmlversion="1.0"encoding="utf-8"?>

    <Sync>

      <Collections>

        <Collection>

          <SyncKey>378940377</SyncKey>

          <CollectionId>6</CollectionId>

          <Status>1</Status>

          <Commands>

            <Add>

              <ServerId>6:22</ServerId>

              <ApplicationData>

                <email:To>"Alice" &lt;alice@contoso.com&gt;</email:To>

                <email:From>"Bob" &lt;bob@contoso.com&gt;</email:From>

                <email:Subject>Accepted: Quarterly Planning</email:Subject>

                <email:DateReceived>20110506T165454Z</email:DateReceived>

                <email:DisplayTo>Alice </email:DisplayTo>

                <email:ThreadTopic>Quarterly Planning</email:ThreadTopic>

                <email:Importance>1</email:Importance>

                <email:Read>0</email:Read>

                <airsyncbase:Body>

                  <airsyncbase:Type>1</airsyncbase:Type>

                  <airsyncbase:EstimatedDataSize>0</airsyncbase:EstimatedDataSize>

                  <airsyncbase:Truncated>1</airsyncbase:Truncated>

                </airsyncbase:Body>

                <email:MessageClass>IPM.Schedule.Meeting.Resp.Pos</email:MessageClass>

                <email:MeetingRequest>

                  <email:AllDayEvent>0</email:AllDayEvent>

                  <email:StartTime>20110510T17000000Z</email:StartTime>

                  <email:DtStamp>20110506T165252Z </email:DtStamp>

                  <email:EndTime>20110510T180000Z</email:EndTime>

                  <email:InstanceType>0</email:InstanceType>

                  <email:Location>Office</email:Location>

                  <email:Organizer>"Bob " &lt;bob@contoso.com&gt;</email:Organizer>

                  <email:Sensitivity>0</email:Sensitivity>

                  <email:TimeZone>4AEAACgAVQBUAEMALQAwADgAOgAwADAAKQAgAFAAYQBjAGkAZgBpAGM

                     AIABUAGkAbQBlACAAKABVAFMAIAAmACAAQwAAAAsAAAABAAIAAAAAAAAAAAAAACgAV

                     QBUAEMALQAwADgAOgAwADAAKQAgAFAAYQBjAGkAZgBpAGMAIABUAGkAbQBlACAAKABVAF

                     MAIAAmACAAQwAAAAMAAAACAAIAAAAAAAAAxP///w==</email:TimeZone>

                  <email:GlobalObjId> BAAAAIIA4AB0xbcQGoLgCAAAAAAAAAAAAAAAAAAAAAAAAAAATQAAAHZD

                     YWwtVWlkAQAAAEEzNTYxQkRBQUU4RTRCMzBBQzI1NUZEM0YzMUEzQUQ3MDAwMDAwMDA

                     wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAA</email:GlobalObjId>

                </email:MeetingRequest>

                <email:InternetCPID>20127</email:InternetCPID>

                <email:Flag />

                <email:ContentClass>urn:content-classes:calendarmessage</email:ContentClass>

                <airsyncbase:NativeBodyType>1</airsyncbase:NativeBodyType>

                <email2:ConversationId>(Uí©E¯*O»&#x12;F               n                 &#x2;Ô</email2:ConversationId>

                <email2:ConversationIndex>Ì&#x10;1ë¯&#x0;&#x0;&#x1A;4E</email2:ConversationIndex>

                <email:Categories />

              </ApplicationData>

            </Add>

          </Commands>

        </Collection>

      </Collections>

    </Sync>

     


    Note that the ApplicationData container of the response that is synced to the organizer's Inbox contains To and From fields however, the values of these elements are different than the values in the original meeting request. In the response message, the To field indicates the organizer, because the organizer is the recipient of the response, while the From field indicates the invitee.


    The MessageClass and Subject elements indicate the invitee's response to the request, as set by the client. The following are the possible values for the MessageClass element:


    ·        IPM.Schedule.Meeting.Resp.Pos

    ·        IPM.Schedule.Meeting.Resp.Tent

    ·        IPM.Schedule.Meeting.Resp.Neg.


    Important:   The organizer's Exchange ActiveSync client must sync the Calendar folder in order to receive the meeting responses from meeting invitees. The organizer's mailbox uses the Calendar item to reconcile responses to a meeting request with the Calendar event.


    Updating the organizer's Calendar item to reflect invitee responses

    When the Exchange ActiveSync client syncs the organizer's Calendar folder, the original meeting item is updated to reflect any new or updated invitee responses. The client can then display the invitee status to the organizer. The following example shows a change in an attendee, Bob's, status after he accepts the meeting invitation. Note that the Calendar item shows a value of 3 for the AttendeeStatus element, rather than 0, which was the value when the request was created and before a response was received.


     

    HTTP/1.1 200 OK

    Content-Type: application/vnd.ms-sync.wbxml

     

    <?xmlversion="1.0"encoding="utf-8"?>

    <Sync>

      <Collections>

        <Collection>

          <SyncKey>124536913</SyncKey>

          <CollectionId>2</CollectionId>

          <Status>1</Status>

          <Commands>

            <Change>

              <ServerId>2:9</ServerId>

              <ApplicationData>

                <calendar:Attendees>

                  <calendar:Attendee>

                    <calendar:Email>bob@contoso.com</calendar:Email>

                    <calendar:Name>Bob </calendar:Name>

                    <calendar:AttendeeStatus>3</calendar:AttendeeStatus>

                    <calendar:AttendeeType>1</calendar:AttendeeType>

                  </calendar:Attendee>

                </calendar:Attendees>

              </ApplicationData>

            </Change>

          </Commands>

        </Collection>

      </Collections>

    </Sync>

     

    The following table lists the possible values for the AttendeeStatus element.


    AttendeeStatus element value

    Meaning

    0

    No response

    2

    Tentative

    3

    Accept

    4

    Decline

    5

    Other

     


    When the organizer creates the meeting request, the AttendeeStatus element is set to 0 because no invitees have yet responded. As the response notifications arrive, the organizer’s Exchange server interprets the iCalendar content in the response messages and updates the AttendeeStatus value for each attendee accordingly. An AttendeeStatus value of 5 indicates a problem with interpreting the invitee response.  


    Exchange ActiveSync does not handle responses involving new time proposals. New time proposals appear as tentative or decline responses to the Exchange ActiveSync client. The new time proposal may be indicated in the subject line or the body of the message, depending on the client that the invitee uses to send the proposal.


    Note:  After an invitee responds to a request, the Exchange server deletes the meeting request from the invitee's mailbox. This helps to ensure that the invitee does not send multiple responses to the same meeting request that might conflict with one another. If the invitee does send multiple responses to the meeting request (for example, by responding from the Calendar item rather than the meeting invitation), the Exchange server automatically updates the organizer's Calendar item to reflect the most recent meeting response status.


    Summary

    The ability to respond to meeting requests is a critical element of a successful calendaring experience for Exchange ActiveSync client users. When you develop your Exchange ActiveSync client applications, make sure that you handle iCalendar meeting responses correctly. Keep in mind that your applications should not process incoming iCalendar meeting requests on the client; meeting requests should be processed by the Exchange server.  


    Additional Resources

    [MS-ASEMAIL]: ActiveSync Email Class Protocol Specification

    [MS-ASCAL]: ActiveSync Calendar Class Protocol Specification

    [MS-ASCMD]: ActiveSync Email Command Reference Protocol Specification

    [MS-ASDTYPE]: ActiveSync Data Types

    [MS-OXGLOS]: Exchange Server Protocols Master Glossary

    [MS-OXCICAL]: iCalendar to Appointment Object Conversion Protocol Specification

     

    Post authored by: Katarzyna Puchala, Microsoft Corporation

    Provisioning, Policies, Remote Wipe, and ABQ in Exchange ActiveSync

    $
    0
    0

    This post is part of an ongoing series that covers Microsoft Exchange ActiveSync for developers.

    Microsoft Exchange ActiveSync policies are the primary tool by which IT administrators can manage devices that connect to Microsoft Exchange mailboxes. Administrators can create policy settings to manage security settings such as PIN length, data encryption, and so on. Policies define the terms by which a client can synchronize mailbox data. The provisioning process is a communication that occurs between the client and server that indicates whether the client can enforces the required policies.

    In addition to policies, Microsoft Exchange Server 2010 introduces another tool for administrators, known as Allow/Block/Quarantine (ABQ). ABQ enables administrators to control which devices or families of devices can synchronize data with Exchange ActiveSync. Administrators can also use ABQ to block certain devices or all unknown devices from synchronizing data.

    Both ABQ and policies help administrators control how and whether data is synchronized onto a device. Remote Wipe is another Exchange ActiveSync feature that is used to remove data froma device. This feature is important when, for example, individuals leave the company, or a device is lost or stolen.

    If you are creating an enterprise-class Exchange ActiveSync client, it is important for you to understand and support provisioning and policies, ABQ, and remote wipe. This post provides the information you need to know about these features, in the following sections:

    • Provisioning
    • Policies
    • Remote wipe
    • ABQ

     

    Note

     

    The following information, covered in this blog post, is important for the Exchange ActiveSync Logo Program:

    ·        Device manufacturer and model information

    ·        Password-related policies

    ·        MaxInactivityTimeDeviceLock policy

    ·        MaxDevicePasswordFailedAttempts policy

    ·        Remote Wipe

     

    For more information about the logo program, see Exchange ActiveSync Logo Program on Microsoft TechNet.

    Provisioning

    The client’s goal in provisioning is to obtain a policy key from the Exchange server. This policy key enables the client to synchronize with a mailbox. Provisioning involves the following steps:

    • The client sends information to the server to identify itself.
    • The server sends security policies to the client that the client must enforce.
    • The client indicates whether it is able to enforce the security policies.
    • If the policies are applied successfully, the client is given a policy key that it then submits with subsequent requests to synchronize the mailbox.

    For a detailed description of this process, see [MS-ASPROV]: ActiveSync Provisioning Protocol Specification section 3.1.5.1.

    The following figure shows the two-step provisioning process.

    clip_image002

    Figure 1: Two-step provisioning process

    Provisioning step 1: policy exchange between client and server

    The policy exchange process involves a client Provision command request and a server Provision command response.

    Client provisioning request

    In its first request to the Exchange server, the client sends a Provision command request, as shown in the following example.

    POST /Microsoft-Server-ActiveSync?User=deviceuser&DeviceId=6F24CAD599A5BF1A690246B8C68FAE8D&DeviceType=PocketPC&Cmd=Provision HTTP/1.1

    Accept-Language: en-us

    MS-ASProtocolVersion: 14.0

    Content-Type: application/vnd.ms-sync.wbxml

    X-MS-PolicyKey: 0

    User-Agent: ASOM

    Host: EXCH-B-003

     

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

    <Provision xmlns="Provision:" xmlns:settings="Settings:">

        <settings:DeviceInformation>

            <settings:Set>

                <settings:Model>… </settings:Model>

                <settings:IMEI>...</settings:IMEI>

                <settings:FriendlyName>...</settings:FriendlyName>

                <settings:OS>...</settings:OS>

                <settings:OSLanguage>...</settings:OSLanguage>

                <settings:PhoneNumber>...</settings:PhoneNumber>

                <settings:MobileOperator>...</settings:MobileOperator>

                <settings:UserAgent>...</settings:UserAgent>

            </settings:Set>

        </settings:DeviceInformation>

         <Policies>

              <Policy>

                   <PolicyType>MS-EAS-Provisioning-WBXML</PolicyType>

              </Policy>

         </Policies>

    </Provision>

    The client Provision command request includes information contained within two parent elements:

    • settings:DeviceInformation element
    • Policieselement

    I will discuss the settings.DeviceInformation element in more detail in the "ABQ" section later in this post.

    In the Policies element section, the client indicates in the PolicyType element the format of the policy information that the client wants the server to use. The client should always send the “MS-EAS-Provisioning-WBXML” value, as described in [MS-ASPROV] section 2.2.2.42.

    Provisioning request for different Exchange ActiveSync protocol versions

    The use of the settings:DeviceInformation element in the provisioning request varies based on the version of the Exchange ActiveSync protocol the client is using, as described in the following table.

     

    Exchange ActiveSync protocol version

    Provision command request

    Exchange ActiveSync version 12.1

    The client should not include a settings:DeviceInformation element because this element is not supported.

    Exchange ActiveSync version 14.0

    The settings:DeviceInformation element is optional.  However, in order to support ABQ, the client must submit the DeviceInformation element with the Provision command request or with a Settings command request, as described in [MS-ASCMD]: ActiveSync Command Reference Protocol Specification section 2.2.3.43.

    Exchange ActiveSync version 14.1

    The settings:DeviceInformation element is required. The settings:Set child element is also required and must contain the Model child element.

    For more information about the differences between Exchange ActiveSync protocol versions in client provisioning requests, see [MS-ASPROV] section 6.

    Server provisioning response

    The following example shows a server response to a client provisioning request.

    Note: The policies listed in this example do not represent all the possible policies thatthe server might send. For a complete list of policies, see [MS-ASPROV] section 2.2.2.

    HTTP/1.1 200 OK

    Connection: Keep-Alive

    Content-Length: 1069

    Date: Mon, 01 May 2006 20:15:15 GMT

    Content-Type: application/vnd.ms-sync.wbxml

    Server: Microsoft-IIS/6.0

    X-Powered-By: ASP.NET

    X-AspNet-Version: 2.0.50727

    MS-Server-ActiveSync: 8.0

    Cache-Control: private

     

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

    <Provision xmlns:A0="AirSync:" xmlns:A1="POOMCONTACTS:" xmlns:A2="POOMMAIL:" xmlns:A3="AirNotify:" xmlns:A4="POOMCAL:" xmlns:A5="Move:" xmlns:A6="GetItemEstimate:" xmlns:A7="FolderHierarchy:" xmlns:A8="MeetingResponse:" xmlns:A9="POOMTASKS:" xmlns:A10="ResolveRecipients:" xmlns:A11="ValidateCert:" xmlns:A12="POOMCONTACTS2:" xmlns:A13="Ping:" xmlns:A15="Search:" xmlns:A16="Gal:" xmlns:A17="AirSyncBase:" xmlns:A18="Settings:" xmlns:A19="DocumentLibrary:" xmlns:A20="ItemOperations:" xmlns:A21="ComposeMail:" xmlns:A22="POOMMAIL2:" xmlns:A23="Notes:" xmlns:A24="RightsManagement:" xmlns="Provision:">

      <Status>1 Success</Status>

      <Policies>

        <Policy>

          <PolicyType>MS-EAS-Provisioning-WBXML</PolicyType>

          <Status>1 Success</Status>

          <PolicyKey>2488355417</PolicyKey>

          <Data>

            <eas-provisioningdoc>

              <DevicePasswordEnabled>1</DevicePasswordEnabled>

              <AlphanumericDevicePasswordRequired>0</AlphanumericDevicePasswordRequired>

              <PasswordRecoveryEnabled>0</PasswordRecoveryEnabled>

              <RequireStorageCardEncryption>0</RequireStorageCardEncryption>

              <AttachmentsEnabled>1</AttachmentsEnabled>

              <MinDevicePasswordLength>4</MinDevicePasswordLength>

              <MaxInactivityTimeDeviceLock>900</MaxInactivityTimeDeviceLock>

              <MaxDevicePasswordFailedAttempts>8</MaxDevicePasswordFailedAttempts>

              <MaxAttachmentSize/>

              <AllowSimpleDevicePassword>1</AllowSimpleDevicePassword>

              <DevicePasswordExpiration/>

              <DevicePasswordHistory>0</DevicePasswordHistory>

              <AllowStorageCard>1</AllowStorageCard>

              <AllowCamera>1</AllowCamera>

              <RequireDeviceEncryption>0</RequireDeviceEncryption>

              <AllowUnsignedApplications>1</AllowUnsignedApplications>

              <AllowUnsignedInstallationPackages>1</AllowUnsignedInstallationPackages>

              <MinDevicePasswordComplexCharacters>1</MinDevicePasswordComplexCharacters>

              <AllowWiFi>1</AllowWiFi>

              <AllowTextMessaging>1</AllowTextMessaging>

              <AllowPOPIMAPEmail>1</AllowPOPIMAPEmail>

              <AllowBluetooth>2</AllowBluetooth>

              <AllowIrDA>1</AllowIrDA>

              <RequireManualSyncWhenRoaming>0</RequireManualSyncWhenRoaming>

              <AllowDesktopSync>1</AllowDesktopSync>

              <MaxCalendarAgeFilter>0</MaxCalendarAgeFilter>

              <AllowHTMLEmail>1</AllowHTMLEmail>

              <MaxEmailAgeFilter>0</MaxEmailAgeFilter>

              <MaxEmailBodyTruncationSize>-1</MaxEmailBodyTruncationSize>

              <MaxEmailHTMLBodyTruncationSize>-1</MaxEmailHTMLBodyTruncationSize>

              <RequireSignedSMIMEMessages>0</RequireSignedSMIMEMessages>

              <RequireEncryptedSMIMEMessages>0</RequireEncryptedSMIMEMessages>

              <RequireSignedSMIMEAlgorithm>0</RequireSignedSMIMEAlgorithm>

              <RequireEncryptionSMIMEAlgorithm>0</RequireEncryptionSMIMEAlgorithm>

              <AllowSMIMEEncryptionAlgorithmNegotiation>2</AllowSMIMEEncryptionAlgorithmNegotiation>

              <AllowSMIMESoftCerts>1</AllowSMIMESoftCerts>

              <AllowBrowser>1</AllowBrowser>

              <AllowConsumerEmail>1</AllowConsumerEmail>

              <AllowRemoteDesktop>1</AllowRemoteDesktop>

              <AllowInternetSharing>1</AllowInternetSharing>

              <UnapprovedInROMApplicationList/>

              <ApprovedApplicationList/>

            </eas-provisioningdoc>

          </Data>

        </Policy>

      </Policies>

    </Provision>

    The response includes the following:

    • A PolicyKey element, which contains a policy key that the client should retain and submit to the server with its next request.
    • A Data element and its child elements, which contain the policy settings that the server requires the client to apply. For more information about individual policy settings, see "Policies" later in this blog post.

    Notice that the response contains two Status elements. The first Status element is a child of the Provision element and indicates the general status of the Exchange server’s ability to process the client’s request. The following table lists the possible values for the first Status element.

     

    Status element value

    Meaning

    Description

    1

    Success

    The Policies element contains the information about the security policies.

    2

    Protocol error

    The request was malformed.

    3

    General server error

    A transient error occurred. The client should retry the request over a period of time.

    The second Status element is a child of the Policy element and indicates whether the policy settings were applied correctly. The following table lists the possible values for the Status element.

     

    Status element value

    Meaning

    Description

    1

    Success

    The Data element contains the policy settings to apply.

    2

    No policy

    The server doesn't have a policy. The device doesn't need to submit a second request; it can proceed to sync data.

    3

    Unknown policy type

    The device sent an invalid value for the PolicyType element. The only valid value for the PolicyType element is “MS-EAS-Provisioning-WBXML”.

    4

    Policy data is corrupt

    The policy data on the server is corrupt. The device should suggest that the user contact the administrator.

    5

    Policy key mismatch

    The policy key sent in the last request does not match the key stored on the server. Either the device sent the wrong policy key or the policy changed on the server since the first response. The device should re-initiate the provisioning process from the beginning.

     

    Provisioning step 2: client acknowledges and applies policies

    At this point, the server relies on the client to apply the policies as requested. After applying the security policy settings, the client sends another Provision command request to the server to acknowledge the policies and indicate its ability to apply them on the device.

    The following example shows the second Provision request that the client sends to the server.

    POST /Microsoft-Server-ActiveSync?User=deviceuser&DeviceId=6F24CAD599A5BF1A690246B8C68FAE8D&DeviceType=PocketPC&Cmd=Provision HTTP/1.1

    Accept-Language: en-us

    MS-ASProtocolVersion: 14.0

    Content-Type: application/vnd.ms-sync.wbxml

    X-MS-PolicyKey: 1307199584

    User-Agent: ASOM

    Host: EXCH-B-003

     

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

    <Provision xmlns="Provision:">

         <Policies>

              <Policy>

                   <PolicyType>MS-EAS-Provisioning-WBXML</PolicyType>

     <PolicyKey>1307199584</PolicyKey>

                   <Status>1</Status>

              </Policy>

         </Policies>

    </Provision>

    This request contains the policy key value that the server sent to the client in step 1. It also contains a Status element that indicates whether the client was able to apply the policy settings. The following table lists the possible values of the Status element.

     

    Status element value

    Meaning

    Description

    1

    Success

    The client was able to apply all the policy settings.

    2

    Partial success

    The client was able to apply some of the policy settings but failed to apply others.

    3

    Failure

    The client was not able to apply any of the policy settings.

    4

    Externally managed

    The client was provisioned by a third party.

    Note: If a Microsoft Exchange administrator sets the "Allow non-provisionable devices" option in the Exchange ActiveSync policy, the server will allow all clients to synchronize mailbox data regardless of whether the client asked for policy settings or applied them successfully. However, if the administrator chooses to disable the "Allow non-provisionable devices" option, only clients that respond with "Success" are allowed to connect to the mailbox.

    Important:   When the client indicates "partial success" in its second request to the server, this means that the client failed to apply at least one of the security policies that the server returned in its initial response. Note, however, that there is a distinction between policies that are not relevant to the device and policies that the device was not able to apply. The policies that “allow” and “disallow” certain features of the device do not have to be applied if they are not relevant to the device in order for the client to indicate "success" in its request. For example, if the device does not support Bluetooth, the client can safely ignore the AllowBluetooth policy and report back “success” instead of “partial success”. Conversely, if AllowBluetooth is set to false and the device supports Bluetooth but cannot disable it, the device can return “partial success”.

    For any policy that requires a certain feature, the client must not return success if the policy cannot be applied. For example, the client should only indicate "success" for the RequireDeviceEncryption policy when the client supports device encryption. If the device doesn’t support encryption, the client should indicate "partial success" or "failure", depending on the status of the other policies. For more information about specific policies, see "Policies" later in this blog post.

    Note: If the DevicePasswordEnabled policy is set to true, and the device is not able to enforce the password, it must return "failure" in response to the Provision command, regardless of whether it can enforce any other policy. The client can return "partial success" if it cannot enforce any other policies. For example, if the client enabled a password but failed to encrypt the device, it can return "partial success" rather than "failure".

    The following example shows the server's response to the second client Provision request.

    HTTP/1.1 200 OK

    Connection: Keep-Alive

    Content-Length: 63

    Date: Mon, 01 May 2006 20:15:17 GMT

    Content-Type: application/vnd.ms-sync.wbxml

    Server: Microsoft-IIS/6.0

    X-Powered-By: ASP.NET

    X-AspNet-Version: 2.0.50727

    MS-Server-ActiveSync: 8.0

    Cache-Control: private

     

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

    <Provision xmlns="Provision:">

         <Status>1</Status>

         <Policies>

              <Policy>

                   <PolicyType> MS-EAS-Provisioning-WBXML </PolicyType>

                   <Status>1</Status>

                   <PolicyKey>3942919513</PolicyKey>

              </Policy>

         </Policies>

    </Provision>

    This response does not include a Data element that contains the list of policy settings. The server simply responds with a Status element (the values for which are listed in the "Server provisioning response" section) and a new policy key. This new policy key is the permanent key that the client should save and resubmit when it sends subsequent requests to the server.

    Client handling of the policy key

    The policy key represents the current security policy settings that are applied on the client. It can be up to 64 characters long and can contain any of the characters that are allowed in an HTTP header. The client should retain only the latest policy key that it has received from the server and submit it with all requests.

    Note: Submitting the policy key is optional the Ping command and the HTTP OPTIONS commands.

    The following example shows a client request that includes the policy key.

    POST /Microsoft-Server-ActiveSync?User=deviceuser&DeviceId=6F24CAD599A5BF1A690246B8C68FAE8D&DeviceType=PocketPC&Cmd=FolderSync HTTP/1.1

    Accept-Language: en-us

    MS-ASProtocolVersion: 14.0

    Content-Type: application/vnd.ms-sync.wbxml

    X-MS-PolicyKey: 3942919513

    User-Agent: ASOM

    Host: EXCH-B-003

     

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

    <FolderSync xmlns="FolderHierarchy:">

         <SyncKey>0</SyncKey>

    </FolderSync>

    When should a client provision?

    Clients should send a Provision command request when they first contact the server. In some scenarios, the server may require the client to provision again, after an initial provision sequence. The server indicates this by sending a 449 HTTP error response or a success response with one of the status codes listed in the following table in response to any client request. The client should immediately send a Provision command request after receiving one of these statuses in a response.

     

    Status code

    Name

    Description

    139

    DeviceNotFullyProvisionable

    The device uses a protocol version that cannot send all the policy settings the administrator enabled.  The client should retry its request once per hour to determine whether the policy has changed. 

    Important:   This is status code indicates a condition that will not be resolved until the administrator changes the policy. The client should display a warning that it cannot synchronize due to current policy settings and recommend that the user contact their administrator

    140

    RemoteWipeRequested

    The server requests that the client wipe all data. The client should send a Provision command request so that it can acknowledge the wipe request.

    141

    LegacyDeviceOnStrictPolicy

    The client is not capable of provisioning and the administrator has decided to make the policy a strict requirement. The client cannot synchronize until the policy changes. The client should retry once per hour to determine whether the policy has changed. 

    Important:   This is status indicates a condition that will not be resolved until the administrator changes the policy.  The client should display a warning that it cannot synchronize due to current policy settings and recommend that the user contact their administrator. 

    142

    DeviceNotProvisioned

    The client has not provisioned yet and must send a Provision command request immediately.

    143

    PolicyRefresh

    The server is configured to send the policy to the client every n hours and it is now time for the client to receive the policy again, regardless of whether the policy has changed. The client has to resend the Provision command request to obtain a new policy key.

    144

    InvalidPolicyKey

    The policy key sent by the client is no longer valid. This occurs when the policy is changed on the server (a new policy key is generated each time the policy changes). The client has to resend the Provision command request to get the new policy.

    145

    ExternallyManagedDevicesNotAllowed

    The client indicated that it was provisioned through another mechanism but the server is configured to require that the client have the server's policy applied. The client should retry once per hour to determine whether the policy has changed. 

    Important:   This status indicates a condition that will not be resolved until the administrator changes the policy.  The client should display a warning that it cannot synchronize due to current policy settings and recommend that the user contact their administrator. 

    In version 12.1 of the Exchange ActiveSync protocol, the server only sends an HTTP 449 response to inform the client that it needs to provision; it does not send the status codes listed in the previous table. Because this error response does not enable the client to distinguish between transient and potentially nontransient provisioning errors, the client should try to provision. If subsequent requests fail with additional HTTP 449 error respon ses, the client should suggest that the user contact their administrator. At that point, the client may choose to try to provision once per hour to determine whether the policy has changed.

    Important:   The client should compare existing device settings against policy updates to ensure that it is compliant with the updated policy. For example, if a password is set on the client, the client should compare the existing password (length, complexity, and so on) against the updated policy settings requested by the server. If the existing password does not conform to these updated policy settings or if the client cannot verify that the current password meets the requirements, the client should prompt the user to configure a new password.

    Policies

    Because it is up to the client to enforce policies, it is important to understand the effects that each policy will have on the device when applied. For a list of the elements that contain policy information, see [MS-ASPROV] section 2.2.2. This information will help you to determine acceptable values and expected results for each policy. For more information about policies in general, see Understanding Exchange ActiveSync Mailbox Policies on Microsoft TechNet.

    This section lists and describes some of the policies that are available; it does not provide a comprehensive list of all policies. For more information about policies, see [MS-ASPROV].

    The following table lists policies that clients can ignore and describes the conditions in which they can be ignored. If the conditions apply, the client can return "success" although the policy is not applied. Policies that are not listed in this table cannot be ignored under any conditions.

    Policy name

    Condition

    AllowBluetooth

    Ignored if the device does not support Bluetooth.

    AllowCamera

    Ignored if the device does not have a camera and a camera cannot be attached to the device.

    AllowDesktopSync

    Ignored if the device does not support connecting to a personal computer.

    AllowInternetSharing

    Ignored if the device does not support sharing its Internet connection with other devices.

    AllowIrDA

    Ignored if the device cannot transmit or receive infrared signals.

    AllowRemoteDesktop

    Ignored if the device does not support connecting remotely to a personal computer.

    AllowStorageCard

    Ignored if the device does not support storing data on removable storage.

    AllowTextMessaging

    Ignored if the device is not capable of using SMS messaging.

    AllowWifi

    Ignored if the device does not have Wi-Fi capability.

    PasswordRecoveryEnabled

    Ignored if the DevicePasswordEnabled element is set to FALSE (0) or if the client does not support recovery passwords.

    RequireStorageCardEncryption

    Ignored if the device does not support removable storage. If the device supports removable storage, it must reply to this policy request based on whether it is able to encrypt the storage card.

    AllowSimpleDevicePassword,

    AlphanumericDevicePasswordRequired,

    DevicePasswordExpiration,

    DevicePasswordHistory,

    MinDevicePasswordComplexCharacters,

    MaxDevicePasswordFailedAttempts,

    MinDevicePasswordLength,

    PasswordRecoveryEnabled

    Ignored if the value of the DevicePasswordEnabled element is FALSE (0).

    In addition, the MinDevicePasswordComplexCharacters policy can safely be ignored if the AlphanumericDevicePasswordRequired policy is set to false.

    The following table lists additional policies and describes the expected behavior:

    Policy name

    Expected behavior

    AllowSimpleDevicePassword

    The server does not define a simple password. In general, simple passwords can include sequential digits (1234), repeating digits (1111), letters in keyboard order (qwerty), and so on.

    AlphanumericDevicePasswordRequired

    If the device can only enforce a numeric PIN, the client must fail to apply this policy if it is enabled.

    DeviceEncryptionEnabled

    The client should encrypt any data received from the server, including email messages, contacts, attachments, and so on. The client is not required to encrypt other data, such as photos or music.

    DevicePasswordEnabled

    If this policy is enabled, the client must require that the user enter a password before accessing any data obtained from the server, including email messages, contacts, attachments, and so on.

    MaxDevicePasswordFailedAttempts

    Specifies the number of consecutive attempts a user can make to enter the correct password for the device. After this number of attempts, the device must wipe all data obtained from the server. The device can (and should) implement a mechanism to prevent accidental button presses from causing a device wipe.

    MaxEmailBodyTruncationSize

    Specifies the maximum size at which to truncate email messages when synchronized to the client. The value is in kilobytes (KBs). The client must not allow the user to choose a value larger than this setting. This value does not restrict the size of items returned by the ItemOperations command. The device can download the full items.

    MaxEmailHTMLBodyTruncationSize

    Specifies the maximum size at which to truncate HTML email messages when synchronized to the client. The value is in KBs. The device must not allow the user to choose a value larger than this setting. This value does not restrict the size of items returned by the ItemOperations command. The device can download the full items.

    MaxInactivityTimeDeviceLock

    Specifies the length of time (in seconds) that the device can be inactive before the password is required to reactivate it. The user can choose a value that is smaller than this, but cannot choose a value that is larger.

    PasswordRecoveryEnabled

    A recovery password is a second password that can be used to unlock the device if the user forgets their original password. When the user enters the recovery password, the client should prompt the user to create a new password immediately. The client should then create a new recovery password and send it to the server by using the Settings command as soon as possible.

    This is not technically a policy, because the client can still synchronize even if the device does not send a recovery password to the server. The purpose of this setting is to indicate to the client whether the server is willing to store a recovery password for the client. If the value for this policy is zero, the client should not send a recovery password to the server.

     

    Remote Wipe

    The remote wipe process enables administrators to request that the client erase all data from a device. Remote wipe is used in scenarios in which a device is lost or stolen or when a user has left the company or no longer has permission to synchronize corporate data. Administrators can use the Exchange Management Shell or the Exchange Management Console (EMC) to request a remote wipe. For more information, see Understanding Remote Device Wipe on Microsoft TechNet.

    After an administrator requests a remote wipe, the next time the client sends a request to the server, the server will respond with status code 140, RemoteWipeRequested. The client should then submit a Provision command request. If the server's response contains a RemoteWipe element, the client should send an acknowledgement that it is about to wipe the device first. Because the wipe will erase all data from memory and storage, the client sends the acknowledgement first because it will not have the information it needs to send requests after it wipes the device. For examples of the requests and responses that are sent during the remote wipe process, see [MS-ASPROV] section 4.2.

    Note:   In version 12.1 of the Exchange ActiveSync protocol, the server sends an HTTP 449 response instead of the 140 status code to request that the client send a Provision command to which the server will respond with a RemoteWipe element.

    The following is an example of a server response to a Provision command request that includes a RemoteWipe element.

    Content-Type: application/vnd.ms-sync.wbxml

    Date: Wed, 25 Mar 2009 01:23:58 GMT

    Content-Length: 14

     

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

    <Provision>

    <Status>1</Status>

    <RemoteWipe />

    </Provision>

    The following example shows a Provision command request from the client that contains the remote wipe status.

    POST /Microsoft-Server-ActiveSync?Cmd=Provision&User=T0SyncUser1v14.0&DeviceId=Device1&DeviceType=PocketPC HTTP/1.1

    Content-Type: application/vnd.ms-sync.wbxml

    MS-ASProtocolVersion: 14.0

    X-MS-PolicyKey: 0

    User-Agent: ASOM

    Host: EXCH-B-003

     

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

    <Provision xmlns="Provision:">

        <RemoteWipe>

            <Status>1</Status>

        </RemoteWipe>

    </Provision>

    The client should include one of the following values in the Status element:

    • 1 (Success) — Indicates that the client will wipe the device shortly after sending.
    • 2 (Failure) — Indicates that the client could not wipe the device.

     

    Important:   Wiping the device resets the device to factory default conditions, including removing all data on the device and any data on the storage card if one is included.

     

    ABQ

    Allow/Block/Quarantine (ABQ) is a new feature introduced in Exchange 2010 that enables administrators to control device access to mailboxes based on device type. While provisioning and policies focus on managing device features such as passwords, cameras, encryption, and so on, ABQ simply controls access to the mailbox. Administrators use ABQ along with policies to manage Exchange ActiveSync clients. For more information, see Controlling Exchange ActiveSync device access using the Allow/Block/Quarantine list on the Exchange Team Blog.

    Microsoft Exchange manages access to the mailbox through ABQ by using device information that it relies on the client to provide. The client sends this information in the Provision command request or as part of the Settings command, as shown in the following example.

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

    <Settings xmlns="Settings:">

        <DeviceInformation>

            <Set>

                <Model>CONTOSO</Model>

                <IMEI>123456789012345</IMEI>

                <FriendlyName>Matt's Phone</FriendlyName>

                <OS>Contoso Phone1.0.1234</OS>

                <OSLanguage>English</OSLanguage>

                <PhoneNumber>555-555-1234</PhoneNumber>

                <MobileOperator>ContosoTelecom</MobileOperator>

                <UserAgent>ContosoPhone1</UserAgent>

                <EnableOutboundSMS>1</EnableOutboundSMS>

            </Set>

        </DeviceInformation>

    </Settings>

    The elements set by the client are listed in the following table:

    Element name

    Description

    Model

    Indicates the manufacturer and model name or number of the device.

    FriendlyName

    Describes the device in a way that is meaningful to a user.

    IMEI

    Uniquely identifies the device.

    OS

    Precisely specifies the operating system version that the client is running. The OS element value is structured as follows: <Operating System Name> <Operating System Major Version> <Operating System Minor Version>.

    OSLanguage

    Indicates the language used by the client. The server displays this information when it lists device properties.

    PhoneNumber

    Can be provided to help with troubleshooting or device management. This element is optional unless the EnableOutboundSMS element is set to 1, in which case the server returns a status code 5 because a phone number is required in order for the server to try to send SMS messages.

    MobileOperator

    Indicates the name of the operator that a mobile device is connected to.

    UserAgent

    The value of this element should match the User-Agent header values that are submitted with each request.

    EnableOutboundSMS

    This element should have a value of either 1 or 0 to indicate whether the client can be used to send outbound SMS messages composed by the server.

     

    Note:   Clients thatsupport versions 12.1 and 14.0 of the Exchange ActiveSync protocol should use the Settings command to send device information. The client should send the Settings command as soon as possible after provisioning and before sending the first FolderSync command.

     

    Related Resources

    [MS-ASCMD]: ActiveSync Command Reference Protocol Specification

    [MS-ASPROV]: ActiveSync Provisioning Protocol Specification

    Understanding Exchange ActiveSync Mailbox Policies

    Understanding Remote Device Wipe

    Controlling Exchange ActiveSync device access using the Allow/Block/Quarantine list

     

    Post authored by: Matt Stehle, Microsoft Corporation

    JET_ERRINFOBASIC_W API

    $
    0
    0

    UPDATE: 8 November 2011, Thom Randolph - MSFT.

    The following API reference information in this post applies to the Windows Extensible Storage Engine (ESE) APIs, that are available on MSDN at the following URL:

    http://msdn.microsoft.com/en-us/library/windows/desktop/gg269259(v=EXCHG.10).aspx

    The ESE APIs that ship in Windows should not be used with Exchange mailbox or public folder databases.


     

    The JET_ERRINFOBASIC_W API includes a group of constants, a structure, and a function, as defined in the header file Esent.h. These are described in this blog post.

    Note: This documentation is based on a preliminary release of the Extensible Storage Engine. This information is subject to change.


    JET_ERRCAT Constants

    The JET_ERRCAT group of constants describes higher-level classifications or categories of errors. This group of constants enables applications to define default treatment for a classification of errors, rather than handling each error case individually. It also ensures that the application does not have to handle new error conditions that are included in existing classifications.

    The JET_ERRCAT constants are arranged in a specific hierarchy of conditions and subconditions, as follows:

    |--- Error
    |--- Operation(al)
    | |--- Fatal
    | |--- IO
    | |--- Resource
    | |--- Memory
    | |--- Quota
    | |--- Disk
    |
    |--- Data
    | |--- Corruption
    | |--- Inconsistent
    | |--- Fragmentation
    |
    |--- Api
    |--- Usage
    |--- State

    The following table lists the JET_ERRCAT constants and provides a description and recovery information, as applicable.

    Constant/value

    Description

    Recovery

    JET_errcatUnknown
    0

    An invalid error category.

    N/A.

    JET_errcatError
    1

    The top level category (no errors should be of this class).

    See the specific error constants.

    JET_errcatOperation
    2

    Represents errors that can happen at any time due to uncontrollable conditions and are often temporary. See subcategories if specified

    Retry and if the error continues, inform the operator.

    JET_errcatFatal
    3

    Represents fatal errors that, when they occur, create a risk that ESE cannot continue in a safe (often transactional) way , and data may become corrupted.

    Restart the instance or process. If the problem persists, inform the operator.

    JET_errcatIO
    4

    Represents IO errors, which come from the operating system, and are out of ESE's control. This type of error may be temporary.

    Retry, and if the error continues, ask the operator to check the disk.

    JET_errcatResource
    5

    Represents a category of errors related to lack of resource conditions.

    See subcategories.

    JET_errcatMemory
    6

    Represents an error caused by lack of memory.

    Retry after a period of time, free up memory, or quit.

    JET_errcatQuota
    7

    Certain "specialty" resources are in pools of a certain size, making it easier to detect leaks of these resources.

    The application should Assert()to detect these issues during development . However, in retail code , the application should treat this as a memory error.

    JET_errcatDisk
    8

    Represents an error caused by lack of disk space.

    Retry later to determine whether more disk space is available, or ask the operator to free some disk space.

    JET_errcatData
    9

    Represents a top-level category for errors related to data.

    See subcategories.

    JET_errcatCorruption
    10

    Represents a corruption issue, which is often permanent without corrective action.

    Restore from backup by using the ESE utilities repair operation (this operation restores only the data that is left/lossy). Also when the recovery(JetInit) method is used, recovery can be performed by allowing data loss (for more information, see JET_bitReplayIgnoreLostLogs.

    JET_errcatInconsistent
    11

    Represents an error in which the database and/or log files are in a state that is inconsistent and cannot be reconciled. This error might be caused by application/administrator mishandling.

    Restore from backup by using the ESE utilities repair operation (which only restores the data that is left/lossy). Also in the case of the recovery(JetInit) operation, recovery can be performed by allowing data loss (for more information, see JET_bitReplayIgnoreLostLogs.

    JET_errcatFragmentation
    12

    Represents a class of errors in which some persisted internal resource ran out.

    For database errors, offline defragmentation will fix the problem. For the log files, first recover all attached databases to a clean shutdown , and then delete all the log files and the checkpoint.

    JET_errcatApi
    13

    See subcategories.

    See subcategories.

    JET_errcatUsage
    14

    Represents a usage error. The client code did not pass the correct arguments to the JET API. This error will persist with retry.

    Client code should use the Assert() method to ensure that this class of errors is not returned. so issues can be caught during development. In retail , the application should notify the operator about the error.

    JET_errcatState
    15

    Represents a class of messages that the API can return to describe the state of the database. For example, the JetSeek() method might return JET_errRecordNotFound when the requested record was not found.

    Varies based on the API.

    JET_errcatObsolete
    16

    Represents errors that are from a previous version of the engine. These errors should not be returned by the current engine.

    Unknown.

    JET_errcatMax
    17

    A constant that indicates the end of the enumeration.

    N/A.

    Requirements

    Client

    Requires Windows 8.

    Server

    Requires Windows 8 Server.

    Header

    Declared in Esent.h.


    JET_ERRINFOBASIC_W Structure

    The JET_ERRINFOBASIC_W structure defines the data that is returned from the JetGetErrorInfo() method when the JET_ErrorInfoSpecificErrInfoLevel[LG1] is passed in.

    typedef struct {
             unsigned long    cbStruct;
             JET_ERR          errValue;
             JET_ERRCAT       errcatMostSpecific;
             unsigned char    rgCategoricalHierarchy[8];
             unsigned long    lSourceLine;
             WCHAR            rgszSourceFile[64];
    } JET_ERRINFOBASIC_W;

    Members

    cbStruct
    The size of the structure, in bytes. It must be set to sizeof( JET_ERRINFOBASIC ).

    errValue
    The error value that was evaluated, as passed in for the pvResult argument to JetGetErrorInfo().

    errcatMostSpecific
    The lowest-level JET_errcat constant that is associated with the error; that is, the leaf-level category in the category hierarchy documented in JET_ERRCAT.

    rgCategoricalHierarchy[8]
    The hierarchy of error categories that is associated with the error. Position 0 is the highest level in the hierarchy of JET_ERRCAT, and the rest are subcategories until the most specific category is set, after which all categories are JET_errcatUnknown.

    lSourceLine
    Reserved.

    rgszSourceFile[64]
    Reserved.

    Requirements

    Client

    Requires 8.

    Server

    Requires 8 Server.

    Header

    Declared in Esent.h.


    JetGetErrorInfoW Function

    The JetGetErrorInfoW function BAS_ of the database engine.

    JET_ERR JET_API JetGetErrorInfoW(
             _In_opt_ void *                    pvContext,
             _Out_writes_bytes_( cbMax ) void * pvResult,
             _In_ unsigned long                 cbMax,
             _In_ unsigned long                 InfoLevel,
             _In_ JET_GRBIT                     grbit );

    Parameters

    pvContext
    The context or error value for which the extended error information is needed. The value passed in depends on the InfoLevel parameter value.

    pvResult
    A pointer to a buffer that will receive the information. The type of the buffer depends on the InfoLevel parameter value. The caller must be configured to align the buffer appropriately.

    cbMax
    The maximum size of the pvResultstructure that is passed in.

    InfoLevel
    The type of information that will be retrieved for the error info/context is specified by the pvContext parameter. The format of the data that is stored in pvResult is dependent on InfoLevel.

    The following table lists the possible values for this parameter.

    Value

    Meaning

    JET_ErrorInfoSpecificErr

    pvContext is interpreted as a JET_ERR/error code, pvResult is interpreted as a JET_ERRINFOBASIC_W, and the fields of the JET_ERRINFOBASIC_W structure are filled in appropriately.

    grbit
    Reserved.

    Return Value

    This function returns the JET_ERR data type with one of the return codes listed in the following table. For more information about the possible ESE errors, see Extensible Storage Engine Errors and Error Handling Parameters.

    Return code

    Description

    JET_errSuccess

    The operation completed successfully.

    JET_errInvalidParameter

    One of the parameters provided contains an unexpected value or contains a value that does not make sense when combined with the value of another parameter.

    This can happen for JetGetErrorInfo when the following occurs:

    • The specified InfoLevel parameter value is invalid.
    • The specified grbit value is invalid.
    • The specified pvResult parameter buffer’s cbMax value is less than the required size for output of this InfoLevel parameter.
    • For InfoLevel = JET_ErrorInfoSpecificErr, the JET_ERR value passed in is unknown to the engine.

    JET_errDisabledFunctionality

    If this SKU of windows doesn’t support this function, this error will be returned.

    On success, the output buffer that is appropriate for the requested error context/value will be set to the extended error info requested.

    On failure, the state of the output buffers will be undefined.

    Remarks

    The JET_ERRINFOBASIC_W function and JET_ERRCAT group of constants contain documentation about the extended error information that is returned for InfoLevel = JET_ErrorInfoSpecificErr.

    Requirements

    Client

    Requires Windows 8.

    Server

    Requires Windows 8 Server.

    Header

    Declared in Esent.h.

    Library

    Use ESENT.lib.

    DLL

    Requires ESENT.dll.

    Unicode

    Note: Only the JetGetErrorInfoW (Unicode) is implemented. This API does not have an A (ANSI) version.

    Disabling EWS in Exchange 2010

    $
    0
    0

    Exchange Web Services (EWS) is a robust API that exposes many Exchange client access features. Many popular clients use this API on many different platforms. What if you want to limit client access via EWS, however? You do have an option. In Exchange 2010, you can use the Set-CASMailbox command to modify EWS access.

    Note:   The Set-CASMailbox command in Exchange 2007 does not provide options for limiting EWS access.

    The following options that the Set-CASMailbox command exposes enable you to change the settings on a per-user basis:

    • Turn EWS on/off
    • Turn EWS on/off for Outlook, Mac Outlook, and Entourage
    • Turn EWS on/off using allow/block lists for user agent filtering

    These options make use of the user agent header to filter access. While useful in many scenarios, user agent filtering has one  inherent disadvantage: User agent strings can easily be written to represent agents on an allowed list, including Outlook, Mac Outlook, and Entourage. Of equal importance is the fact that specific EWS features can’t be blocked. EWS feature access is not segmented to allow access to particular EWS operations — it’s all or nothing. Turning off EWS will affect clients that use the OOF settings, availability, mail tips, and so on. It is important to take this into consideration when planning the client-server interaction part of your system architecture.

    EWS Managed API 1.2 SDK – get ready, get set, plan

    $
    0
    0

    Are you ready? The EWS Managed API 1.2 documentation is now available, so let the preparation, planning, and architecting begin. The new EWS Managed API will have some updates that you may want to incorporate into your application. Take a look at the What’s New topic to learn more about the new content that is available to support the new EWS Managed API 1.2 functionality. Take a look at the Exchange Web Services Managed API 1.2 SDK topic to learn about the new EWS Managed API 1.2 functionality. 

    Did you say “Where is the API download?” It’s coming soon. We are releasing the documentation earlier than usual so that you can get a jump on your planning for the next update of your EWS client application. So go have a feature review, maybe update your design specs, and get ready to implement your next update to your EWS client application.


    New Exchange Interoperability Content on Open Specifications Developer Center

    $
    0
    0

    In November and December 2011, Exchange content made its debut on the Learn Open Specifications and Interoperability page in the Open Specifications Developer Center:

    The updates include nine new Microsoft Exchange Learning Modules:

    While you’re on the Learn tab exploring the new Exchange learning modules, don’t miss the Open Specifications Interactive Pivot, which also includes Exchange open specifications documents. We’re very excited about the Pivot, which makes it easy to find the open specifications documents you need in a visual, intuitive way. The Pivot uses Silverlight Deep zoom technology, which lets you visually search and filter the open specifications documents. Once you use it, you’ll see why we’re excited.

    Authenticate your Exchange client in Office 365

    $
    0
    0

    The Exchange Online server for your Office 365 account uses a different default authentication scheme than Exchange on-premises. In most cases, you won't notice the difference – except when you're using the EWS Managed API to call Exchange Web Services (EWS). Then you'll quickly find out that something has changed, because your client that worked before will start failing with a 401 Unauthorized error when it runs Autodiscover.

    Exchange Online uses basic authentication, and chances are your client is expecting to use NTLM authentication. The problem is simple, and the fix is simple too: you need to change your code to create a set of credentials for basic authentication.

    Typically, that means changing a line of code that looks like this one:

    NetworkCredential credentials = CredentialCache.DefaultCredentials;

    To one that looks like this one:

    NetworkCredential credentials = new NetworkCredential(UserSMTPEmailAddress, SecurelyStoredPassword);

    Of course, the devil is in the details, and in this case it's that parameter called SecurelyStoredPassword. You'll need to make sure that your client gets the user's password and stores it, for example, in a SecureString object instead of a plain text string. For a more recent example, you can take a look at the Credential Locker for Windows 8 store and desktop apps.

    Hot off the press! Synchronization and Notifications in Exchange Online and Exchange 2013

    $
    0
    0

    Last week, we added the following new content to the Exchange Online and Exchange 2013 development section on MSDN:

    This includes information about the affinity scenario for notifications, where the client manages its affinity with the mailbox server by using the X-AnchorMailbox header, the X-PreferServerAffinity header, and the X-BackEndOverride cookie. We provide instructions for how to use the headers and cookie and how to group mailboxes and batch requests. We also provide a detailed example that shows you all the moving parts, and details about error handling and throttling limits.

    All this is included with other concepts you might already be familiar with: streaming notifications, pull notifications, and item and folder synchronization. We provide information about how to perform these tasks by using either the EWS Managed API, or the underlying EWS operations and elements that are sent over the wire - so it’s your one-stop shop for Exchange Online and Exchange 2013 app development, no matter what your technology preference is. And we’re not stopping here. We are actively publishing updates to the Create EWS and web service solutions for Exchange section, so check back often for the latest insights and guidance. Enjoy!

    What’s new in Exchange 2013 SP1

    $
    0
    0

    You might have heard the news that Exchange 2013 Service Pack 1 (SP1) and the EWS Managed API 2.1 are now available. And you might be asking, what does that mean for me – and more importantly, what does that mean for my applications? Here's the low down.

    For the Exchange 2013 SP1 release:

    • The messages.xsd and types.xsd schema files have been updated. Remember, the types.xsd and messages.xsd files always contain the latest versions of the
      schema. The Exchange 2013 schema files now have the following names: messages-e15.xsd and types-e15.xsd.
    • To target Exchange2013 SP1 in your Autodiscover requests, set the SOAP Autodiscover RequestedServerVersion element to Exchange2013_SP1. If you're using EWS, set the RequestServerVersion element value to Exchange2013_SP1 in your requests. 
    • Edge Transport servers are back! Edge Transport servers minimize the attack surface by handling all Internet-facing mail flow, which provides SMTP relay and smart host services for your Exchange organization, including connection filtering, attachment filtering, and address rewriting. If you'd like to read more about this, see Edge Transport Servers.

    For the EWS Managed API 2.1 release:

    • The EWS Managed API installer now automatically adds the EWS Managed API DLL to the GAC and makes it available to all users of the computer.

    The following functionality has been added to either the EWS Managed API, EWS, or both:

    FunctionalityIn EWS Managed API? In EWS?
    Read receipts can now be suspended for updates and deletions.YesYes
    You can get moderated transport approval information.YesYes
    Voting responses can be viewed.YesYes
    The SetHoldOnMailboxes method and SetHoldOnMailboxes operation accept all the parameters in a
    single object.
    YesYes
    eDiscovery searches can specify a language for search queries and a culture-specific format for date ranges.YesYes
    The StreamingSubscriptionConnection object can now access the StreamingSubscription objects.YesNo
    Conversations have a setting to indicate whether they contain email messages that are protected by IRM.YesYes
    Meeting attendees can propose new start and end times for meetings and include them in their meeting response.NoYes
    The SOAP Autodiscover GetUserSettings method now returns the GroupingInformation setting that is used maintain affinity for a
    multiple mailbox event subscription.
    YesN/A

     

    We’re in the process of updating the Exchange MSDN documentation for Exchange 2013 SP1, so stay tuned! You can also view these changes in the EWS schema files published with Exchange 2013 SP1 and Exchange Online, and by looking at the EWS Managed API.

    Using OAuth2 to access Calendar, Contact and Mail API in Office 365 Exchange Online

    $
    0
    0

    I am excited to announce that finally EWS in Exchange Online as part of Office 365 exposes a RESTful API for Calendar, Contact and Mail that uses OAuth2 for authorization. In this blog I want to briefly describe Exchange's underlying OAuth2 implementation and how to use OAuth2 to access the new Calendar, Contact and Mail APIs.

     

    First and foremost Office 365 fully integrates with Windows Azure Active Directory (AAD) to implement the OAuth2 protocol. There is an exciting announcement available here from Alex Simons, Director of AAD that outlines the new AAD capabilities around this protocol. At the end of this blog I will refer to more documentation. Don't hesitate to ask questions on Stack Overflow about accessing the new APIs using the OAuth2 protocol or about the APIs themselves. Please tag your question with [ms-office] and [ews] to get the fastest response possible.

     

    I will focus in this post on the basic concepts and will highlight some of the differences compared to other OAuth2 implementations to get you started as fast as possible. 

     

    Step One: Registering your application

    Before you can use OAuth2 to access the Calendar, Contact and Mail APIs, your application needs to be registered in AAD. When you sign up for Office 365 for business or Office 365 developer, don’t worry, you already get AAD. If you are using Visual Studio, the app registration and permission management in AAD is done automatically for you! Outside of Visual Studio, you should visit the Windows Azure Portal and do the application registration there. For a step by step walkthrough, go here. During the application registration process a client ID for your application is created, client secrets for web apps are managed, and the permissions your application needs for accessing the APIs are defined.

     

    Important:  Permissions must be defined up-front in AAD for the APIs as part of the registration process. While you might be used to specifying the permissions with the authorization request in other OAuth2 implementations by using the "scope" parameter, this is not possible at this point. In order for your application to configure these permissions in AAD, the AAD tenant where your application is registered must be linked to an Office 365 subscription with Exchange Online.

     

    Step Two: Triggering user consent (aka authorization)

    The goal of your application is to access the Calendar, Contact and Mail APIs. For this you need to get an access token that is passed along with the API request to Office 365. An OAuth2 authorization request is the first step for your application to get an access token. As part of the authorization process, user consent is involved. User consent is the act of displaying a dialog that clearly lists the permissions that your application is requesting. The user can decide if the permissions your application is requesting should be granted. The permissions that appear in this consent dialog are the same permissions you configured in Step One in AAD.

     

    A typical authorization request looks like this (make sure you use https):

    GET https://login.windows.net/common/oauth2/authorize?response_type=code&client_id=acb81092-056e-41d6-a553-36c5bd1d4a72&redirect_uri=https://mycoolwebapp.azurewebsites.net&resource=https:%2f%2foutlook.office365.com%2f&state=5fdfd60b-8457-4536-b20f-fcb658d19458

     

    Parameter

    Description

    response_type

    Required. Value is always code

    client_id

    Required. Value of your client_Id given when you registered your application with AAD

    resource

    Required. The Office 365 resource your app wants to access. As you want to access Office 365 Calendar, Contact, and Mail APIs this is "https://outlook.office365.com/".

    state

    Required. A long unique string value of your choice that is hard to guess. Used to prevent CSRF. For example, this can be a Guid generated by your app with each authorization request.

    redirect_uri

    Required. URI in your app where users will be sent after authorization. Must be registered in AAD.

     

    Important: Redirect URIs must be registered in AAD as "Reply URLs" as part of the initial app registration, or at any point in time later in the process of developing your app. Failure to specify the correct redirect_uri will cause the authorization request to fail. So check your Reply URLs in AAD with your app registration.

     

    If the user authorizes your application they will be redirected to the redirect_uri that you specified in your request above along with a temporary authorization code and the same state that you passed in the request above.

     

    Upon successful authorization, the redirected URL should look like:

    {your redirect uri}/?code={authorization code issued by AAD}&state={same state Guid passed as in the authorize request}

     

    Ensure that the state parameter in this response matches the one you passed in the authorization request above. If the state does not match, that means the request may be a result of CSRF and must be rejected. 

     

    If the user does not allow authorization to your application, redirection to the redirect_uri still occurs. Additional query parameters indicate the user canceled authorization and a short description of the error: 

    {your redirect uri}/?error=access_denied&error_description=AADSTS65004%3a+The+resource+owner+or+authorization+server+denied+the+request.%0d&state={same state Guid passed as in the authorize request}

     

    Before we continue with the next step on how to trade in the authorization code to an actual access token that you can use to access the Office 365 Calendar, Contact and Mail APIs we need to talk about a very nice variation of authorization you can request for a web application. Note that following doesn't apply for a native application. In particular AAD offers for a web application the capability for an administrator of an Office 365 Organization to consent on-behalf of all users in this organization. Once an administrator does this, users will not see any additional consent dialog with authorization requests. Essentially what this provides you is that your web application can have a sign-up experience for an organization in addition to an individual sign-up for a user.

     

    You can accomplish this kind of organization sign-up in your app by simply modifying the authorize request to add an additional parameter called "prompt". For the example above this would be:

    GET https://login.windows.net/common/oauth2/authorize?response_type=code&client_id=acb81092-056e-41d6-a553-36c5bd1d4a72&redirect_uri=https://mycoolwebapp.azurewebsites.net&resource=https:%2f%2foutlook.office365.com%2f&state=5fdfd60b-8457-4536-b20f-fcb658d19458&prompt=admin_consent

     
    Triggering admin consent for an organization sign-up:

    Parameter

    Description

    prompt

    Value: "admin_consent". Indicates that the authorization request is for all users in an Office 365 Organization.

     

    Important: Only an administrator of an Office 365 Organization can consent to such an authorization request. If an end-user tries to do this, AAD will redirect back to your application with an specific error indicating that consent could not be given.

     

    Step Three: Trade-In for an access/refresh token

    We're almost there. At this point we have an authorization code from a user or an administrator dependent on the authorization request your application sent. This code can be used to request an access token. Together with the access token your application will also receive a refresh token and an ID token. For the API access only the access token is important. The refresh token is for your app to keep in a safe place in an encrypted persistent temporary or permanent storage dependent on your app's requirements. You use the refresh token to request additional access tokens for either the same Calendar, Contact and Mail APIs or other Office 365 APIs such as OneDrive Pro. The ID token can be used to authenticate the user to your application. It contains the users ID and the organizations ID as known by AAD. You can use those IDs for your app's own memory or profile store on who signed up. Both access token and refresh token are JSON encoded web tokens that can be easily parsed. The specific properties to use for building an app-specific profile store in the ID token are "oid" for the user identifier and "tid" for the organization identifier.

     

    Let's look at how such a token request looks like using the code.

     

    Code Request:

    The base token URL is:

    POST https://login.windows.net/common/oauth2/token

    The body is form encoded:

    grant_type=authorization_code&code={code from the authorize request}&redirect_uri={reply url for your application}&client_id={your application's client id in AAD}&client_secret={your application's client secret}

     

    Important: The redirect_uri in the token request must be the same as the one used with the original authorize request.

     

    A successful response to this request contains the following fields in a JSON object:

    Field

    Description

    access_token

    Base64 url encoded JSON web token for API access.

    token_type

    Always "Bearer"

    expires_in

    The time period (in seconds) after which the access token will become invalid. For now this value is 60 minutes.

    expires_on

    Time in Unix epoch when the access token expires.

    resource

    The Office 365 resource or API that this access token applies to.

    refresh_token

    Opaque refresh token for your app to keep and get additional access tokens.

    scope

    The permissions that this access token contains.

    id_token

    Base64 url encoded JSON web token for user identification by the client application.

     

    After 60 minutes the access token becomes invalid. A good pattern to follow is to cache this access token and use it to call the Calendar, Contact and Mail APIs until the API returns a 401 access denied with an error code of "invalid_token". In that 401 event your app should use the refresh token to get a new access token and retry the request.

     

    Note: In case you are curious about what an access token or ID Token look like, there is a great web app available at http://jwt.calebb.net that allows you to simply cut and paste the token received from a token request and peek into the fields.

     

    Request additional access tokens with a refresh token

    Below is the request your app uses to get a new access token. The actual response is the same as in the code request, thus together with the access token your app receives a new refresh token. You should take the new refresh token to replace the old one as refresh tokens will expire in some period of time too.

    The base token URL is:

     POST https://login.windows.net/common/oauth2/token

     The body is form encoded:

     

    grant_type=refresh_token&refresh_token={the current RefreshToken in your applications cache}&client_id={your application's client id in AAD}&client_secret={your application's client secret}&resource={Uri of the API}

     

     

    Important: The resource parameter indicates what API endpoint your application wants access to within the Office 365 APIs. For the Calendar, Contact and Mail API this is "https://outlook.office365.com".

     

    As briefly mentioned above, the refresh token, while long living, becomes invalid at some point too. One example is if the user changes their password, refresh tokens become invalid. Your app can react to this gracefully by handling an error response from the token request that returns "invalid_grant". If this happens your app should go back to the authorization request as outlined in Step One to get a new authorization code and use this to get a new access token/refresh token pair.

     

    Step Four: Accessing the API with the access token

    We are almost there. Your application has an access token at this point for the Calendar, Contact and Mail API. Using this access token is fairly simple. When sending a RESTful API https request the access token is attached in the standard authorization header with the Bearer auth scheme. An example is listed below: 

    GET https://outlook.office365.com/EWS/OData/Me/Inbox/Messages?$top=5

    User-Agent: My-Cool-WebApp/1.0
    client-request-id: 9aa1c740-25e2-4841-9146-ef7018f7bf37
    return-client-request-id: true
    authorization: Bearer {access token your app received in Step Three}

     

    Important: Always use https with your API request.

     

    Unrelated to OAuth2, there are two http request headers the Office365 APIs would want your application to specify. This is the "User-Agent" and the "client-request-id". For User Agent you can follow RFC 2616 which basically describes it as {ProductName}/{ProductVersion} [{comment}]. For "client-request-id" your app should create a new Guid for each request. When the request fails "return-client-request-id" returns the Guid that was submitted as "client-request-id" with the request. It is highly recommended that you persist the failed request together with client-request-id and all http response headers in some application log. If you ever need help troubleshooting your application with the Office 365 APIs, this will be pave the route to a fast and successful resolution of the problem.

     

    Client libraries are your Friend - use them!

    Above I described how your application can apply the OAuth2 protocol for Office 365 APIs on the example of the Calendar, Contact and Mail API. While the OAuth2 protocol is a fairly straight forward and well understood pattern there are many things such as caching of access tokens/refresh tokens that are more complicated to handle within an application. The Azure Active Directory Authentication Library (ADAL) will help you abstracting not only the OAuth2 protocol, but also provide caching and mechanisms to get new access tokens. Whenever possible you should use this client library for your web or native app. ADAL comes for a variety of platforms including .NET, Windows Store, iOS and Android. Check them out!

     

    Summary

    Hopefully this blog provided you with enough detail to get started developing an exciting application for the Calendar, Contact and Mail API in Office 365. We would love to hear from you at this forum and are eager to know about your apps and feedback on how we can improve on our APIs and authentication to them.

     

    Note that there will be many more functionalities coming in the next month and I will try to keep the blog updated whenever a new capability lights up. For example, the current blog describes the OAuth2 code flow, and AAD in the near future will provide a OAuth2 implicit flow that is optimized for JavaScript-based applications such as Office 365 mail apps. For sure we will post about this pretty soon. We are also working on having OpenID Connect available for single sign-on into your web app and Office 365. All more exciting functionality that will make application development more easy and hopefully worry-free regards the way your application authenticates with Office 365 APIs.

     

    Additional documentation of interest

    Finally, as promised, some pointers to documentation. Lots of time went into these and they are well worth reading while sipping your morning or afternoon coffee:

     

    Authentication and authorization using Common Consent Framework

    How to: Integrate O365 with a web server app using Common Consent Framework

    Using the Mail, Calendar, and Contact REST APIs to work with emails, calendar items, and contacts

    ADAL - Active Directory Authentication Library info

    Azure Active Directory info

     

     

    Customizing the compose experience with mail apps for Outlook

    $
    0
    0

    Today we bring you a guest post from Andrew Salamatov, a Program Manager with Exchange. Enjoy.

    Writing messages and scheduling meetings often requires users to look up and include content from outside of Outlook. Frequently, users have to use software that takes them outside of Outlook to complete the task, when it would be much more efficient if they could just stay inside of the mail experience. After all, many of us live in Outlook! To help make users more productive with these scenarios, we’re excited to announce a brand new feature in the Apps for Outlook platform – apps can now customize the message and appointment compose experience across desktop, web and mobile!

    This feature has already rolled out to all users in Office 365 and is included in the SP1 update to Office and Exchange 2013 that we made available at the end of February (this feature requires an Exchange 2013 SP1 mailbox). A deeper dive into compose capabilities of Apps for Outlook will be the subject of another post. I'll just mention a few highlights.

    Streamlined productivity

    There are many compelling scenarios out there that can really help users get things done faster. If you are interested in building compose apps, here are some to use as examples:

    A survey app could enable users to send out quick polls on a topic, or get consensus on when to meet. After the poll is sent, the read version of this app can activate on this poll and allow recipients to easily vote.

    [Click to enlarge]

    A template app could let users choose the right style to craft the message with, or compose messages based on legal document templates.

    [Click to enlarge]

    And a workflow app could let users submit documents for approval.

    [Click to enlarge]

    Write once, run everywhere 

    As with apps that are available while reading messages, a compose app can run across Outlook on your desktop, Outlook Web App in your browser, and OWA for Devices on your iPhone or iPad. In fact, you can now build an app that runs in messages and/or appointments, while the user is reading or composing!

    [Click to enlarge]

    My Templates app

    You can try out compose apps by using the My Templates app that comes pre-installed with Exchange. To use, simply start writing a new message. Then, choose “APPS” in Outlook Web App.

    [Click to enlarge]

    Then select "My Templates".

    [Click to enlarge]

    Selecting any template will insert it into the body.

    If you are interested in building mail apps, check out our session from SPC14 which dives into developing apps and mentions even more great scenarios, or take a look at the documentation. We will also be at MEC and Build, so if you’re around, stop by!

     Happy building!

    Andrew Salamatov,

    Program Manager, Microsoft Exchange

     

    Enabling Microsoft Azure portal access to manage applications using the OAuth2 protocol

    $
    0
    0

    In my previous post about OAuth2 access to Calendar, Contact and Mail APIs I explained that applications need to be registered and configured in Microsoft Azure Active Directory (AAD). Furthermore, administrators for Office 365 organizations use Microsoft Azure Active Directory to manage OAuth2-enabled applications used by users in their organization. This management includes seeing which web applications users consented to, or revoking access to web applications.

     

    The management user interface for AAD is available within the Microsoft Azure portal. While all Office 365 organizations automatically have AAD available, currently the Microsoft Azure portal requires additional sign-up to get access to the management user interface.

     

    We are actively working on changing this so that no sign-up is required. In the meantime, be aware that no Office 365 organization will be charged additional fees for signing-up to Microsoft Azure as long as no additional services other than AAD are subscribed to. Be assured that AAD comes with any Office 365 subscription for free.

     

    I thought it is worth a blog guiding through the sign-up experience to get to the Microsoft Azure portal to start registering, configuring and managing applications for your Office 365 organization.

     

    Step 1: Launching the Microsoft Azure management portal

     

    In your browser of choice simply navigate to https://manage.windowsazure.com/. You should be prompted to provide a user account. Here you should enter any organizational account that is an administrator of your Office 365 organization.

     

    A screenshot of the Azure login page.

     

    In the next step you will be asked to provide the password for the account that you specified.

     

    A screenshot of the Azure password entry page.

     

     

    Step 2: Starting the sign-up for Microsoft Azure portal

     

    After successful sign-on with an administrative organizational account of your Office 365 organization, a screen is displayed that will indicate that this account has no Microsoft Azure subscription associated. By selecting "Sign up for Windows Azure" you start the process of enabling your Office 365 organization to manage AAD within Microsoft Azure Portal.

     

    A screenshot of the error page that displays when there is no Azure subscription for the account. This page has a link to the Azure sign-up page.

     

    Step 3: Providing and verifying contact information

     

    In this step you can provide and change contact information for the Microsoft Azure subscription. Some of the information will be prefilled based on the account information of the organizational account that was used to sign-on.

     

    Don't worry about the words "Free Trial", you will actually get a fully functional subscription with no additional charges at the end of this process. Note that additional charges only apply if additional Microsoft Azure services are subscribed to.

     

    A screenshot of the Azure sign-up page.

     

    Provide a valid verification before continuing to the next step. Below is an example using text messages.

     

    A screenshot of the "Mobile verification" section of the Azure sign-up page.

     

    Step 4: Add payment information and confirm the sign-up to Microsoft Azure

     

    Although the AAD services are available at no charges, including the management of those in the Microsoft Azure portal you will be asked to provide a valid payment information. Again, rest assured that there will be no charges against this payment option unless at a later time you add non-AAD Microsoft Azure services that require payment.

     

    A screenshot of the "Payment information" section of the Azure sign-up page.

     

    We're almost there. Simply check the checkboxes to agree to the Microsoft Azure terms of use and optionally to be contacted for additional Microsoft Azure offers and click on "Sign up".

     

    A screenshot of a completed Azure sign-up page.

     

    Step 5: Change the free trial to a pay-as-you-go subscription

     

    In Step 3 I told you to not worry about the wording of "Free Trial". But at this point if you don't do anything the Microsoft Azure subscription will expire in 30 days. So why did I tell you to not worry?

     

    Well, first of all, even if you choose to not do anything, at this point you can start using the Microsoft Azure portal for 30 days to register, configure and/or manage applications using the OAuth2 framework. But what happens after the 30 days you might wonder. The answer is you can't manage AAD anymore in the Microsoft Azure portal as your subscription is expired. But all the applications are still there as AAD itself remains active and fully functional. AAD is unaffected by the expiration of the Microsoft Azure subscription and the Microsoft Azure subscription only governs the user's ability to sign in to the Microsoft Azure Portal for our purposes.

     

    To avoid doing the sign-up again after these 30 days, I recommend to convert the "Free Trial" to a "Pay-as-you-Go" subscription by selecting the "Upgrade Now" option. Doing this upgrade will ensure a non-interruptive management experience in the Microsoft Azure portal for all your applications in AAD.

     

    Again: no additional charges will apply for this upgrade unless you subscribe to non-AAD Microsoft Azure services.

     

    A screenshot of the Azure subscriptions page after signing up for a new subscription. The page indicates that there is a free trial that expires in 29 days.

     

    After selecting the "Upgrade Now" option, select "Yes, upgrade my subscription" and give it a friendly name such as "Pay-As-You-Go" and click the checkmark in the right lower corner to complete the upgrade process.

     

    A screenshot of the Azure subscriptions page while upgrading the free trial to a pay-as-you-go subscription.

     

    Step 6: Confirmation of the upgrade

     

    After you go through the upgrade process you should see a screen similar to this, indicating you have 30 days to try additional Azure services, and after these 30 days the subscription will continue. The message also indicates that you will not be charged for services that are included in the subscription. AAD is one of these services that are included.

     

    A screenshot of the Azure subscriptions page after successfully upgrading to a pay-as-you-go subscription.

     

    Step 7: Start managing AAD in the Microsoft Azure portal

     

    To finish this blog, let me guide you through getting to the AAD management user interface in Microsoft Azure. In the last step the screenshot shows in the upper left corner a link called "Portal". By selecting this link you will launch the Microsoft Azure portal. Since this is the first time, you will be greeted with a tour that explains some more things regarding management of services within Microsoft Azure. You can select the arrow key to browse through this sequence or simply close it.

     

    A screenshot of the tour that is presented when you login to the Azure management portal for the first time.

     

    To get to the AAD management user interface, select "All Items" in the left navigation bar. You should see your Office 365 organization listed there as type "Directory".

     

    A screenshot of the "All Items" section in the Azure management portal.

     

    By selecting this you launch the Microsoft Azure Active Directory management interface and can see "Applications" as one of the tabs to choose from.

     

    A screenshot of the Azure management portal after selecting the directory.

     

    Congratulations, you did it! You are ready to manage applications your users or administrators installed or consented to, or start registering and configuring your own applications for some cool development of new apps for Office 365 using OAuth2!

     


    EWS Managed API 2.2 now available

    $
    0
    0

    If you're reading this, the EWS Managed API 2.2 is available for download. This version doesn't add much to the 2.1 version, but if you're working with attachments in a mail app, these changes were made with your scenario in mind.

    The 2.2 release adds an Attachment property to the GetAttachmentResponse class. This seemingly simple change means that now you can use the EWS Managed API to retrieve attachments using only the attachment ID, as is the case when a mail app sends attachment IDs to a remote service, as described in the How to: Get attachments of an Outlook item from an Exchange server article. Look for that article to be updated with sample code using the EWS Managed API in the near future.

    Download the 2.2 version here.

    Managing user consent for applications using Office 365 APIs

    $
    0
    0

    Now that the new Office 365 APIs are available in preview and ready for you to build exciting applications, you might wonder how these applications can be managed.

     

    There are several aspects to managing applications that are built by using the Microsoft Azure Active Directory (AAD) OAuth2 framework, and in this blog I want to briefly explain one important one.

     

    Applications developed by using the AAD OAuth2 framework participate in the consent flow that AAD provides. As I mentioned in my previous blog (Using OAuth2 to access Calendar, Contact and Mail API in Office 365 Exchange Online), there are two types of consent:

    ·        User Consent, or consent provided by an end user

    ·        Admin Consent, or consent provided by an administrator

     

    An application has to request which consent flow to implement.

     

    If the application implements the user consent flow, any user in the Office 365 organization can install the application and give consent for the application to access the user's resources.

     

    If the application implements the admin consent flow, only users who belong to the Global Administrators group in the Office 365 organization can give consent to the application. That consent is then given on behalf of all users in the organization. Users do not have to provide an additional consent, and the application can access signed-on users' resources immediately.

     

    Note that an application can implement both consent flows. You can think of user consent as "Connect to my Office 365 resources", and admin consent as "Sign my organization up to use this application". The two models are not mutually exclusive.

     

    The user consent flow is implemented by default for Office 365 organizations, but an administrator can change this default to prevent end users from installing applications.

     

    This capability is not exposed in the Office 365 Portal or the Windows Azure Management Portal in AAD. To manage identities, an Office 365 administrator can use the PowerShell tools provided by AAD in addition to the portals. The administrator can use these tools to turn off user consent by using the following procedure.

     

    To turn off user Consent

     

    1.      Get the  Windows Azure AD PowerShell Module. This is available on TechNet.

      

    2.      Connect to your Office 365 Tenant.

     

    $msolcred = get-credential
    connect-msolservice -credential $msolcred

     

    3.  Check the current settings for allowing user consent.

     

    Get-MsolCompanyInformation | flDisplayName,UsersPermissionToUserConsentToAppEnabled

     

    DisplayName                              : Contoso

    UsersPermissionToUserConsentToAppEnabled : True

     

    Note: A value of "True" indicates that users can consent to applications.

     

    4.  Turn off user consent to applications.

     

    Set-MsolCompanySettings -UsersPermissionToUserConsentToAppEnabled:$false

     

    5.      Verify that user consent to applications is turned off.

     

    Get-MsolCompanyInformation | flDisplayName,UsersPermissionToUserConsentToAppEnabled

     

    DisplayName                              : Contoso

    UsersPermissionToUserConsentToAppEnabled : False

     

    Note: A value of "False" indicates that users cannot consent to applications.

     

     

    Important: Turning off user consent impacts users in the following ways:

    ·        End users cannot consent to applications. This means that installed or native applications cannot be installed anymore in the Office 365 organization. It is not possible for an administrator to install a native application and make it available to all users.

    ·        Existing consents that users provided remain valid until the user either revokes the consent (for web applications) or uninstalls the application (for native applications).

     

     

    How end users can revoke consent

     

    I want to explain how end users can manage their consent. First, it is important to understand how applications record the consent. This is different for native applications (or applications that a user installs - sometimes also called native device apps) and web server applications.

     

    For native applications, the consent is recorded on the device where the application is installed, as part of the RefreshToken. If the application is developed by using the ADAL client libraries, the RefreshToken is stored on the device. If an application doesn't use ADAL libraries, the developer needs to handle storing the RefreshToken on the device.

     

    For web server applications, the consent is recorded in AAD and is not part of the RefreshToken. While the RefreshToken still has to be managed, it does not actually carry any consent information.

     

    This means that in order for an end user to revoke user consent for a device app, the user has to uninstall the application from the device or computer it is installed on.

     

    For web server apps, the user can sign on with their organizational account and go to http://myapps.microsoft.com. From there, they can see the applications that they have consented to and they can revoke access.

     

    I hope this blog provided some more context around how consent is managed for applications that are consuming the Office 365 APIs. As always, please post additional questions.

     

     

     

     

     

     

    Zapier’s Office 365 API Journey

    $
    0
    0

    Since we first heard about the new Office 365 product suite, we at Zapier have been eager to dig into the APIs that would accompany it. So earlier this year, when the Office 365 APIs preview launched at http://dev.office.com/, we jumped at it!

    For those of you who aren't familiar with the Office 365 APIs, the preview has these goodies:

    • A REST API for Office 365 for Business (Home & Outlook.com currently excluded)
    • OAuth2 for authentication
    • Endpoints for Mail, Calendar, Contacts, and Files/Folders
    • OData formatting (which provide tons of powerful query string operators)
    • JSON serialization

    Previously, much of the Microsoft development ecosystem focused on .NET code. While .NET SDKs still have superb support, this marks an exciting time where language-agnostic REST APIs are first class citizens. For example, Zapier is mostly written in Python and we found it a breeze to connect to the new REST/OAuth/OData Office 365 APIs. Here's how we did it.

    Getting started

    The first thing you'll need is an Office 365 subscription. They do offer free trials, so you can sign up and start experimenting right away at http://office.microsoft.com/en-us/business/, or get a developer site at http://msdn.microsoft.com/library/office/fp179924(v=office.15).

    After you get all settled and are able to log on to https://outlook.office365.com/, you're ready to explore the API. Currently, Basic Authentication is enabled (for testing purposes only) in addition to OAuth2. That means there is a really simple way to explore the API directly from your browser. Just visit https://outlook.office365.com/EWS/OData/Me and enter in your normal Office 365 login credentials; you should see some JSON containing a bunch of handy links.

    Let's tour a few of those more interesting links!

    A quick tour

    Explore the following links to get a list of calendars and events, contacts, and email messages:

    I highly recommend keeping your browser session up and running, or using a tool like http://www.hurl.it/ to experiment with requests as you go.

    It is also wise to read up on the MSDN REST API docs for more information about how to use the REST API. Additionally, read the OData URI conventions doc for more information about how to use OData query strings for filtering and performance tweaks.

    Some real code

    Ripped straight out of Zapier, here is some real production code that shows how to use some of the useful resource URLs listed above with Basic Auth (we'll talk about OAuth in a moment!). Remember, these are the same calls you were making in your browser, just scripted!

    import requests # install http://docs.python-requests.org/

    EMAIL = 'you@yourdomain.onmicrosoft.com' # or your custom domain
    PASSWORD = 'yourpassword' # the same one you use to log in with

    # Get a list of all calendars.
    calendars_url = 'https://outlook.office365.com/EWS/OData/Me/Calendars'

    print('Calendars:')
    response = requests.get(calendars_url, auth=(EMAIL, PASSWORD))
    for calendar in response.json()['value']:
     
    print(calendar['Name'])
    print('')

    # Get a list of all events.
    events_url = 'https://outlook.office365.com/EWS/OData/Me/Events'

    print('Events:')
    response = requests.get(events_url, auth=(EMAIL, PASSWORD))
    for event in response.json()['value']:
     
    print(event['Subject'])
    print('')

    # Get a list of all contacts.
    contacts_url = 'https://outlook.office365.com/EWS/OData/Me/Contacts'

    print('Contacts:')
    response = requests.get(contacts_url, auth=(EMAIL, PASSWORD))
    for contact in response.json()['value']:
     
    print(contact['EmailAddress1'])
    print('')

    # Get a list of the 10 most recently created contacts.
    contacts_url = 'https://outlook.office365.com/EWS/OData/Me/Contacts'
    params = {'$orderby': 'DateTimeCreated desc', '$top': '10'}

    print('10 Most Recent Contacts:')
    response = requests.get(contacts_url, params=params, auth=(EMAIL, PASSWORD))
    for contact in response.json()['value']:
      print(contact['EmailAddress1'])
    print('')  

    # Get a list of the 25 most recently received messages.
    messages_url = 'https://outlook.office365.com/EWS/OData/Me/Inbox/Messages'
    params = {'$orderby': 'DateTimeReceived desc', '$top': '25', '$select': 'Subject,From'}

    print('25 Most Recent Messages:')
    response = requests.get(messages_url, params=params, auth=(EMAIL, PASSWORD))
    for message in response.json()['value']:
     
    print(message['Subject'])
    print('')

    If you are creating a prototype script, you can use Basic Auth to quickly try out the APIs, because it is really simple and easy. However, if you are performing these calls in production, or on behalf of others, don't collect their passwords, just use OAuth (which is much more pleasant for everyone). Let's cover that now.

    Connecting OAuth

    Now that you have the API landscape under your belt, we can upgrade from Basic Auth to OAuth2. To do that, you'll need to connect your Office 365 Subscription to an Azure account (which contains all the Active Directory apps). Just visit https://manage.windowsazure.com/ to get started.

    After you have an Azure account created and connected to your Office 365 app, you'll need to create a new Active Directory application. You might need to create a new directory under your Active Directory tab, but right alongside your Active Directory users, groups, domains, and so on you should see applications. You want to create one of those.

    A screenshot of the Microsoft Azure Active Directory portal.

    As you create and edit your app, you'll be able to set up your logo, secret keys, redirect/reply URI, and all the other good bits you are familiar with around OAuth. The only difference is that you'll need to select your scopes at application creation time, not in the redirect URI like most apps. You can do that in the "permissions to other applications" section:

    A screenshot of the Microsoft Azure permissions to other applications section of the app registration page.

    Then you'll want to set these values in the code powering your OAuth app:

    It is worth reiterating that you don't need to provide scopes, as those are encoded in the "permissions to other applications" section.

    After you finish the flow, just use the access_token and refresh_token in the same way that most OAuth services do. You can learn more about OAuth 2.0 in Azure AD, which should cover much of the basics outlined above.

    Putting it into production

    Thanks to the adoption of standard web API patterns like OAuth and REST, our company Zapier was able launch its very own Office 365 Integration in just a few days using the same developer platform optimized for the most common web API patterns.

    A quick checklist to run down before you go into production:

    • Make sure your refresh tokens swap for a new access token properly.
    • Use filter query strings like $filter=Price+lt+20 to reduce the number of records you request instead of requesting all records and doing it in memory.
    • Add a sanity limit query string like $top=100 to protect your performance.
    • Along with $top=100, consider using something like $orderby=DateTimeReceived+desc to get new records.
    • Use $select=DisplayName,EmailAddress1 to reduce the amount of data to only the bits you need. This is especially useful for email messages (which can be very large).

    If you follow these tips, you can be sure that your API calls are quick, efficient and robust. Don't forget to keep your eyes on the Office 365 documentation as they are often updated with new endpoints and features. Likewise, the Office 365 Dev Blog is indispensable!

    Bryan Helmig

    This post brought to you by Bryan Helmig. Bryan is a co-founder and engineer at Zapier. In addition to being a blues/jazz guitarist and whiskey connoisseur, he's hacked on just about every API available today and has helped design and build the Zapier platform which makes 10s of millions of API calls a day.

    Announcement: Exchange Dev blog has moved

    $
    0
    0

    This is the final Exchange Dev blog post. We’ve moved to the Office Developer blog, in this new location:

    http://blogs.office.com/dev

    Please join us in this new location to keep reading all the latest news about Exchange development.

    Don’t worry, we won’t delete any of these MSDN blog posts – they’ll stay here so you can continue to refer to them for the information you need.

    Here are all the places where you can join the Office Developer conversation:

      Twitter @OfficeDev

     Facebook Office Developer

     Yammer Office 365 Technical Network 

     MSDN Exchange Server Development forum

    Stackoverflow [ews] [exchange-server] [exchangewebservices] [ews-managed-api]

      Office Developer Center

    OAuth2 in action with the release of Office 365 Calendar, Contacts and Mail

    $
    0
    0

    I bet everyone is equally excited like me to have the Office 365 API out of preview and generally available to start building super cool apps. For those entrepreneurs that worked with us through the preview,  my colleague Rohit Agarwal posted a blog that summarizes the changes done to the Calendar, Contacts and Mail APIs in a nice concise way. Check it out here. As Rohit is looking out for the APIs, my focus is more on the authentication part, and especially on how to use OAuth2 to our APIs. If you missed my previous posts, check them out here:

     

    ·        Using OAuth2 to access Calendar, Contact and Mail API in Office 365 Exchange Online

    ·        Managing user consent for applications using Office 365 APIs 

    ·        Enabling Microsoft Azure portal access to manage applications using the OAuth2 protocol

     

    While not much changed on the OAuth2 front I thought it might be a good idea to provide a way to explore how OAuth2 works with our APIs. Over the past month this idea materialized in a little web app called "Office 365 OAuth Sandbox". It allows you to see how the OAuth2 protocol works with Azure AD, and see some limited pre-canned APIs in action that you might find useful. It is available on https://oauthplay.azurewebsites.net.

     

    Before you check it out I want to make you aware of some points:

     

    First the app uses the OAuth2 code flow as described Authorization Code Grant Flow.

     

    Second, the app can be used in two modes. One mode allows you to use your own Office 365 user account to see the OAuth2 Consent and afterwards play with the pre-canned APIs. If you don't have an Office 365 tenancy or don't trust the web app to not do any harm, a second mode allows you to play with a sandboxed Office 365 tenant and a few different sandbox users that are setup with pre-populated data. The app prefills a sandbox account for you in the sign-on dialog. The password is displayed when hovering over the "Authorize using sandbox account" button.

     

    Finally if you chose the mode to use your own Office 365 user account, remember you can always revoke access to the web app at https://myapps.microsoft.com.

     

    Note if you use the sandboxed Office 365 tenant you might or might not see the Consent Dialog, as probably many people use the sandboxed tenant and already consented to the app. In good Microsoft manner my Office 365 developer company is Contoso. This means if you see the Consent Dialog you will see that the web app is developed by Contoso. The web itself is hosted in Windows Azure.


    Other than that all the pre-canned API calls are read-only to the Office 365 data, but more important the app only asks and gets permissions to read calendar, contacts and mail data. The app never asks or is given any manipulative permissions to data. The read-only API calls are the same, regardless if you chose to use the sandboxed or your own Office 365 tenant.

     

    Now, all I can add is to encourage you to play with the web app and listen to your feedback on the blog channel. But before I finish this blog, I want to say special thanks to my colleague Alex Park, as without him the web app would not have been available in this form to you. Also thank you to Shreedevi Padmasini who helped with great ideas, readjusted the pre-canned queries and helped getting all the sandbox Office 365 infrastructure in place.

     

    With this. Happy play on https://oauthplay.azurewebsites.net.

     

    Let us know how you like it!

     

    Thank you!

    Matthias Leibmann

     

     

    FAQ:

    Q: Why can't I play around with the APIs in the Office 365 OAuth2 sandbox?

    A: The Office 365 OAuth2 Sandbox main goal was to show how the on-the-wire protocol looks like requesting access tokens for the Calendar, Contacts and Mail API. However we thought after getting access tokens you also want to see that those indeed work, thus we included some pre-canned APIs. However, there is a new API playground that focuses solely on playing with the API. Check it out, it is available here: http://apisandbox.msdn.microsoft.com

     

    Q: The Office 365 OAuth2 playground only works with the Calendar, Contacts and Mail API, but not any of the other APIs. What about those?

    A: Yes, that is true. We focused on showing the OAuth2 protocol and did not include all possible APIs. For this we do have the new API Playground (http://apisandbox.msdn.microsoft.com) that allows you to play with all the Office 365 APIs. You can get additional access tokens for these APIs by following the protocol as documented in Refresh Tokens for Multiple Resources.

     

    Q: What other OAuth2 flows are available to build apps against the Office 365 APIs?

    A: We are still working very hard to make the client credential flow (as described here) work briefly after GA, hopefully by end of the year. I will blog about this as soon as it is available.

     

    Q: Can I use OpenID connect to provide SSO into my web app with an Organizational Account in Office 365

    A: Yes, absolutely. We want you to use OpenID connect for all web apps that want to do SSO with Office 365. AAD supports OpenID connect as described in following article: OpenID Connect. There is also an example of using Calendar, Contacts, and Mail API from a single tenant ASP.NET MVC app using OpenId Connect available on Github here.

     

    Q: Are there any more examples that help me quick start my project?

    A: Absolutely yes. Check out https://github.com/OfficeDev for Office 365 examples or https://github.com/AzureADSamples. Fresh from the press is following Windows Store example for Calendar, Contacts and Mail API: https://github.com/OfficeDev/Office-365-APIs-Starter-Project-for-Windows.

     

     

     

     

     

    Viewing all 108 articles
    Browse latest View live


    Latest Images