How to Programmatically Modify Recipient Addresses in Postfix Mail Queue


5 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"