Keeping mailboxes lean is essential for performance and storage management on self-hosted email servers. Over time, folders like Trash
, Junk
, or even custom folders such as Newsletters
or Archive
can accumulate old messages that serve no ongoing purpose.
This guide demonstrates how to automatically remove (expunge) old messages from selected folders based on their age using Dovecot’s native doveadm
utility. The method is simple, scriptable, and integrates cleanly into any system via cron.
Preview: What would be deleted? (Dry Run)
Before deleting anything, you can preview which messages would be expunged by using doveadm fetch
.
Example:
doveadm fetch -A 'uid flags subject' mailbox Trash savedbefore 30d
This lists all messages in the Trash
folder that are older than 30 days, including:
- UID (unique message ID per folder)
- Flags (e.g.
\Seen
,\Deleted
) - Subject line (for identification)
You can replace the folder and retention period as needed:
doveadm fetch -A 'uid subject' mailbox Newsletters savedbefore 45d
This helps verify your rules before running actual expunge commands.
Script Location and Structure
We place the script in a controlled location under:
/root/dovecot-autoclean/dovecot_expunge.sh
#!/bin/bash
# Path to doveadm binary
DOVEADM="/usr/bin/doveadm"
# Expunge mails older than the defined age from specified folders
$DOVEADM expunge -A mailbox Trash savedbefore 30d
$DOVEADM expunge -A mailbox Junk savedbefore 90d
$DOVEADM expunge -A mailbox Newsletters savedbefore 45d
Make the script executable:
chmod +x /root/dovecot-autoclean/dovecot_expunge.sh
You can customize both folder names and the age (savedbefore
) to match your needs. The folder names must exactly match their IMAP representation.
Cron Integration (no systemd)
We recommend scheduling the script once daily. Two common options:
Option 1: crontab -e
(user-specific, e.g. root)
Run:
crontab -e
Add the following line to run the script at 03:30 every night:
30 3 * * * /root/dovecot-autoclean/dovecot_expunge.sh
Option 2: /etc/crontab
(system-wide)
Alternatively, edit /etc/crontab
and insert:
30 3 * * * root /root/dovecot-autoclean/dovecot_expunge.sh
This explicitly declares the user (root
) and is preferred in environments with centralized cron management.
Manual Testing
Before relying on automation, test the script manually:
/root/dovecot-autoclean/dovecot_expunge.sh
This will run all expunge commands and print errors to the console if applicable.
Notes and Considerations
- The
-A
flag requiresdoveadm
to access a user list (e.g., via SQL, passwd, or LDAP). - If
-A
doesn’t work, you can loop over users manually (not covered here). savedbefore 30d
refers to the internal save timestamp, not the email’sDate:
header.- Folder names are case-sensitive depending on your Dovecot namespace settings.
- You can add more folders or adjust timeframes as needed, e.g.:
$DOVEADM expunge -A mailbox Projects-2021 savedbefore 180d
Summary
This method provides a lightweight, cron-based strategy for automatic email cleanup using Dovecot’s built-in tooling. It gives administrators fine-grained control over which folders are cleaned, and after how long—without installing additional software or relying on user behavior.
This article replaces the now deprecated script formerly hosted at github.com/filipnet/dovecot-autoclean, which will be removed shortly. All relevant instructions are now maintained here.