Postfix Queue Management: How to Delete All Emails for a Specific Domain


2 views

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 of delete for testing: postsuper -h $(cat queue_ids.txt)
  • Monitor mail logs during the operation: tail -f /var/log/mail.log