Menu
AkurAI-Build
publicLatest change 3875cdb1f0241e71211550cba0c68f423eb55260 - Add safe mail domain retirement operations by Ólafur Búi Ólafsson
set -euo pipefail
action="$1"
domain="${2:-}"
config_paths=(
/etc/postfix/vmailbox
/etc/postfix/vmailbox_domains
/etc/opendkim/key.table
/etc/opendkim/KeyTable
/etc/opendkim/signing.table
/etc/opendkim/SigningTable
/etc/opendkim/trusted.hosts
/etc/opendkim/TrustedHosts
/etc/dovecot/users
)
if [ "$action" = list ]; then
signed="$(sudo awk '{print $2}' /etc/opendkim/key.table 2>/dev/null | cut -d: -f1 | sort -u | tr '\n' ',' | sed 's/,$//')"
hosted="$(sudo awk '{print $1}' /etc/postfix/vmailbox_domains 2>/dev/null | sort -u | tr '\n' ',' | sed 's/,$//')"
printf 'dkim_signed=%s postfix_hosted=%s\n' "${signed:-none}" "${hosted:-none}"
while IFS= read -r dir; do
name="${dir##*/}"
messages="$(sudo find "$dir" -type f \( -path '*/cur/*' -o -path '*/new/*' \) | wc -l)"
accounts="$(sudo grep -c "@$name:" /etc/dovecot/users 2>/dev/null || true)"
printf 'domain %s maildirs=%s messages=%s accounts=%s bytes=%s\n' "$name" \
"$(sudo find "$dir" -mindepth 1 -maxdepth 1 -type d | wc -l)" "$messages" "$accounts" \
"$(sudo du -sb "$dir" | cut -f1)"
done < <(sudo find /var/vmail -mindepth 1 -maxdepth 1 -type d | sort)
exit 0
fi
[ "$action" = retire ]
[[ "$domain" =~ ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$ ]]
escaped="${domain//./\\.}"
domain_re="(^|[.@*[:space:]])${escaped}([:[:space:]/]|$)"
present=0
for path in "${config_paths[@]}"; do
[ -f "$path" ] || continue
if sudo grep -Eqi -- "$domain_re" "$path"; then present=1; fi
done
[ -d "/var/vmail/$domain" ] && present=1
[ -d "/etc/opendkim/keys/$domain" ] && present=1
if [ "$present" = 0 ]; then
printf 'retired=%s already_absent=yes changed=0\n' "$domain"
exit 0
fi
stamp="$(date -u +%Y%m%dT%H%M%SZ)"
changed=0
for path in "${config_paths[@]}"; do
[ -f "$path" ] || continue
sudo grep -Eqi -- "$domain_re" "$path" || continue
sudo cp -a "$path" "$path.retired-$stamp"
sudo sed -Ei "/$domain_re/Id" "$path"
changed=$((changed + 1))
case "$path" in
/etc/postfix/vmailbox | /etc/postfix/vmailbox_domains) sudo postmap "$path" ;;
esac
done
maildir=no
if [ -d "/var/vmail/$domain" ]; then
sudo rm -rf -- "/var/vmail/$domain"
maildir=yes
fi
keys=no
if [ -d "/etc/opendkim/keys/$domain" ]; then
sudo rm -rf -- "/etc/opendkim/keys/$domain"
keys=yes
fi
sudo postfix check
sudo systemctl reload postfix@- 2>/dev/null || sudo systemctl reload postfix
sudo systemctl restart opendkim
remaining=0
for path in "${config_paths[@]}"; do
[ -f "$path" ] || continue
if sudo grep -Eqi -- "$domain_re" "$path"; then remaining=$((remaining + 1)); fi
done
[ "$remaining" = 0 ]
[ ! -e "/var/vmail/$domain" ]
[ ! -e "/etc/opendkim/keys/$domain" ]
for unit in postfix@- dovecot opendkim opendmarc; do
systemctl is-active --quiet "$unit"
done
historical="$(sudo grep -rli -- "$escaped" /etc/postfix /etc/opendkim /etc/dovecot 2>/dev/null |
grep -cE '\.(bak|db|retired-[0-9TZ]+)' || true)"
printf 'retired=%s changed=%s maildir_removed=%s dkim_keys_removed=%s refs_remaining=0 historical_copies=%s services=active\n' \
"$domain" "$changed" "$maildir" "$keys" "$historical"