Home / Alt manpages / doveadm-purge(1)

  • doveadm-purge(1)
  • User command
  • linux

Reclaim Unreferenced mdbox Messages with doveadm purge

doveadm purge clears mdbox storage that Dovecot has already deleted, and it has no undo, so the real work is picking the right users first. The examples use the installed Dovecot 2.3 command from dovecot-core package version 1:2.3.21+dfsg1-2ubuntu6.5.

Allow about fifteen minutes for a single-user check, plus whatever maintenance window your storage needs. You need access to the Dovecot host, a working doveadm configuration, and an account whose mail storage uses mdbox. Take a backup or snapshot according to your retention policy before a broad run; there is no undo option in doveadm purge.

1. Confirm the installed command

Start with the read-only checks. These do not purge anything and normally need no sudo:

$ command -v doveadm
/usr/bin/doveadm
$ dpkg-query -W -f='${Package} ${Version}\n' dovecot-core
dovecot-core 1:2.3.21+dfsg1-2ubuntu6.5
$ doveadm help purge
DOVEADM-PURGE(1)                    Dovecot                   DOVEADM-PURGE(1)

NAME
       doveadm-purge - Remove messages with refcount=0 from mdbox files

The installed manual defines four target forms: the current user, every user, users read from a file, or a user mask. It also confirms that -v enables progress output and -D enables debug messages.

Checkpoint

If doveadm help purge cannot load the command help, stop here and fix the installation or configuration first. Do not compensate by pointing the command at guessed storage paths.

2. Understand what purge actually removes

mdbox stores a message once and tracks how many mailbox instances still refer to it. Expunging the last instance drops that reference count to zero, and doveadm purge removes those no-longer-referenced messages from the mdbox files. It is storage cleanup after deletion, not a replacement for doveadm expunge.

  • Still present somewhere means purge leaves it alone. A message still referenced in a mailbox is not removed merely because it is old.
  • Expunged everywhere means it is already gone. A message with a zero reference count is already logically deleted and will not be recoverable through normal mailbox operations once its storage is reclaimed.

The command is destructive even though it never selects messages by date or search query. It acts on the storage belonging to whichever users you select, so do not run a broad target until you have checked user database iteration and taken a usable backup.

3. Test one explicit user

Choose an exact mailbox account and record it before running the command:

$ MAIL_USER='[email protected]'
$ doveadm purge -u "$MAIL_USER"
$ printf 'exit status: %s\n' "$?"
exit status: 0

This is an administrative mail operation and may need the Dovecot administrator's privileges depending on your socket and configuration. Use sudo only when the normal administrator invocation requires it, for example sudo doveadm purge -u "$MAIL_USER", and never put a password, token or other secret on the command line.

A zero status means the operation completed; it does not promise a particular number of bytes reclaimed, and a user with no refcount-zero messages will produce normal, empty output. For more visibility, run the verbose form:

$ doveadm -v purge -u "$MAIL_USER"
$ printf 'exit status: %s\n' "$?"
exit status: 0

Run the verbose form during your test, not an unbounded all-user job, and save the output and timestamp with your maintenance record.

4. Review a fixed user list

Use -F when you have a deliberately reviewed list rather than trusting user database iteration. The file holds one username per line:

$ install -m 600 /dev/null /tmp/doveadm-purge-users.txt
$ editor /tmp/doveadm-purge-users.txt
$ sed -n '1,20p' /tmp/doveadm-purge-users.txt
[email protected]
[email protected]
$ doveadm -v purge -F /tmp/doveadm-purge-users.txt
$ printf 'exit status: %s\n' "$?"
exit status: 0

The file is input data, not a shell script: shell quoting inside it has no special meaning, since the command reads the usernames itself. Keep one complete username per line, remove blank or accidental entries, and check the list against your backup scope and maintenance ticket before execution.

Recovery

If the list is wrong, stop before the purge command runs. Afterwards, remove the temporary list with rm -- /tmp/doveadm-purge-users.txt only once you no longer need the audit copy; deleting the list does not restore purged messages.

5. Use all-user mode only after checking iteration

-A asks Dovecot to run the operation for every user returned by the user database. Inspect the effective configuration before using it:

$ doveconf -n | less
$ doveconf -n | rg -n 'userdb|iterate_query|iterate_attrs|iterate_filter|first_valid_uid'
  • SQL user databases need an iterate_query that matches the database layout, per the manual.
  • LDAP user databases need iterate_attrs and iterate_filter checked against the directory schema.
  • The passwd user database can let -A include system users below first_valid_uid, according to the manual's warning.

If iteration is incomplete or too broad, use a reviewed -F file instead. Only after those checks, and with a current recovery point, run:

$ sudo doveadm -v purge -A
$ printf 'exit status: %s\n' "$?"
exit status: 0

Expect this job to take longer than the single-user test, and avoid overlapping it with mailbox migrations, storage maintenance or other jobs that heavily access the same mail files.

6. Troubleshoot scope and connection errors

A missing or mistyped user target is a scope problem: recheck the exact account, the list file and the user database before adding privileges, since a successful sudo will not make a non-existent mailbox appear. When the administrator command must use another doveadm socket, pass an absolute local socket path or a remote hostname:port value with -S:

$ sudo doveadm -S /run/dovecot/doveadm-server purge -u "$MAIL_USER"

Use the socket path documented by your Dovecot configuration rather than guessing a remote endpoint, and treat TCP access as security-sensitive. Add -D for diagnostics if you need it, but review its output before sharing it since debug logs can expose deployment details. -o setting=value can override a configuration setting for a controlled test, but never use it to bypass authentication, redirect mail storage, or change a production setting without a documented rollback.

Done means

  • Version checked. The installed Dovecot version and doveadm purge syntax matched the examples.
  • Storage confirmed. The target storage is mdbox, and you understand that zero-reference messages are reclaimed for good.
  • Single user first. A single-user run completed successfully before any broader scope was considered.
  • List or iteration reviewed. Every -F list was checked, or all-user database iteration was verified before using -A.
  • Backup in place. A backup or snapshot and a maintenance record exist for the destructive operation.
  • Recovery path known. The socket, scope and recovery path can be stated without guessing.