June 2013

Volume 28 Number 6

Microsoft Office - Exploring the JavaScript API for Office: Mail Apps

By Angela Chu-Hatoun | June 2013 | Get the Code

This article is the fourth part of an in-depth look at the JavaScript API for Office, focusing on the portion of the API available to mail apps supported by Outlook and Outlook Web App. I assume you have some general understanding of apps for Office. If in doubt, reading the Dev Center documentation page, “Overview of apps for Office” (bit.ly/12nBWHG), will set you on the right path. Part 1 of this series, “Exploring the New JavaScript API for Office” (msdn.microsoft.com/magazine/jj891051), provides a high-level overview of the object model, which has the Office object as the root object. The Mailbox object, hanging off from Office.context, offers an entry point for most of the mail app-specific functionality in the object model, and this is where I’ll pick up the discussion.

The key takeaway of this article is what you, as a developer, can do with the JavaScript API for Office in mail apps. I’ve also provided an online companion article in which I walk through a sample mail app, complete with source code, at msdn.microsoft.com/magazine/dn205107. Now, I’ll discuss various features of the JavaScript API for Office, starting out with some of the more basic, commonly used techniques and then moving on to more advanced concepts.

Fundamental Features of the JavaScript API for Office

The Mailbox object provides access to the user profile, the item currently selected by the user, forms to display the item, and a subset of Exchange Web Services (EWS) to manipulate items and folders in the mailbox. The Item object represents the selected message or appointment item. Through that object, you can further access built-in properties, custom properties and attachments of that item.

Controlling Activation Based on Item Type You can define rules in the manifest to determine when to activate a mail app. The item currently selected by the user and specified by Mailbox.item can be a Message (including meeting requests, responses and cancellations) or an Appointment object. Depending on your scenario, you can restrict the mail app to activate for only a specific type of item. The following XML example shows an ItemIs activation rule that restricts the mail app to activate only for messages:

<Rule xsi:type="ItemIs" ItemType="Message" />

Using the JavaScript API for Office, you can use the itemType property to verify the type of the selected item:

Office.context.mailbox.item.itemType

Item Access and Properties One basic function offered by mail apps is accessing the currently selected item and its built-in properties.

The following JavaScript example shows how to access the selected item and its built-in property, subject:

// The initialize function is required for all apps.
Office.initialize = function () {
  // Check for the DOM to load.
  $(document).ready(function () {
    var item = Office.context.mailbox.item;
    var subject = item.subject;
    // Continue processing the subject.
  });
}

Well-Known Entities Exchange Server recognizes certain entities that are available regardless of whether you used entities to activate the mail app. Outlook and Outlook Web App extract these entities if they exist in the subject or body of the selected item and make them available through the following JavaScript API methods:

  • getEntities method
  • getEntitiesByType(entityType) method
  • getFilteredEntitiesByName(name) method

Supported entities include address, contact, email address and more.

Note that Outlook and Outlook Web Apps extract strings only in English regardless of the default locale you specify in the app manifest. They can’t extract entities in the Sent Items folder. And they can extract meeting suggestions in messages but not in appointments.

Getting Matches That Result in Contextual Activation You can specify activation rules that depend on regular expression matches (ItemHasRegularExpressionMatch rules) or entity matches (ItemHasKnownEntity rules) in the selected item. You can use the following methods to get regular expression matches. These methods are available on the parent Item object, which can be a message or appointment:

  • getRegExMatches method
  • getRegExMatchesByName(name) method

You can use the methods listed in the Well-Known Entities section to get specific entity matches. Note that you can always use these methods to get any entity matches regardless of the type of activation rules you use for the mail app.

Examples The following is an example of an ItemHasRegularExpressionMatch rule, named VideoURL, which activates the mail app if the selected item is a message and the message body contains a URL for a video on YouTube:

<Rule xsi:type="RuleCollection" Mode="And">
  <Rule xsi:type="ItemIs" ItemType="Message"/>
  <Rule xsi:type="ItemHasRegularExpressionMatch"
    RegExName="VideoURL"
    RegExValue="https://www\.youtube\.com/watch\?v=[a-zA-Z0-9_-]{11}"
    PropertyName="Body"/>
</Rule>

The following JavaScript code sample shows how to use the Item.getRegExMatches method to get the matches of the preceding VideoURL regular expression:

Office.initialize = function () {
  // Check for the DOM to load.
  $(document).ready(function () {
    // Get an array of string matches for the regular expression VideoURL,
    // as specified in the manifest.
    var matches = Office.context.mailbox.item.getRegExMatches().VideoURL;
    // Continue processing the matches for the regular expression.
    });
}

The following is an example of an ItemHasKnownEntity rule that activates the mail app if an address is present in the subject or body of a message:

<Rule xsi:type="RuleCollection" Mode="And">
  <Rule xsi:type="ItemIs" ItemType="Message"/>
  <Rule xsi:type="ItemHasKnownEntity" EntityType="Address" />
</Rule>

The following JavaScript code sample shows how to use the getEntitiesByType method to get an array of strings that are postal addresses in the subject or body of the currently selected message:

Office.initialize = function () {
  // Check for the DOM to load.
  $(document).ready(function () {
    var item = Office.context.mailbox.item;
    // Get an array of strings that represent postal
    // addresses in the current item.
    var addresses = item.getEntitiesByType(
      Office.MailboxEnums.EntityType.Address);
    // Continue processing the array of addresses.
  });
}

Activating a mail app based on contexts—especially regular expression matches or the existence of well-known entities—is powerful and can be complicated to debug. See the MSDN Library article, “Troubleshooting mail apps activation,” at bit.ly/11C0H30 for tips on how to debug activation issues.

Data Storage Per Item Per App The CustomProperties object lets you store item-specific data that only your mail app can access as a custom property on the item in a subsequent session. Such data is represented as key-value pairs. If the app is designed to run on multiple Outlook clients and form factors, the custom properties roam with the supported Outlook client and form factor.

The custom properties for an item are available through the Item.loadCustomPropertiesAysnc method. This is an asynchronous method that takes a callback method as a parameter. When the custom properties are loaded, they’re available through the asyncResult.value property, which is passed to the callback method as an input parameter. Figure 1 shows how to load, get, set and save custom properties for the current item.

Figure 1 Working with Custom Properties for the Current Item

Office.initialize = function () {
  var mailbox = Office.context.mailbox;
  mailbox.item.loadCustomPropertiesAsync(customPropsCallback);
}
function customPropsCallback(asyncResult) {
  if (asyncResult.status == Office.AsyncResultStatus.Succeeded) {
    var customProps = asyncResult.value;
    var myProp = customProps.get("myProp");
    customProps.set("otherProp", "value");
    customProps.saveAsync(saveCallback);
  }
  else {
    write (asyncResult.error.message);
  }
}
function saveCallback(asyncResult) {
  // Callback method to save custom properties.
}

Data Storage Per Mailbox Per App The RoamingSettings object lets you store custom data that your mail app can access for the same mailbox regardless of whether the mail app is running on a desktop, tablet or smartphone. The following JavaScript example shows how to get mailbox-specific data in the initialize event handler of the mail app:

var _mailbox;
var _settings;
Office.initialize = function () {
  // Check for the DOM to load using the jQuery ready function.
  $(document).ready(function () {
    // Initialize instance variables to access API objects.
    _mailbox = Office.context.mailbox;
    _settings = Office.context.roamingSettings;
    // Continue with app-specific code.
  });
}

User Profile You can access the user’s profile using the Office.context.mailbox.userProfile property. Through the UserProfile object, you can get the display name, SMTP address and the local time zone of the signed-in user. The following JavaScript code sample shows how to access the UserProfile.emailAddress property of the current user signed in to Outlook or Outlook Web App:

Office.initialize = function () {
  // Check for the DOM to load.
  $(document).ready(function () {
    var userProfile = Office.context.mailbox.userProfile;
    var SMTPAddress = userProfile.emailAddress;
    // Continue with processing the user's SMTP address. 
  });
}

Displaying Outlook Forms In Outlook a user can specify forms to display appointments and messages by default. Using the following methods in the JavaScript API for Office, a mail app can display an appointment and message respectively, using the same forms that Outlook uses:

  • Mailbox.displayAppointmentForm(itemId)
  • Mailbox.displayMessageForm(itemId)

The code in Figure 2 checks to see if the user has selected an appointment and displays it with the Outlook default appointment form.

Figure 2 Checking to See If User Has Selected an Appointment

var myOm;
var myItem;
Office.initialize = function () {
  $(document).ready(function () {
    myOm = Office.context.mailbox;
    // Get the selected item.
    myItem = myOm.item;
    // Display the selected appointment.
    displaySelectedAppointment();
  });
}
function displaySelectedAppointment() {
  // Display selected item only if the item is an appointment.
  if (myitem.itemType == Office.MailboxEnums.ItemType.Appointment)
  {
    myOm.displayAppointmentForm(myItem.itemId);
  }
  else
  {
    // Handle condition as appropriate.
  }
}

The Mailbox.displayNewAppointmentForm method allows you to assign values to certain fields in an appointment form for a new meeting and display the form for the user to fill in the appointment. When calling this method, specify these fields as a list of string-value pairs, as shown in Figure 3.

Figure 3 Assigning Values to Specific Fields in a New Appointment Form

var myOm;
Office.initialize = function () {
  $(document).ready(function () {
    myOm = Office.context.mailbox;
    // After the DOM is loaded, can display the
    // pre-populated new appointment form.
    displayFormForNewAppointment();
  });
}
function displayFormForNewAppointment(){
  var formParameters =
  {
    "requiredAttendees" : ["wendy@contoso.com", "derek@contoso.com"],
    "optionalAttendees" : ["shane@contoso.com", "michael@contoso.com"],
    "start" : new Date("September 27, 2012 11:15:00"),
    "end" : new Date("("September 27, 2012 12:30:00"),
    "location" : "Conf room 200",
    "resources" : ['sound', 'lighting', 'recording'],
    "subject" : "Next rehearsal",
    "body" : "This is about the next rehearsal."
  }
  // Display a form to create an appointment with
  // the specified fields in the form.
  myOm.displayNewAppointmentForm(formParameters);
}

The methods that display reply forms to an appointment or message offer the most room for customization:

  • Appointment.displayReplyAllForm(htmlBody) method
  • Appointment.displayReplyForm(htmlBody) method
  • Message.displayReplyAllForm(htmlBody) method
  • Message.displayReplyForm(htmlBody) method

With each of these methods, you can provide an HTML string that represents the body of the reply form. The example in Figure 4 displays a reply-all form for a message.

Figure 4 Specifying the HTML for a Reply-All Form for a Message Item

var myOm;
var myItem;
Office.initialize = function () {
  // Check for the DOM to load.
  $(document).ready(function () {
    myOm = Office.context.mailbox;
    // Get the selected item.
    myItem = myOm.item;
    // After the DOM is loaded, display
    // the reply form.
    displayReply();
  });
}
function displayReply(){
  // Display a reply form to the sender and recipients only
  // if the selected item is a message.
  if (myitem.itemType == Office.MailboxEnums.ItemType.Message) {
      myItem.displayReplyAllForm
      ("<html><head><head><body>This is the body of " +
       "the email reply.</body></html>");
  }
}

Advanced Concepts

Getting Item Attachments A mail app can use the JavaScript API for Office and EWS callback tokens to access attachments of the currently selected message or appointment in the user’s mailbox. The use of the callback token allows back-end, server-side code of the mail app—or third-party Web services—to call the EWS operation, GetAttachment, to actually get the specific attachments.

The following describes how a mail app gets attachments (this process is also illustrated in Figure 5):

  1. A mail app uses Mailbox.getCallbackTokenAsync to request a callback token, uses Item.attachments to get metadata about the attachments of the selected appointment or message (including attachments IDs), and uses Mailbox.ewsUrl to get the URL of the EWS endpoint for the current e-mail account.
  2. The mail app passes the callback token, attachment IDs and URL of the EWS endpoint to the server-side code.
  3. The server-side code calls the EWS GetAttachment operation to get the actual attachments from that Exchange store.

Mail Apps Accessing Attachments from an Exchange Server
Figure 5 Mail Apps Accessing Attachments from an Exchange Server

Note that the server-side code should access EWS by directly creating EWS requests. You can’t use the Mailbox.makeEws­RequestAsync method to access the GetAttachment operation. As of this writing, accessing attachments is supported if the mail app runs on Outlook Web App. The feature isn’t available if the mail app is running in Outlook.

See the MSDN code sample, “Mail apps for Office: Get attachments from an Exchange server” (bit.ly/11dG9fS), for an example of how to access attachments in a mail app.

User Token for Single Sign-On Your mail app can use common authentication Web techniques to authenticate and authorize users. If you want to support single sign-on authentication for your users across Outlook and Outlook Web App, you can use Exchange identity tokens by calling the Mailbox.getUserIdentityTokenAsync method.

Single sign-on is based on an Exchange Server assigning an Exchange identity token for the user’s e-mail account on that Exchange Server. An Exchange identity token contains multiple fields, among which are a signature for validating the token and a unique identifier representing the Exchange e-mail account.

In general, a mail app that authenticates users can interact with a Web service—which can be server-side code for the mail app—or a third-party Web service, which uses its own Identity Provider (IdP) to validate user identity in a federated identity system. The key to single sign-on is the mapping that the Web service maintains between the unique ID (from the Exchange identity token) and the user identity (which is known to the IdP).

Figure 6 provides a high-level description of using Exchange identity tokens for authentication.

The following summarizes the process:

  1. The mail app calls Mailbox.getUserIdentityTokenAsync to request an Exchange identity token for the user, specifying a callback method that runs when the asynchronous get operation completes.
  2. The callback function gets the Exchange identity token and passes it to the Web service for authentication.
  3. The Web service gets a public key from the Exchange Server to validate the token.
  4. Depending on whether the user has signed in before, the Web service proceeds as follows:
    1. If it’s the first time the user signs in to the mail app, no prior mapping exists for that account, and the Web service responds to the mail app to prompt the user for credentials. Upon receiving the credentials, the mail app passes them to the Web service.
    2. The service then creates a mapping between the unique ID provided by the token and the user identity from the credentials that are well-known to the IdP. Using the credentials, the service can log in the user.
    3. On subsequent times: When the user opens the mail app in Outlook or Outlook Web App from a desktop, tablet or browser on a smartphone, the following steps occur:
      1. The mail app calls getUserIdentityTokenAsync and gets the same unique ID in the token
      2. The mail app passes the token to the Web service.
      3. The Web service validates the token.
      4. The Web service then looks up the mapping table, finds the user and authorizes access.

Authentication Using Exchange Identity Tokens
Figure 6 Authentication Using Exchange Identity Tokens

Once you validate the token, you can keep the user logged in, even when the user opens the mail app from another host application or device.

The details for authentication and validation are fairly complex. You can use an EWS Managed API Validation Library to simplify the process. Using that Validation Library, a Web service would create an object, extract and put the token into the object, verify if the signature is valid, and if it’s valid, then put the unique identifier in the mapping database.

For more information about using Exchange identity tokens for authentication, see the following Dev Center documentation:

  • “Authenticating a mail app by using Exchange identity tokens” (bit.ly/ZYaZ9v)
  • “Inside the Exchange identity token” (bit.ly/ZxRogq)
  • “How to: Call a service by using an identity token in Exchange” (bit.ly/12jqxcU)
  • “How to: Use the Exchange token validation library” (bit.ly/11akmEg)
  • “How to: Validate an Exchange identity token” (bit.ly/15im6SO)
  • “How to: Authenticate a user with an identity token for Exchange” (bit.ly/13gZ36T)

For code samples:

  • You can refer to “Mail apps for Outlook: Use a client identity token” sample in C# for Visual Studio 2012 (bit.ly/ZxS85b) for a C# example of a mail app and a Web service that use Exchange identity tokens for authentication.
  • See “Mail apps for Outlook: Validate a client identity token using the .NET Framework” (bit.ly/17j9FSZ) for an example of how to use the .NET Framework to validate Exchange client identity tokens.

Access to a Subset of EWS Using the Mailbox.makeEwsRequestAsync method, mail apps can access a subset of EWS operations to create, find, get, update, move, or send an item or folder. For example, you can use the CreateItem operation to create an appointment, message or contact. You can use the FindItem operation to look up items in a mailbox. And you can use the SendItem operation to send a message or meeting invitation. The supported subset of operations pertains to only the user’s mailbox. Other EWS operations that pertain to an entire organization—such as accessing the Global Address List or iterating through every person in the organization—are off limits to mail apps. Also, because the supported subset of operations is powerful, mail apps must request read/write mailbox permission in the app manifest, and only administrators can install mail apps requiring such permission.

When you call the Mailbox.makeEwsRequestAsync method, you’re requesting EWS on the Exchange Server that hosts the user’s mailbox. Before calling makeEwsRequestAsync, specify input arguments for the following parameters:

  • data parameter: Create an XML SOAP request for the EWS operation you intend to call.
  • callback parameter: A callback method that would handle the response from the operation.
  • userContext parameter: Any input data for the callback method.

When the operation finishes, the apps for Office framework calls the callback method with one argument, which is an AsyncResult object, similar to the other asynchronous methods that you’ve seen in the first part of this series. The callback method can access the Async­Result.value property to get the XML SOAP response that contains data relevant to the operation. The callback method can also access the AsyncResult.asyncContext property to access any other input parameter passed in through the userContext parameter. The callback method then parses the XML in the SOAP response to get the data relevant for its purposes.

For a complete list of supported EWS operations and further details, see the Dev Center documentation, “Calling Web services from a mail app for Outlook” (bit.ly/12jtH0z).

For an example of a mail app that demonstrates calling the GetItem operation, see “Mail apps for Outlook: Make an EWS request” sample in C# for Visual Studio 2012 (bit.ly/Zv3hEQ).

Wrapping Up

That wraps up my discussion of building mail apps, as well the four-part exploration of the JavaScript API for Office. For the previous installments in this series, and the online companion article for this installment, see:


Angela Chu-Hatoun started as a software developer and switched to writing for her greater interest in explaining how software works. She has been a programmer writer in the Office Division for 12 years, and writes for developers about creating apps for Office and other solutions for Outlook. She enjoys reading about current affairs, gardening, travelling, food and fashion.

Thanks to the following technical experts for reviewing this article: Andrew Salamatov (Microsoft) and Tim Wan (Microsoft)
Tim Wan graduated from Caltech in 2003 and holds a degree in Engineering and Applied Sciences. For the past nine years he has been a software developer in Outlook. He worked extensively on the mail apps feature in Outlook 2013, as well as the Outlook Object Model in previous releases. He looks forward to bringing new features and improvements to customers worldwide.