A SnappyMail plugin that automatically configures a CardDAV address book for every user on login — with zero per-user setup.
SnappyMail can sync contacts from a CardDAV server, but the sync settings (URL, username, password) are stored per account and must normally be entered by each user by hand. There is no built-in admin/global way to push one shared address book to everyone. This plugin closes that gap: on each successful login it writes the correct CardDAV config for that user and (optionally) pulls the contacts in.
It was built against MDaemon's per-user public address-book URLs, but the URL is fully templated, so it works with any CardDAV server that exposes a predictable per-user URL.
On the login.success hook, for each account that matches the domain filter, the plugin:
- Builds the CardDAV URL from a template using the account's email
(
{host},{domain},{local},{b64}placeholders). - Writes the contacts-sync config via SnappyMail's own
setContactsSyncData()— in read-only mode — reusing the user's login password as the CardDAV password. The password is handed to core as plaintext and core encrypts it exactly as the normal UI flow does; the plugin never stores a password itself. - Triggers a sync (optional) so the address book is populated immediately.
Because the CardDAV password is just the login password, the setup self-heals on password change: SnappyMail invalidates the stored (HMAC-checked) password, and the next login rewrites it.
Why the login password works as the CardDAV password: this assumes your mail server uses unified credentials (same password for IMAP and CardDAV), which is the case for MDaemon and most all-in-one mail servers.
- SnappyMail 2.27.0+
- In Admin → Contacts: Enable contacts (a DB backend selected) and Allow contacts sync (with external CardDAV server) must be enabled.
- A CardDAV server reachable from the SnappyMail server/container, with a valid TLS cert it trusts (a self-signed/untrusted cert makes sync fail silently — check the logs).
cd /path/to/snappymail/plugins # the dir that contains e.g. mailbox-detect/
git clone https://github.com/ggYasin/snappymail-carddav-autoconfig.git carddav-autoconfigOr download and drop the folder in as carddav-autoconfig/. Then:
- Admin → Extensions → enable CardDAV Autoconfig.
- Open its settings and configure the options below.
- Have a user log out and back in to apply.
The plugin folder may need to be owned by the web-server user (match the other plugins).
| Option | Default | Description |
|---|---|---|
| CardDAV host:port | mail.example.com:4433 |
Your CardDAV server host (and port). |
| Domain filter | allow |
allow = only listed domains · deny = all except listed · all = every domain. |
| Domains | example.com |
Comma-separated list used by allow/deny. Ignored when filter = all. |
| Folder name | ~public/{domain}/Contacts |
Server-side address-book folder; base64-encoded into {b64}. |
| CardDAV URL template | https://{host}/webdav/carddav/{domain}/{local}/b64={b64}/ |
Placeholders: {host} {domain} {local} {b64}. |
| Already-configured accounts | overwrite |
overwrite = always rewrite our config on login · keep = leave an account that already has a contacts-sync config untouched. |
| Trigger sync on each login | on |
Pull the address book on each login, or only write the config. |
| Non-blocking sync | on |
Run the sync after the login response is sent (PHP-FPM), so a slow/failing CardDAV server never delays or breaks login. Off = inline/blocking. |
| Min minutes between syncs | 5 |
Throttle: skip the sync if the account synced within the last N minutes. 0 = every login. |
For an address alice@example.com with the defaults, the generated URL is:
https://mail.example.com:4433/webdav/carddav/example.com/alice/b64=fnB1YmxpYy9leGFtcGxlLmNvbS9Db250YWN0cw/
where b64 is base64("~public/example.com/Contacts") with = padding stripped.
If you're unsure of the exact per-user URL, ask the server via CardDAV discovery (replace host/credentials):
# 1) find your principal
curl -k -u user@example.com:PASS -X PROPFIND https://HOST/.well-known/carddav \
-H "Depth: 0" -d '<d:propfind xmlns:d="DAV:"><d:prop><d:current-user-principal/></d:prop></d:propfind>'
# 2) find your address-book home-set (PROPFIND the principal href)
# 3) list address books (PROPFIND the home-set with Depth: 1) — note the b64=... collectionThe b64= segment decodes to the internal folder name (for MDaemon public folders:
~public/<domain>/Contacts).
- Read-only. Contacts sync down only; users can't push edits back to the shared book
(
Mode = 2). This is intentional for a shared/company directory. - One sync slot. SnappyMail supports a single CardDAV sync URL per account, so this replaces any personal CardDAV sync the user had configured.
- Login performance. With Non-blocking sync on (default), login is never delayed or failed by the sync — it runs in the background after the response is sent. The worker still does the sync work, so it briefly occupies one PHP-FPM slot per login.
- No duplicate contacts. SnappyMail's CardDAV sync has a read-then-insert race (no lock, no unique constraint on the UID), so overlapping syncs for one account would otherwise multiply contacts. This plugin serializes syncs with a per-account file lock (overlapping syncs are skipped) and throttles them. The lock uses the system temp dir, so it coordinates across PHP-FPM workers on a single host (not across multiple webmail hosts/containers).
- Static config UI. SnappyMail's plugin settings form only renders static fields, so the domain filter is a dropdown + list rather than a per-domain toggle grid.
- Logs. Everything is logged under
CardDAV autoconfig:— raise the level in Admin → Logging to watch it.
MIT © Yasin Fadaee — see LICENSE.