mirror of
https://github.com/myvesta/vesta
synced 2025-07-05 12:36:23 -07:00
127 lines
3.3 KiB
Bash
127 lines
3.3 KiB
Bash
#!/bin/bash
|
||
# info: delete old emails (by mtime) for user/domain/account, with optional scope
|
||
# usage: v-delete-mails USER DOMAIN ACCOUNT MTIME_DAYS|all SCOPE
|
||
# SCOPE: all – clean every Maildir folder (cur, new, tmp, custom subfolders)
|
||
# trash – clean only Trash/Junk/Spam folders
|
||
|
||
# load Vesta functions & config
|
||
source "$VESTA/func/main.sh"
|
||
source "$VESTA/conf/vesta.conf"
|
||
|
||
# read arguments
|
||
user="$1"
|
||
domain="$2"
|
||
account="$3"
|
||
mtime="$4"
|
||
scope="$5"
|
||
|
||
# verify argument count
|
||
check_args '5' "$#" 'USER DOMAIN ACCOUNT MTIME_DAYS|all SCOPE'
|
||
|
||
# validate scope
|
||
if [[ "$scope" != "all" && "$scope" != "trash" ]]; then
|
||
echo "ERROR: SCOPE must be 'all' or 'trash'."
|
||
exit 1
|
||
fi
|
||
|
||
# validate logical combinations
|
||
if [[ "$user" == "all" ]]; then
|
||
if [[ "$domain" != "all" || "$account" != "all" ]]; then
|
||
echo "ERROR: When USER is 'all', both DOMAIN and ACCOUNT must be 'all'."
|
||
exit 1
|
||
fi
|
||
elif [[ "$domain" == "all" && "$account" != "all" ]]; then
|
||
echo "ERROR: When DOMAIN is 'all', ACCOUNT must also be 'all'."
|
||
exit 1
|
||
fi
|
||
|
||
# build a detailed summary for the warning
|
||
declare -a summary_parts
|
||
if [[ "$user" == "all" ]]; then
|
||
summary_parts+=("all users")
|
||
else
|
||
summary_parts+=("user '$user'")
|
||
fi
|
||
|
||
if [[ "$domain" == "all" ]]; then
|
||
summary_parts+=("all domains")
|
||
else
|
||
summary_parts+=("domain '$domain'")
|
||
fi
|
||
|
||
if [[ "$account" == "all" ]]; then
|
||
summary_parts+=("all accounts")
|
||
else
|
||
summary_parts+=("account '$account'")
|
||
fi
|
||
|
||
# join with commas
|
||
summary=$(printf ", %s" "${summary_parts[@]}")
|
||
summary=${summary:2}
|
||
|
||
# only warn if any of them is 'all' or if mtime is 'all'
|
||
if [[ "$mtime" == "all" || "$user" == "all" || "$domain" == "all" || "$account" == "all" ]]; then
|
||
echo "WARNING: This will delete emails older than '$mtime' days for ${summary}."
|
||
read -p "Are you sure? (yes/no): " confirm
|
||
[[ "$confirm" != "yes" ]] && { echo "Aborted."; exit 1; }
|
||
fi
|
||
|
||
# function to delete emails
|
||
delete_emails() {
|
||
local u="$1" d="$2" a="$3"
|
||
local maildir="/home/$u/mail/$d/$a"
|
||
|
||
[[ ! -d "$maildir" ]] && return
|
||
|
||
echo "→ Cleaning '$a@$d' (user: $u), scope: $scope, mtime: $mtime"
|
||
|
||
# build find predicates
|
||
if [[ "$scope" == "all" ]]; then
|
||
folder_expr=( -path "*/cur/*" -o -path "*/new/*" -o -path "*/tmp/*" )
|
||
else
|
||
folder_expr=( -ipath "*/trash/*" -o -ipath "*/junk/*" -o -ipath "*/spam/*" )
|
||
fi
|
||
|
||
# assemble and run find
|
||
if [[ "$mtime" == "all" ]]; then
|
||
find "$maildir" -type f \( "${folder_expr[@]}" \) -print -delete 2>/dev/null
|
||
else
|
||
find "$maildir" -type f \( "${folder_expr[@]}" \) -mtime +"$mtime" -print -delete 2>/dev/null
|
||
fi
|
||
}
|
||
|
||
# collect users
|
||
if [[ "$user" == "all" ]]; then
|
||
users=$(v-list-users plain | awk '{print $1}')
|
||
else
|
||
users="$user"
|
||
fi
|
||
|
||
# iterate through users, domains, accounts
|
||
for u in $users; do
|
||
if [[ "$domain" == "all" ]]; then
|
||
domains=$(v-list-mail-domains "$u" plain | awk '{print $1}')
|
||
else
|
||
domains="$domain"
|
||
fi
|
||
|
||
for d in $domains; do
|
||
if [[ "$account" == "all" ]]; then
|
||
accounts=$(v-list-mail-accounts "$u" "$d" plain | awk '{print $1}')
|
||
else
|
||
accounts="$account"
|
||
fi
|
||
|
||
for a in $accounts; do
|
||
delete_emails "$u" "$d" "$a"
|
||
done
|
||
done
|
||
done
|
||
|
||
# restart dovecot to refresh mailbox state
|
||
systemctl restart dovecot
|
||
|
||
# log the action (status first, then message)
|
||
log_event "$OK" "Deleted emails (>$mtime days, scope=$scope) for $user $domain $account"
|
||
|
||
exit 0
|