From b3de32ed04bbce8e0e79c9ee99d0cad2f1176e41 Mon Sep 17 00:00:00 2001 From: ale <ale@incal.net> Date: Mon, 24 Feb 2025 11:02:04 +0000 Subject: [PATCH] Make Postfix queue manipulation tools more accurate Replace awk-based regular expressions with 'jq' parsing the JSON postqueue output, which is more accurate as it does not depend on the exact syntax of the queue IDs. --- roles/mail/files/pqgrep | 29 ++++++++++++++++++------ roles/mail/files/pqsummary | 45 +++++++++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/roles/mail/files/pqgrep b/roles/mail/files/pqgrep index 3c2dee71..993c8e72 100644 --- a/roles/mail/files/pqgrep +++ b/roles/mail/files/pqgrep @@ -3,6 +3,17 @@ # Filter out messages matching a specific criteria. # +usage() { + cat >&2 <<EOF +Usage: pqgrep [<options>] <sender> +Known options: + -i INSTANCE Limit to a specific Postfix instance + -d Delete the selected messages from the queue + +EOF + exit 2 +} + instances=postfix-out do_delete=0 sender= @@ -15,21 +26,25 @@ while [ $# -gt 0 ]; do -d) do_delete=1 ;; + -h|--help) + usage + ;; -*) echo "Unknown option '$1'" >&2 - exit 2 + usage ;; *) + if [ -n "$sender" ]; then + echo "Too many arguments" >&2 + usage + fi sender="$1" ;; esac shift done -if [ -z "$sender" ]; then - echo "Usage: pqgrep [<options>] <sender>" >&2 - exit 2 -fi +[ -n "$sender" ] || usage if [ "$instances" = "all" ]; then instances=$(postmulti -l | awk '$1 != "-" {print $1}') @@ -40,7 +55,7 @@ for instance in $instances; do if [ $do_delete -eq 1 ]; then cmd="xargs -n 1 postmulti -i $instance -x postsuper -d" fi - postmulti -i $instance -x mailq \ - | awk "\$7 == \"${sender}\" {print \$1}" \ + postmulti -i $instance -x postqueue -j \ + | jq -r "select(.sender == \"${sender}\") | .queue_id" \ | $cmd done diff --git a/roles/mail/files/pqsummary b/roles/mail/files/pqsummary index a9515985..b4603f0d 100644 --- a/roles/mail/files/pqsummary +++ b/roles/mail/files/pqsummary @@ -3,20 +3,50 @@ # Print a summary of a Postfix queue. # +usage() { + cat >&2 <<EOF +Usage: pqsummary [<options>] +Known options: + -i INSTANCE Limit to a specific Postfix instance + -n N Show the top N results (default: 20) + -s Aggregate by sender (default) + -r Aggregate by recipient + +EOF + exit 2 +} + instances=postfix-out +num_results=20 +jq_query_sender=".sender" +jq_query_recipient=".recipients[0].address" +jq_query="$jq_query_sender" while [ $# -gt 0 ]; do case "$1" in -i) instances="$instances $2" shift ;; + -s) + jq_query="$jq_query_sender" + ;; + -r) + jq_query="$jq_query_recipient" + ;; + -n) + num_results="$2" + shift + ;; + -h|--help) + usage + ;; -*) echo "Unknown option '$1'" >&2 - exit 2 + usage ;; *) echo "Too many arguments" >&2 - exit 2 + usage ;; esac shift @@ -29,8 +59,11 @@ fi for instance in $instances; do echo echo "* $instance:" - postmulti -i $instance -x mailq \ - | awk '/^[a-zA-Z0-9]+/ {count[$7]++} END {for(i in count){ print i, count[i] }}' \ - | sort -n -k2 \ - | column -t + postmulti -i $instance -x postqueue -j \ + | jq -r "$jq_query" \ + | sort \ + | uniq -c \ + | sort -n -r \ + | column -t \ + | head -${num_results} done -- GitLab