Address Book
The Address Book code is found in two places: the UI is primarily in mail/components/addrbook, while the back end is in mailnews/addrbook. This documentation only describes the back end.
Interfaces and Classes
Address Book Manager
The address book manager is responsible for organising individual "directories" (address books), including reading the configuration from the preferences at start-up and creating the directory objects. It is defined by the interface nsIAbManager and implemented as AddrBookManager. You can get a reference to the manager at MailServices.ab.
The address book manager can get a reference to a particular directory in a number of ways:
By URI. Registered directories have a URI defined by the type of directory and any information needed to identify an individual directory. For example
jsaddrbook://abook.sqlite.By unique identifier (UID). For example
70139e91-37a5-47fd-8856-2f0756f43ef1.By location in the preferences. Directories store their preferences at
ldap_2.servers.<some identifier>.
nsIAbManager also defines the DIRECTORY_TYPE constants mentioned below.
Directories
Individual address books are referred to as "directories" or "books" in the code. They implement nsIAbDirectory.
There are different implementations:
A base class
AddrBookDirectorywhich handles most of the implementation detail using data provided by a sub-class. It should not be instantiated directly.The most common type is
SQLiteDirectorywhich, as the name implies, stores data in an SQLite database in the user profile. It inherits fromAddrBookDirectory. Directories of this type have URIs with the schemejsaddrbook, and are of typeJS_DIRECTORY_TYPE.CardDAVDirectoryextendsSQLiteDirectoryby adding CardDAV capabilities. Directories of this type have URIs with the schemejscarddav, and are of typeCARDDAV_DIRECTORY_TYPE.LDAPDirectoryextendsAddrBookDirectoryand adds LDAP capabilities. Directories of this type have URIs with the schememoz-abldapdirectory, and are of typeLDAP_DIRECTORY_TYPE.nsAbDirPropertyprovides a base C++ implementation ofnsIAbDirectoryto OS-specific address booksnsIAbOSXDirectoryandnsAbOutlookDirectory. These are both of typeMAPI_DIRECTORY_TYPE. The OS-specific types are likely to be discontinued.WebExtension APIs can provide contact suggestions to the user when composing messages. This is done via a
ASYNC_DIRECTORY_TYPEdirectory.
Contacts
Directories contain contacts or "cards", which implement the interface nsIAbCard. The are accessible by the childCards property as well as methods for searching, adding, modifying, and deleting contacts. (Confusingly a "card" can also refer to a mailing list, see below.)
Contacts are implemented by AddrBookCard for all of the JS code, or nsAbCardProperty in C++.
The current implementation stores contact data as key/value pairs. Work is underway to replace this with a more capable data storage based on the vCard format.
Mailing Lists
A mailing list (or just a "list" in many places) is a collection of contacts. To be added to a mailing list, a contact must have an email address. A mailing lists can be both nsIAbDirectory and nsIAbCard, depending on the situation. Directories provide an array of their mailing lists as nsIAbDirectory with the childNodes property. They also appear as nsIAbCard in the childCards property and some of the methods that handle cards.
A mailing list can not have any childNodes of its own. However in a confusing quirk, it can have the card of another mailing list in its childCards.
Mailing lists are implemented in AddrBookMailingList.
Notifications
The address book code fires observer service notifications. The notification names should be self-explanatory.
Notifications about directories
In all cases the "subject" of the notification is the directory.
addrbook-directory-created
addrbook-directory-updated – the "data" contains the property that changed, and only the "DirName" property can change
addrbook-directory-deleted
addrbook-directory-invalidated – many contacts changed, anything storing or displaying contacts should be thrown away and reloaded
addrbook-directory-synced – CardDAV sync succeeded
addrbook-directory-sync-failed – CardDAV sync failed
Notifications about contacts
In all cases the "subject" of the notification is the contact, and unless otherwise stated "data" contains the UID of the directory containing the contact.
addrbook-contact-created
addrbook-contact-updated
addrbook-contact-properties-updated – "data" contains a JSON-stringified object containing the old and new values of any properties that changed
addrbook-contact-deleted
Notifications about lists
In these cases the "subject" of the notification is the list as nsIAbDirectory and "data" is the parent directory's UID.
addrbook-list-created
addrbook-list-updated
addrbook-list-deleted
In these cases the "subject" is the contact in question, and "data" is the list's UID.
addrbook-list-member-added
addrbook-list-member-removed
Transition to vCard Storage
As mentioned above, contact properties are stored as key/value pairs. This has limitations in a modern address book:
There's a fixed set of keys. Although there's no real restrictions on keys you could use, no user interface is available for anything outside of the known keys.
Multiple values for the same key aren't possible. For example if a contact has three email addresses, the first two can be stored in
PrimaryEmailandSecondEmail, but there's nowhere to store the third.Storing meta information about the values is impossible. There's no way to mark an email address as a work address or a home address, for example.
To combat this, from Thunderbird 102 contacts stored in local directories will be converted to use the industry standard vCard format. CardDAV directories already use vCard, although the data was converted to key/value pairs so the UI could use it.
LDAP and OS-specific address books will continue to use keys/values.
New interface properties
nsIAbCard gains two new members:
supportsVCarda boolean value indicating support for vCard (or lack thereof). OnlyAddrBookCardobjects currently support vCard.vCardPropertiesis aVCardPropertiesobject if the card supports vCard, or null.
The VCardProperties class contains methods for parsing, manipulating, and serialising vCards. Each piece of information in a card is represented by a VCardPropertyEntry object. See VCardUtils.sys.mjs for more information.
Storage changes
In practice, we'll be storing the vCard data as just another key/value pair. The key used will be _vCard and the value will be the entire vCard.
When a card is saved to a directory, the following things happen:
If it supports vCard, the
vCardPropertiesmember is serialised.If it doesn't, the existing key/value pairs are converted to a
VCardPropertiesobject, then serialised.Some properties are collected from the card:
display name (
DisplayName)first and last names (
FirstNameandLastName)first and second preference email addresses (
PrimaryEmailandSecondEmail)nick name (
NickName)
The serialised vCard, these properties, and any key/value properties which can't be stored in a vCard are saved.
Any key/value properties which can be stored in the vCard are abandoned. No information is lost because the values are part of the vCard.
The names and addresses stored separately are for performance reasons. The vCard is considered the true source of information.
Data conversion between keys/values and vCard
VCardUtils.sys.mjs contains a number of utility functions for converting between the storage types:
VCardUtils.abCardToVCardconverts annsIAbCard(any implementation) into a vCard string.VCardUtils.propertyMapToVCardconverts aMapof keys and values to a vCard string.VCardUtils.vCardToAbCardconverts a vCard string to anAddrBookCard.VCardProperties.fromVCardconverts vCard string to aVCardPropertiesobject.VCardProperties.fromPropertyMapconverts aMapof keys and values to aVCardPropertiesobject.VCardProperties.prototype.toPropertyMapconverts aVCardPropertiesobject to aMapof keys and values.VCardProperties.prototype.toVCardconverts aVCardPropertiesobject to a vCard string.
Conversion from a key/value dictionary to vCard should not result in any data loss. In the other direction data loss is possible.
To see exactly what fields are converted and what they are converted to, see typeMap in VCardUtils.sys.mjs.
Last updated
Was this helpful?

