Nylas API Contacts CRUD Now Supports iCloud

Now with the support for iCloud contacts, developers can interface with more CRUD-supported, information-dense contacts.

Previously, we wrote about our development process for shipping the very beginnings of our Contacts v2.0 upgrade which allows developers to sync contact profiles from address books (like Gmail contacts) into SaaS applications with full CRUD features. The initial release allowed developers to sync contacts from Gmail, Microsoft Exchange, Outlook.com, and Office 365 accounts.

We’re continuing to build these features to service more types of accounts, and we recently released bi-directional sync and CRUD for iCloud contacts. Now with support for iCloud contacts, developers can interface with more CRUD-supported, information-dense contacts:

Before

 

null

 After

 

null

 

While integrating Contacts v2.0 for iCloud, we ran into a few challenges around multipart formatting, type mapping, and the management of codebase complexity with one-off adaptations for both multipart formatting and type mapping:

Multipart Formatting

One substantial hurdle we faced during this build out process was translating between the different contact providers and our contact models. Each contact provider has its own system and format for collecting contact data. Google has a straightforward interface for its contacts API called gdata, Exchange Active Sync uses tokenized XML through “devices,” and iCloud follows the IETF standard of vCard.

The vCard format that iCloud implements looks like:

BEGIN:VCARD
VERSION:3.0
UID:123456789
N:Appleseed;John;;;
FN:John Appleseed
NOTE:Good notes
PHOTO;VALUE=uri;X-ABCROP-RECTANGLE=ABClipRect_1&0&205&1115&1115&hP6x6elkonMVk3k9ibig1g==:https://p41-contacts.icloud.com:000/1234567/wbs/abc123
item1.ADR;TYPE=WORK;TYPE=pref:;;695 Minna St;San Francisco;CA;;United States
item1.X-ABADR:us
TEL;TYPE=CELL;TYPE=pref;TYPE=VOICE:(415) 604-9500
item2.URL;TYPE=pref:http://nylas.com
item2.X-ABLABEL:_$!<HomePage>!$_
X-AIM;TYPE=HOME;TYPE=pref:aimaddress
IMPP;X-SERVICE-TYPE=aim;TYPE=HOME;TYPE=pref:aim:aimaddress
EMAIL;TYPE=WORK;TYPE=pref;TYPE=INTERNET:info@nylas.com
REV:2018-01-01T00:00:00Z
END:VCARD

In addition, the parts within a single vCard are different in formatting in small, nuanced ways. Take ADR for example: It follows the format of “{Post Office Address};{Extended Address};{Street};{Locality};{Region};{Postal Code};{Country},” but when iCloud interfaces with the vCard format, the first two parts, Post Office Address and Extended Address, are overall ignored. 

item1.ADR;TYPE=WORK;TYPE=pref:;;695 Minna St;San Francisco;CA;;United States

There were many other tiny details regarding multipart formatting that significantly slowed down the development process when interfacing directly with the vCard format. We learned that interface documentation (like the vCard format, for example) can only take you so far because implementations (like iCloud) follow details that other providers don’t and remedying this requires testing as many types of contact information as possible. Through the testing process, we also discovered that any name or address that included a semicolon within each contact was always incorrect. 

 

Type Mapping

As another added complexity to the translation, we learned that on top of weird formatting nuances, iCloud fields also have type mappings that are somewhat unintuitive. 

Remember that IMAP example from before?

IMPP;X-SERVICE-TYPE=aim;TYPE=HOME;TYPE=pref:aim:aimaddress

You’ll notice that the URI value aim:aimaddress also prepends a protocol and colon; in this case, it’s aim.  Instead of a one-to-one mapping from IMAP service to protocol, the mapping is sometimes many-to-one: both AIM and ICQ use the OSCAR protocol, and iCloud labels this protocol aim. Similarly, QQ and Gadu-Gadu are both labelled with the x-apple protocol.

Although vCard fields like TEL label types with TYPE, IM addresses are different in that they have more “types.” The most important of all is provider, and it’s labeled with X-SERVICE-TYPE.

IMPP;X-SERVICE-TYPE=aim;TYPE=HOME;TYPE=pref:aim:aimaddress

Another example is phone type mappings: A phone labelled as “Home fax” on an iCloud contact is represented as TYPE=HOME;TYPE=FAX instead of TYPE=HOME FAX. The same is true for a phone labelled as “Work fax”: It’s labelled as TYPE=WORK;TYPE=FAX instead of TYPE=WORK FAX.

Determining these complicated mappings required testing with a single contact that had multiple different types of phone numbers and IM addresses. This made it easier to work around these hurdles.

 

Managing Codebase Complexity

The growth of our codebase with one-off adaptions for different fields and types was a second order effect of the disconnect between interface and implementation. It made our code reviews harder because the iCloud contacts sync was intermingled with the translation between the vCard and contact, so there was no clear delegation of tasks.

About 2/3 of iCloud v2.0 upgrade’s development was simply this translation. The first half was the pulling of contacts from iCloud, and this complexity was doubled when translating the other way around with CRUD functionality. We realized that we needed a separate adaptor to service the needs of the two-way translation.

Separating the sync and translation functionalities by creating an adaptor solely for iCloud translation reduced our sync logic code by 60% and made our system even more modular. It also made our code reviews a lot easier, which we love!

But reducing all of this complexity for our customers also means that using the Nylas API removes the nightmare of interfacing with implementation-specific details of large protocols and substitutes it with a simple and pleasant experience.

We’d love for you to try it out: head over to our API docs or one of our SDKs to get started.

About Author

Nathan Ju

Subscribe to Engineering Blog Updates

Start Developing Today

Connect up to 10 accounts (email, calendar, and contacts) for free today.

Start Free Trial