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.
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
nsIAbManagerand implemented as
AddrBookManager. You can get a reference to the manager at
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
- By unique identifier (UID). For example
- By location in the preferences. Directories store their preferences at
nsIAbManageralso defines the
DIRECTORY_TYPEconstants mentioned below.
Individual address books are referred to as "directories" or "books" in the code. They implement
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 from
AddrBookDirectory. Directories of this type have URIs with the scheme
jsaddrbook, and are of type
SQLiteDirectoryby adding CardDAV capabilities. Directories of this type have URIs with the scheme
jscarddav, and are of type
AddrBookDirectoryand adds LDAP capabilities. Directories of this type have URIs with the scheme
moz-abldapdirectory, and are of type
nsAbDirPropertyprovides a base C++ implementation of
nsIAbDirectoryto OS-specific address books
nsAbOutlookDirectory. These are both of type
MAPI_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
Directories contain contacts or "cards", which implement the interface
nsIAbCard. The are accessible by the
childCardsproperty 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
AddrBookCardfor all of the JS code, or
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.
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
nsIAbCard, depending on the situation. Directories provide an array of their mailing lists as
childNodesproperty. They also appear as
childCardsproperty and some of the methods that handle cards.
A mailing list can not have any
childNodesof its own. However in a confusing quirk, it can have the card of another mailing list in its
Mailing lists are implemented in
The address book code fires observer service notifications. The notification names should be self-explanatory.
In all cases the "subject" of the notification is the directory.
- addrbook-directory-updated – the "data" contains the property that changed, and only the "DirName" property can change
- 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
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-properties-updated – "data" contains a JSON-stringified object containing the old and new values of any properties that changed
In these cases the "subject" of the notification is the list as
nsIAbDirectoryand "data" is the parent directory's UID.
In these cases the "subject" is the contact in question, and "data" is the list's UID.
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
SecondEmail, 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.
nsIAbCardgains two new members:
supportsVCarda boolean value indicating support for vCard (or lack thereof). Only
AddrBookCardobjects currently support vCard.
VCardPropertiesobject if the card supports vCard, or null.
VCardPropertiesclass contains methods for parsing, manipulating, and serialising vCards. Each piece of information in a card is represented by a
VCardPropertyEntryobject. See VCardUtils.jsm for more information.
In practice, we'll be storing the vCard data as just another key/value pair. The key used will be
_vCardand 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 (
- first and last names (
- first and second preference email addresses (
- nick name (
- 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.
No migration takes place when the user upgrades to a Thunderbird version that supports vCard. However at this point the version number of the database storage is incremented (from 3 to 4) and a backup is automatically created.
Cards are only migrated when they are saved.
nsIAbCard(any implementation) into a vCard string.
Mapof keys and values to a vCard string.
VCardUtils.vCardToAbCardconverts a vCard string to an
VCardProperties.fromVCardconverts vCard string to a
Mapof keys and values to a
VCardPropertiesobject to a
Mapof keys and values.
VCardPropertiesobject 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