Autoexpunge Configuration for All Mailboxes

Hello, I’m setting up automatic deletion of emails older than 30 days or > 200 emails. I’ve edited the dovecot.conf file as follows:

protocols = imap pop3
listen = *, ::
base_dir = /run/dovecot/
login_greeting = Mail Delivery Agent
default_client_limit = 5000
!include conf.d/*.conf
!include_try conf.d/domains/*.conf

service stats {
  unix_listener stats-writer {
    group = mail
    mode = 0660
    user = dovecot
  }
}

namespace {
    type = private
    separator = /
    inbox = yes
    list = yes

    mailbox * {
        autoexpunge = 30d
        autoexpunge_max_mails = 200
        mailbox_list_index = yes
    }

    mailbox Archive {
        auto = subscribe
        special_use = \Archive
    }

    mailbox Drafts {
        auto = subscribe
        special_use = \Drafts
    }

    mailbox Trash {
        auto = subscribe
        special_use = \Trash
    }

    mailbox "Deleted Messages" {
        auto = no
        special_use = \Trash
    }

    mailbox Spam {
        auto = subscribe
        special_use = \Junk
    }

    mailbox Junk {
        auto = no
        special_use = \Junk
    }

    mailbox Sent {
        auto = subscribe
        special_use = \Sent
    }

    mailbox "Sent Mail" {
        auto = no
        special_use = \Sent
    }

    mailbox "Sent Messages" {
        auto = no
        special_use = \Sent
    }
}

May I ask if I have done it correctly? Thank you

It appears that my Dovecot configuration for automatically purging old emails is wrong. Therefore, I have opted for an alternative approach by using clean-email.sh script and setting up a cronjob to automate this task

#!/bin/bash

process_domain() {
    # Check if domain.txt exists and is not empty
    if [ ! -f domain.txt ] || [ ! -s domain.txt ]; then
        echo "The domain.txt file does not exist or is empty."
        return
    fi

    dos2unix domain.txt
    while IFS=";" read -r user domain time || [ -n "$user" ]
    do
        # Check the structure of the line
        if [ -z "$user" ] || [ -z "$domain" ] || [ -z "$time" ]; then
            echo "Skipping line with incorrect structure: $user;$domain;$time"
            continue
        fi

        # Get the list of email accounts
        accounts=$(v-list-mail-accounts $user $domain | awk 'NR>3 {print $1"@'$domain'"}')

        # Iterate through the accounts and perform cleanup
        for account in $accounts
        do
            doveadm expunge -u $account mailbox '*' before $time
        done
    done < domain.txt
}

process_account() {
    # Check if account.txt exists and is not empty
    if [ ! -f account.txt ] || [ ! -s account.txt ]; then
        echo "The account.txt file does not exist or is empty."
        return
    fi

    dos2unix account.txt
    while IFS=";" read -r account time || [ -n "$account" ]
    do
        # Check the structure of the line
        if [ -z "$account" ] || [ -z "$time" ]; then
            echo "Skipping line with incorrect structure: $account;$time"
            continue
        fi

        doveadm expunge -u $account mailbox '*' before $time
    done < account.txt
}

process_domain
process_account

domain.txt

user1;domain1;30d
user2;domain2;45d

account.txt

acc1@domain3;30d
acc2@domain3;45d
acc3@domain3;60d

In your opinion, could this script be further optimized, for example, replacing domain.txt and account.txt with a single list?

I didn’t have time to review it but with above code you are missing the first account in the list, you could use:

accounts=$(v-list-mail-accounts $user $domain | awk 'NR>=3 {print $1"@'$domain'"}')

or

accounts=$(v-list-mail-accounts $user $domain | awk 'NR>2 {print $1"@'$domain'"}')

or

accounts=$(v-list-mail-accounts $user $domain plain | awk '{print $1"@'$domain'"}')
2 Likes