Inspect Dovecot Mail Safely with doveadm fetch
You will use doveadm fetch to retrieve selected message metadata or content from a Dovecot mailbox, with a search query narrow enough to review safely. Allow about 15 minutes for a first check, plus time to identify the right mailbox and UIDs. This guide follows the Dovecot 2.3 command installed here: package dovecot-core version 1:2.3.21+dfsg1-2ubuntu6.5. Dovecot 2.4 has changed some doveadm defaults and requirements, so do not silently transfer those assumptions to this command.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Check the installed command
Run this as your normal account first. Fetch reads mail, but the command can expose complete messages, so use an account and terminal with the same care as the mailbox itself. You may need an administrator account or sudo for a deployment's Dovecot socket permissions, but elevated privileges are not required by the syntax:
$ 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 fetch
DOVEADM-FETCH(1) Dovecot DOVEADM-FETCH(1)
The help command prints the installed manual. If command -v finds nothing, stop and install or enable Dovecot through your normal system-management process. Do not use a different host's command output as proof that this host has the same options.
2. Understand the command shape
The basic form is doveadm fetch [options] fields search_query. The fields say what to print; the search query says which messages to select. With no user-selection option, this Dovecot 2.3 manual says the command uses the environment of the currently logged-in user. For an administrative check, make the target explicit with -u:
$ doveadm fetch -u '[email protected]' 'mailbox date.sent' \
mailbox 'INBOX' subject 'SEARCH_TERM'
Replace every uppercase placeholder. The quoted field list is one argument containing two fields. The search query is made of search terms such as mailbox, subject, uid and their values; its full grammar is documented by doveadm-search-query(7). If the query matches no messages, there may be no output.
Checkpoint: confirm the intended user, mailbox and search terms before adding body or text. A metadata-only query is the safer first test.
3. Fetch a small, useful metadata set
Use stable identifiers when you already know them. This example asks for the mailbox and sent date of three message UIDs in one mailbox:
$ doveadm fetch -u '[email protected]' 'mailbox date.sent' \
mailbox-guid 'MAILBOX_GUID' uid '8,25,45'
mailbox: dovecot/pigeonhole/2.0
date.sent: 2010-01-19 01:17:41 (+0100)
^L
mailbox: dovecot/pigeonhole/2.0
date.sent: 2010-01-28 09:38:49 (+0100)
The exact mailbox name, dates and number of records depend on your data. The default formatter is pager: each field appears as key: value, and form-feed characters separate records. Seeing ^L in a terminal or log means a record separator, not a mailbox value. Use -f flow for key=value lines, -f tab for tab-separated output, or -f table for an aligned table:
$ doveadm -f table fetch -u '[email protected]' 'uid size.virtual flags' \
mailbox 'INBOX' all
Check the output before widening the query. For scripts, choose a formatter deliberately and account for records that contain message text or unusual characters.
4. Fetch a header or body only when needed
The field determines how much data leaves the mailbox. hdr returns the message header, body returns the body, text returns the complete message, and text.utf8 returns the complete message as UTF-8. Other useful metadata fields include flags, guid, uid, size.physical, size.virtual, mailbox and user.
$ doveadm fetch -u '[email protected]' hdr \
mailbox 'INBOX' uid 'MESSAGE_UID'
$ doveadm fetch -u '[email protected]' body \
mailbox 'INBOX' uid 'MESSAGE_UID' > message-body.txt
$ test -s message-body.txt && echo 'body saved'
body saved
The redirection writes local data and can overwrite an existing file. Use a new filename or a guarded temporary path when the result matters:
$ output_file="message-body.$$.txt"
$ doveadm fetch -u '[email protected]' body \
mailbox 'INBOX' uid 'MESSAGE_UID' > "$output_file" && \
printf 'saved %s\n' "$output_file"
saved message-body.12345.txt
If the fetch fails, inspect the exit status and remove only the known incomplete output after checking its path. The original message is not altered by fetch. Do not include message contents in a shared terminal capture, ticket or debug log unless the recipient is authorised to see them.
5. Limit administrative scope
-u USER selects one user and accepts * and ? wildcards. -F FILE reads one username per line and runs the command for every listed user. -A runs it for all users. These are read operations, but they can disclose a large amount of personal data and create heavy mailbox or database load:
$ doveadm fetch -u '[email protected]' 'mailbox uid size.virtual' \
mailbox 'INBOX' all
$ printf '%s\n' '[email protected]' > users-to-check.txt
$ doveadm fetch -F users-to-check.txt 'mailbox uid' mailbox 'INBOX' all
Do not use -A as a discovery shortcut. The 2.3 manual warns that combining it with a passwd userdb can include system users below first_valid_uid. For SQL or LDAP userdbs, iteration settings must match the database or directory schema. Start with one user and one narrow query, then obtain approval before widening the scope.
Checkpoint: if you created users-to-check.txt, review and delete it when the operation is complete. It contains account names and may itself be sensitive. Nothing in these examples changes mailbox state, so there is no Dovecot undo operation required.
6. Diagnose an empty or failed result
An empty result normally means that no message matched the query, not that fetch silently fetched everything. Recheck the exact mailbox spelling, user, UID and search terms. Search terms are not shell globs unless the search-query syntax defines them as such.
For more detail, add the global -v option for verbosity and progress, or -D for debug messages:
$ doveadm -v fetch -u '[email protected]' 'uid mailbox' \
mailbox 'INBOX' uid 'MESSAGE_UID'
A socket or permission error is an access or deployment problem. -S can select an absolute UNIX socket path or a HOST:PORT TCP endpoint, but use it only when your Dovecot configuration documents that endpoint. A remote socket can send mailbox data across the network; check transport and authorisation before using it.
If the command reports an unknown field, compare it with the installed manual. If it reports a malformed query, reduce the query to mailbox INBOX uid MESSAGE_UID, verify that form, then add one condition at a time. Avoid repeatedly retrying a broad query against a busy production service.
Done means
- You confirmed the installed Dovecot package and the local
doveadm fetchsyntax. - You selected one explicit user, mailbox and narrow search query before reading message content.
- You chose fields and an output formatter that match the amount and shape of data required.
- You treated
hdr,body,textandtext.utf8as sensitive output. - You understand that
-Aand-Fexpand scope and may require careful userdb configuration. - You kept the original mailbox unchanged and handled any local output file deliberately.