When managing a Postfix mail server handling multiple domains, you'll occasionally need to purge messages destined for a specific domain. First, let's examine the queue:
postqueue -p | grep example.com
This command lists all queued messages containing "example.com" in recipient addresses. For more detailed inspection:
postqueue -p | awk '/example\.com/ {print $1}' | tr -d '!'
Method 1: Using postsuper
The safest approach uses postsuper to delete by queue ID:
postqueue -p | grep example.com | awk '{print $1}' | \
tr -d '!' | xargs -n 1 postsuper -d
Method 2: Direct mailq filtering
For systems with older Postfix versions:
mailq | grep example.com | cut -d' ' -f1 | \
tr -d '*!' | postsuper -d -
Create a reusable script (/usr/local/bin/purge_domain_queue
):
#!/bin/bash
DOMAIN="$1"
if [ -z "$DOMAIN" ]; then
echo "Usage: $0 domain.com"
exit 1
fi
mailq | grep "@${DOMAIN}" | \
while read -r line; do
QUEUE_ID=$(echo "$line" | awk '{print $1}')
postsuper -d "${QUEUE_ID%!}"
done
Make it executable:
chmod +x /usr/local/bin/purge_domain_queue
For complex cases where emails might be sent from the domain:
mailq | awk '/@example\.com/ || /^[A-Z0-9]+!\s.*example\.com/ {print $1}' | \
tr -d '!*' | xargs postsuper -d
After deletion, verify the queue is clean:
postqueue -p | grep -c example.com
Should return 0 if successful. For persistent issues, check Postfix logs:
tail -f /var/log/mail.log | grep example.com
When managing a mail server hosting multiple domains, you'll occasionally need to purge queued messages for just one domain while preserving others. Postfix doesn't provide a built-in command for this, but we can combine several tools to achieve precise queue manipulation.
The most straightforward approach combines postsuper
with queue ID filtering:
# List all queue IDs for messages destined to example.com postqueue -p | grep 'example.com' | awk '{print $1}' | tr -d '!*' > queue_ids.txt # Delete the identified messages postsuper -d $(cat queue_ids.txt)
For more advanced filtering, use this Python script:
#!/usr/bin/env python3 import subprocess import re def flush_domain_queue(domain): output = subprocess.check_output(['postqueue', '-p']).decode() pattern = re.compile(r'^([A-Z0-9]+)\s+.*' + re.escape(domain), re.M) queue_ids = set(pattern.findall(output)) if queue_ids: subprocess.call(['postsuper', '-d'] + list(queue_ids)) print(f"Deleted {len(queue_ids)} messages for {domain}") else: print(f"No messages found for {domain}") flush_domain_queue('example.com')
For large queues, first analyze with qshape
:
# Analyze queue by destination domain qshape -s deferred | grep example.com # Then proceed with deletion using Method 1 or 2
- Always create queue backups with
postcat -q QUEUE_ID > backup_file
- Consider using
hold
instead ofdelete
for testing:postsuper -h $(cat queue_ids.txt)
- Monitor mail logs during the operation:
tail -f /var/log/mail.log