Restore Selected Mail Safely with doveadm import
Someone deleted the wrong folder, and all you have is a Maildir or mdbox backup: doveadm import pulls selected messages back into a user's mailbox. You will run one narrow, checkable import instead of a blind bulk copy. Allow about fifteen minutes for a small test, longer for a real mailbox.
The route
Jump straight to the step you need, or tick off Done means at the end.
The examples target the installed Dovecot 2.3.21 package, dovecot-core 1:2.3.21+dfsg1-2ubuntu6.5.
- What you need: a readable source mailbox, a configured Dovecot destination, and an account permitted to run doveadm mail commands.
- What it is: a restore or merge, not a transport migration. It writes mail and can create mailboxes.
- Privileges: the command normally needs elevated privileges or an account with suitable Dovecot access. The inspection commands below do not.
Treat the source path, destination user and search query as a change plan.
1. Check the installed command
Start with a read-only version and syntax check. The installed manpage is the contract for this host, so do not copy options from a different Dovecot release without checking them:
$ doveadm --version
2.3.21
$ man doveadm-import
The command takes three positional arguments:
source_locationuses the same style as Dovecot'smail_locationsetting, such asmaildir:/backup/user/Maildirormdbox:/backup/user/mdbox.dest_parentis the parent mailbox the imported folders land under.search_queryselects which messages to import.
Checkpoint
Write down the exact source path and destination user before you go on. A typo in the source can turn a restore into an import from the wrong mailbox.
2. Make a narrow test plan
Choose the destination with -u. While testing, put a non-empty parent mailbox such as Restore-2026-09 around the imported folders. Dovecot creates that parent if it does not exist:
$ doveadm import -u '[email protected]' \
'maildir:/srv/backup/jane.doe/Maildir' \
'Restore-2026-09' \
'mailbox INBOX from [email protected]'
This imports messages in the source INBOX whose sender matches [email protected]. Quote the query as one shell argument when it contains spaces. It is a Dovecot search query, so use the search-query documentation for operators rather than guessing at shell syntax.
For a complete backup, use all as the query:
$ doveadm import -u '[email protected]' \
'mdbox:/srv/backup/jane.doe/mdbox' \
'Restore-2026-09' \
all
Warning
Do not use all as a first test against an uncertain source. A successful command can import far more mail than you intended.
3. Decide which user opens the source
By default the source is opened in the destination user's context. If the source belongs to another Dovecot user and your access model permits it, add -U:
# Run with the Dovecot administrator account or suitable privilege.
$ doveadm import -U '[email protected]' \
-u '[email protected]' \
'maildir:/srv/mail/backup-owner/Maildir' \
'Restore-2026-09' \
'mailbox INBOX all
-U changes the username used to open the source. It does not change the destination chosen by -u. Check filesystem permissions and Dovecot's user database before running this form.
Tip
If source and destination have different system ownership, fix the access design. Do not make a broad, permanent permission change for one restore.
Checkpoint
With the command still on paper, confirm all four values: source user, destination user, source location and query. If any is unknown, stop here.
4. Run one controlled import
Use -v for a progress counter. Add -s only if the destination parent and newly created mailboxes should be subscribed:
# Elevated operation: this creates mailboxes and copies messages.
$ doveadm -v import -u '[email protected]' -s \
'maildir:/srv/backup/jane.doe/Maildir' \
'Restore-2026-09' \
'mailbox INBOX from [email protected]'
import: copied messages
Progress text varies with the mailbox and installed build. The useful success signal is an exit status of zero, followed by a check of the destination through IMAP or a read-only doveadm command such as:
$ printf 'exit status: %s\n' "$?"
exit status: 0
$ doveadm search -u '[email protected]' mailbox 'Restore-2026-09/INBOX' ALL
Checkpoint
The search output is host-specific. Check the message count and a few expected headers in a mail client before importing more.
Tip
Subscription is a separate choice from copying. If you want the imported mail to appear in the user's normal view straight away, subscribe deliberately.
5. Scale to a user list only after verification
For several known users, put one username per line in a file and use -F. Creating that file is an ordinary local shell action, but review it before the import:
$ sed -n '1,20p' /root/restore-users.txt
[email protected]
[email protected]
$ doveadm -v import -F /root/restore-users.txt \
'maildir:/srv/backup/common/Maildir' \
'Restore-2026-09' \
'mailbox INBOX from [email protected]'
-A gets users from the configured user database instead. Use it only when iteration is known to work:
- SQL needs a matching
iterate_query. - LDAP needs matching iteration settings.
- passwd user databases can include system users below
first_valid_uid, as the manpage warns.
For a controlled recovery, -F is usually easier to audit than -A.
6. Handle duplicates and undo carefully
Warning
Do not assume a second run is harmless. Dovecot's import documentation says imports do not preserve UIDs or check whether a message is already present, although message flags are preserved. A retry after a timeout can therefore create duplicates. Record the query, source and destination before every run.
Recovery
If the test used a dedicated parent such as Restore-2026-09, stop and inspect it. Only after confirming it holds no original mail, remove that imported mailbox using your normal Dovecot mailbox administration procedure.
Warning
Mailbox deletion is destructive and is not an undo button for a mixed import. If you imported into an existing mailbox, there may be no safe automatic rollback. Restore from a verified backup, or remove only individually confirmed duplicate messages.
Done means
- Command checked. You confirmed the installed Dovecot version and the exact source location.
- Plan recorded. The destination user, source user and search query were written down and reviewed.
- Narrow first. A small import ran under a dedicated parent before any broad restore.
- Result verified. The command returned status zero and the destination held the expected mail.
- Subscription decided. You know whether the new mailboxes should be subscribed.
- Record kept. You retained the import record so a timeout is not blindly retried.