diff --git a/roles/mail/files/pqgrep b/roles/mail/files/pqgrep
index 3c2dee71b807d7baa50ffeaba9a4ac915ab19d0e..993c8e7202e2c80d9101f9bccace562b43958c96 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 a951598563e0f95e4786bab2ceabf8295e08e37d..b4603f0da1ac1e3e486807d3c55eb66d6918b4f9 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