Manage Dovecot Mailbox Permissions Safely with doveadm acl
Get an ACL entry wrong on a shared Dovecot mailbox and someone either can't open it or can read mail they were never meant to see. doveadm acl grants, inspects, replaces and removes those entries, and this guide walks through all four plus verification. Allow about fifteen minutes for one mailbox, assuming the account and mailbox already exist. The examples describe Dovecot 2.3 from package dovecot-core 1:2.3.21+dfsg1-2ubuntu6.5.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need shell access to the mail host and a Dovecot install with the ACL plugin. Commands that change another user's mailbox normally need the privileges your Dovecot administration setup grants, so use the account and socket arrangement approved for that host. Don't add sudo out of habit: it can mask a socket or configuration problem.
1. Check that ACL support is actually enabled
The command ships with the Dovecot core package, but the acl plugin still has to be enabled in the server configuration. Check the effective config before touching a mailbox:
$ doveconf -n | grep -E '(^|[[:space:]])mail_plugins[[:space:]]*='
Look for acl in the relevant mail_plugins line. If the plugin isn't enabled, doveadm acl can fail even though the binary and manual page are both installed. Fix that through your normal deployment process, then recheck before continuing.
Checkpoint
Pin down the target user and mailbox precisely. The examples use [email protected] as the mailbox owner and shared/Support as the mailbox name: swap in your own before running anything.
2. Read the current entry before you touch it
get shows every ACL entry on a mailbox. -u makes the user context explicit:
$ doveadm acl get -u [email protected] 'shared/Support'
ID Global Rights
--------------- -------------
owner lookup read write write-seen write-deleted insert post expunge create delete admin
[email protected] lookup read
Column widths shift with the installed formatter, so read the values, not the alignment. The default formatter is table; switch to another when you want easier parsing, for example:
$ doveadm -f flow acl get -u [email protected] 'shared/Support'
This read is a checkpoint, not a formality. It tells you whether the entry already exists and stops set from wiping out something you didn't mean to touch.
3. Add only the rights you need
add keeps existing rights and grants more on top. This example lets Bob list and read the mailbox:
$ doveadm acl add -u [email protected] 'shared/Support' [email protected] lookup read
If the entry already existed, add keeps its rights and adds the new ones. Check the result straight away:
$ doveadm acl get -u [email protected] 'shared/Support'
ID Global Rights
-------------------- -------------
[email protected] lookup read
The right names are Dovecot's own, not the single-letter IMAP ACL form. Common mappings: l to lookup, r to read, w to write, i to insert, k to create, x to delete, a to admin. write-seen controls the \\Seen flag and write-deleted controls \\Deleted.
4. Replace an entry only when you mean to
Warning
set replaces every right for the selected identifier. It is not an additive version of add. Use it only once you've decided the complete final set:
$ doveadm acl set -u [email protected] 'shared/Support' [email protected] lookup read insert
Confirm the rights you didn't name are actually gone:
$ doveadm acl get -u [email protected] 'shared/Support' | grep '[email protected]'
Meant to add one right but used set instead? Restore the full previous list with another set. This is exactly why step 2's get output matters before any replacement.
5. Remove a right, or the whole entry
remove takes away named rights and leaves the entry in place:
$ doveadm acl remove -u [email protected] 'shared/Support' [email protected] insert
Run get again and confirm Bob kept the rights you meant him to keep. Removing the last right leaves an entry with no rights, not no entry.
Warning
delete removes the whole entry. That's broader than removing one right, and hard to undo unless you recorded the original:
$ doveadm acl delete -u [email protected] 'shared/Support' [email protected]
$ doveadm acl get -u [email protected] 'shared/Support'
Recovery means adding or setting the entry again from your recorded ACL. If the mailbox has inherited or group-based access, deleting one entry doesn't touch those other sources.
6. Know the identifiers and their precedence
The identifier chooses who gets the rights: owner, group=NAME, user=NAME, authenticated, and anyone (anonymous is an alias for anyone). A mailbox name can contain * and ? wildcards, so quote it wherever the shell might interpret those.
Dovecot resolves identifiers in this order: group override, user, owner, group, authenticated, then anyone. A user entry can override a group result. group-override=NAME can override a user's rights too; the documented use is temporarily pulling access from a group's members. Treat that as security-sensitive and record the previous ACL before applying it.
7. Diagnose access without guessing
If someone still can't open a shared mailbox, use the command built to explain why:
$ doveadm acl debug -u [email protected] 'shared/Support'
For the current user's effective rights:
$ doveadm acl rights -u [email protected] 'shared/Support'
These separate an ACL problem from mailbox discovery, subscription, namespace or authentication problems. If the ACL data looks stale, doveadm acl recalc recalculates the user's shared-mailbox records in acl_shared_dict, but only run it after checking the configuration and this command's own diagnostics.
For bulk work, -F FILE reads one username per line and -A runs for every user. Treat both as high-impact: review the user database or input file first, and test with one explicit -u invocation before either. A malformed list or an unsuitable iterate_query can leave coverage incomplete. -S selects a local Unix socket or a remote host:port; verify the endpoint before you use it.
Done means
- Confirmed the ACL plugin is enabled and pinned down the exact user and mailbox.
- Read the existing entry before running
setordelete. - Granted the rights actually needed, nothing broader.
- Verified the change with
get,rightsordebug. - Recorded the previous ACL before any replacement or deletion, so you can recover.