How to Programmatically Modify Recipient Addresses in Postfix Mail Queue


23 views

When dealing with bounced emails in Postfix, it's crucial to understand where and how messages are stored. The mail queue typically resides in /var/spool/postfix with these key directories:

/var/spool/postfix/deferred/  # For deferred messages
/var/spool/postfix/incoming/  # New messages being processed
/var/spool/postfix/active/    # Messages currently being delivered

First, identify the queued messages using the mailq command. For example:

$ mailq | grep "user@wrongdomain.com"
-Queue ID-  --Size-- ----Arrival Time---- -Sender/Recipient-------
ABC123DEF       1024 Fri Jan 12 14:23:41  sender@domain.com
                                         user@wrongdomain.com

For a single message, you can manually edit the queue file:

# Find the message file
$ find /var/spool/postfix/deferred -name "ABC123DEF*"

# Make a backup copy
$ cp /var/spool/postfix/deferred/ABC123DEF .

# Edit the recipient information
$ postcat -q ABC123DEF > message.txt
$ sed -i 's/user@wrongdomain.com/user@correctdomain.com/' message.txt

# Re-inject into Postfix
$ postfix -i < message.txt

For bulk operations, use the official Postfix tools:

# List all messages for a recipient
$ postqueue -p | grep "user@wrongdomain.com" | awk '{print $1}' > queue_ids.txt

# Create a processing script
#!/bin/bash
while read qid; do
  postcat -q "$qid" > temp_msg
  sed -i 's/user@wrongdomain.com/user@correctdomain.com/' temp_msg
  sendmail -G -i -f sender@domain.com user@correctdomain.com < temp_msg
  postsuper -d "$qid"
done < queue_ids.txt

Always follow these precautions when modifying the mail queue:

  • Make backups of queue files before modification
  • Stop postfix during major queue operations (systemctl stop postfix)
  • Verify message integrity with postcat -q after changes
  • Consider using postsuper -H to hold messages during editing

For ongoing address corrections, implement a smtpd_recipient_restrictions filter:

# In main.cf
smtpd_recipient_restrictions =
    check_recipient_access hash:/etc/postfix/recipient_map
    ...other restrictions...

# Create recipient_map
$ cat /etc/postfix/recipient_map
user@wrongdomain.com   user@correctdomain.com

# Postmap and reload
$ postmap /etc/postfix/recipient_map
$ systemctl reload postfix

The Postfix mail queue stores messages in the /var/spool/postfix/ directory with several subdirectories:

/var/spool/postfix/
├── deferred/
├── active/
├── incoming/
├── hold/
└── corrupt/

First, locate the problematic message in the queue:

postqueue -p | grep "recipient@wrongdomain.com"

This will show you the queue ID of the message (e.g., A1B2C3D4EF).

Postfix provides tools to edit messages in the queue. Here's the safest approach:

# 1. Create a copy of the message
postcat -q A1B2C3D4EF > message.txt

# 2. Edit the recipient in the file
sed -i 's/recipient@wrongdomain.com/recipient@correctdomain.com/' message.txt

# 3. Remove the original message from queue
postsuper -d A1B2C3D4EF

# 4. Inject the corrected message
sendmail -f sender@domain.com recipient@correctdomain.com < message.txt

For bulk modifications, use this bash script:

#!/bin/bash

OLD_ADDR="wrong@example.com"
NEW_ADDR="correct@example.com"

for ID in $(postqueue -p | grep "$OLD_ADDR" | awk '{print $1}' | tr -d '!*'); do
    postcat -q $ID > temp_msg
    sed -i "s/$OLD_ADDR/$NEW_ADDR/g" temp_msg
    postsuper -d $ID
    sendmail -f $(grep '^From:' temp_msg | cut -d'<' -f2 | cut -d'>' -f1) $NEW_ADDR < temp_msg
done

Common issues when modifying queue files directly:

  • File permissions - ensure you're running as root or postfix user
  • Queue corruption - always make backups before modifications
  • Header integrity - maintain proper MIME structure when editing

For future prevention, consider setting up a header_check filter:

# In main.cf:
header_checks = regexp:/etc/postfix/header_checks

# In header_checks file:
/^To:.*wrong@example.com/ REPLACE To: correct@example.com

After making changes, verify the message is in queue with the correct recipient:

postqueue -p | grep "correct@example.com"