Skip to content

Contacts

Users keep their contacts on phones, laptops and webmail at once, and expect a change made in one place to appear everywhere. Stalwart stores address books for every account and serves them over JMAP for Contacts and CardDAV, so that contacts can be kept and synchronised across devices and applications. This page describes how clients reach the address books and the limits and defaults an administrator configures. It also explains how contact UIDs and searches behave, and how the spam filter uses address books.

JMAP for Contacts (RFC 9610) is an alternative to CardDAV, built on the same JSON foundation as the other JMAP specifications. Clients manage address books and contacts through JSContact, a schema-defined JSON representation of contact data. CardDAV relies on XML-based WebDAV extensions and on the vCard format, and JMAP for Contacts replaces both layers with JSON objects and operations.

CardDAV is a standardised extension of WebDAV, through which clients work with contact data stored on a server. It gives contact applications on desktop and mobile platforms, including Apple Contacts and Thunderbird, an interoperable way to manage personal and shared address books. Through CardDAV, contacts are created and edited, organised into address books and synchronised across devices. The same data is available to JMAP clients, so a change made in one kind of client appears in the other.

The recommended way to configure a CardDAV client is through the autodiscovery endpoint at /.well-known/carddav. A client that queries this path is redirected to the CardDAV resource of the authenticated account.

Clients configured manually can use the direct path /dav/card/<account_name>, where <account_name> is the username of the account. The address books of the account alice, for example, are at /dav/card/alice. Both methods lead to the same contact data.

Address-book-wide limits are set on the AddressBook singleton, found in the WebUI under Settings › Calendar & Contacts › Address Book.

maxVCardSize is the largest single vCard object the server accepts, 512 KiB by default. It can be raised or lowered to suit the cards that clients are expected to submit.

In JMAP, one contact card can belong to several address books, and maxAddressBooksPerCard limits how many. Cards can also carry embedded media, and maxMediaSize limits the total size of the photos, logos, sounds and keys embedded in one card, 2 MiB by default.

The JMAP ContactCard/parse method is bounded by parseLimitContact on the Jmap singleton, which sets the largest number of vCard items parsed in a single request. The Jmap singleton is found in the WebUI under Settings › Network › JMAP › Limits, Settings › Network › JMAP › Push, Settings › Network › JMAP › WebSocket.

The vCard format exists in two versions in common use, and clients differ in which one they handle. Cards are returned to CardDAV clients in the vCard version they request. For clients that do not request one, vCardVersion selects it, v4 by default. The values are v4 (vCard 4.0, RFC 6350) and v3 (vCard 3.0, RFC 2426).

The UID of a contact card identifies it across clients, so it has to stay stable. Once set, it can never be removed or changed. A UID can still be added to a card that has none, provided no other card in the address book uses it. Requests that break these rules fail:

  • Over CardDAV, a PUT that changes or removes the UID, or that adds a UID already used by another card, fails with 403 Forbidden and the precondition CARDDAV:no-uid-conflict, which names the existing card.
  • Over JMAP, ContactCard/set fails with invalidProperties and the description You cannot change the UID of a contact.

CardDAV clients do not always spell the same UUID the same way, and Stalwart tolerates the differences. A UID written with or without the urn:uuid: prefix, or in a different letter case, is accepted as the same UID. The stored spelling is kept, and the PUT returns 204 without an ETag. JMAP compares UIDs exactly.

CardDAV addressbook-query reports compare text using a collation, a named rule for comparing strings. The collations come from RFC 4790 and RFC 5051, and each address book lists the ones it supports in its supported-collation-set:

CollationComparison
i;unicode-casemapCase-insensitive for all Unicode text. The default for CardDAV.
i;ascii-casemapCase-insensitive for ASCII letters only.
i;octetExact byte comparison.

The default match type is contains, as RFC 6352 section 10.5.4 specifies. A request that names any other collation fails with 403 and the precondition supported-collation.

To improve client compatibility, Stalwart creates a default address book when an account is accessed and has none, so contact operations proceed without manual setup. The address book is created under the account’s address book home, with the name set in defaultHrefName on the AddressBook singleton, default by default. Clients show it under the display name in defaultDisplayName, Stalwart Address Book by default, which can be changed to match the organisation’s branding or language.

A JMAP client sets the default address book with the onSuccessSetIsDefault argument of AddressBook/set, and AddressBook/get reports it in isDefault. The change applies only when every other change in the request succeeded, and only in the user’s own account. Until a default is set, the address book created first is the default.

Clearing defaultHrefName turns automatic creation off. Stalwart then creates no default address book, and an account has no address book until the user creates one.

The AddressBook singleton also caps the address book resources of each account. maxAddressBooks limits the number of address books an account can create, and maxContacts the number of contact cards. These values apply to every account unless they are overridden at the account or tenant level.

Address books also help the spam filter, which uses each account’s address book to recognise trusted senders. A message from a sender in the recipient’s address book is filed in the inbox even when its spam score is high, provided the sender is authenticated, by DMARC or by an authenticated submission. The score itself is not changed, as described in Inbox override. These messages can also train the spam classifier, as described in trusted senders.