- Products
- Solutions Use casesBy industry
- Developers
- Resources Connect
- Pricing
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
After
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:https://www.nylas.com item2.X-ABLABEL:_$!!$_ 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:[email protected] 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 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
. instead of
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.
Nylas was founded in 2013 with a mission to power the communications layer of the modern technology stack. Our universal APIs for email, calendar, and contacts are used by tens of thousands of developers across more than 25 countries.