Ruby gem for Mail, Calendar, and Contacts APIs

Today I published a new Ruby on Rails sample, the Office 365 VCF Import/Export Sample. It's basically a simple tool that allows a user to export contacts from her Office 365 mailbox to vCard files, or import vCard files into her contacts.

But wait, there's more! Instead of implementing the Contacts API in the sample, I created a separate Ruby gem and implemented a portion of the Mail, Calendar, and Contacts APIs. That gem is published on rubygems.org for you to install and use in your projects.

vCard Import/Export

The look and feel of the sample app owes a LOT to the great work done by Michael Hartl in his Ruby on Rails Tutorial.

The sample app basically uses the Contacts API in two ways: to create new contacts and to get existing contacts.

Getting the contacts list

When the user signs in, the app presents a list of existing contacts, sorted alphabetically by display name. The list is paged, showing 30 contacts at a time. Here's what that looks like using the ruby_outlook gem:

  # Maximum 30 results per page.
 view_size = 30
 # Set the page from the query parameter.
 page = params[:page].nil? ? 1 : params[:page].to_i
 # Only retrieve display name.
 fields = [
 "DisplayName"
 ]
 # Sort by display name
 sort = { :sort_field => 'DisplayName', :sort_order => 'ASC' }
 
 # Call the ruby_outlook gem
 wrapped_contacts = outlook_client.get_contacts user.access_token,
 view_size, page, fields, sort
 

The wrapped_contacts variable is a JSON hash of the returned contacts.

Getting details on a single contact

When the user clicks the "Export" button for a contact, the app gets all fields for that single contact, using its Id. Here's how that's done with the ruby_outlook gem:

  outlook_client = RubyOutlook::Client.new
 
 # Call the ruby_outlook gem to get the contact from its ID
 contact = outlook_client.get_contact_by_id current_user.access_token, contact_id
 

The contact variable is a JSON hash of all the fields of the contact. That is used to build a vCard stream, which the user can download.

Creating a new contact

When the user clicks the "Import" button on the main page, they are given the option to enter vCard data manually, or to open a local vCard file for import.

When the user clicks "Import" on this page, the vCard data is transformed into a JSON hash conforming to the Contact entity defined by the Contact API. It then uploads that to the server via the ruby_outlook gem:

  outlook_client = RubyOutlook::Client.new
 response = outlook_client.create_contact current_user.access_token, contact
 

The contact variable contains the JSON hash of the new contact, and the response variable contains the JSON hash that's returned by the server after creation.

More on the ruby_outlook gem

The gem doesn't just implement the Contacts API. It implements the following:

  • Contacts API: CRUD, including a "get by ID" function.
  • Calendar API: CRUD, including a "get by ID" function and a calendar view function.
  • Mail API: CRUD, including a "get by ID" function. Also implements a send mail function.

You may have noticed that there's a lot here that isn't implemented. For the stuff that isn't there, I created a make_api_call function that allows you to call any part of the API that you need. If you look at the source for the gem, you'll notice that all of the implemented functions (like get_contacts for example), use the make_api_call to do the actual work. Following their example, you can implement any other API call you want. Let's take a look at an example.

  # method (string): The HTTP method to use for the API call. 
 # Must be 'GET', 'POST', 'PATCH', or 'DELETE'
 # url (string): The URL to use for the API call. Must not contain
 # the host. For example: '/api/v1.0/me/messages'
 # token (string): access token
 # params (hash) a Ruby hash containing any query parameters needed for the API call
 # payload (hash): a JSON hash representing the API call's payload. Only used
 # for POST or PATCH.
 def make_api_call(method, url, token, params = nil, payload = nil)
 

Using the gem to create a folder

The gem currently has no functions for working with mail folders. However, you can use the make_api_all function to do the work. The details on creating a folder are documented here. Using that information, you can do the following to create a subfolder in the Inbox:

  outlook_client = RubyOutlook::Client.new
 
 create_folder_url = '/api/v1.0/me/folders/inbox/childfolders'
 new_folder_payload = { 'DisplayName' => 'New Subfolder' }
 
 create_result = outlook_client.make_api_call('POST', create_folder_url, 
     token, nil, new_folder_payload)
 

Using similar methods you should be able to call anything that the APIs support.

Go download the gem, the sample, or both! As always, I'd love to hear your feedback in the comments or on Twitter (@JasonJohMSFT). Feel free to report issues or submit pull requests on GitHub!