Requeuing failed messages

Mark Sapiro mark at
Wed Jan 4 00:09:09 UTC 2017

On 01/02/2017 05:05 PM, Mark Sapiro wrote:
> On second thought, the above sendmail command is probably not a good
> idea. The issue is that -t will send the message to all To: and Cc:
> recipients in the message headers. This can include addresses which are
> in other domains and which probably already received the message and may
> not even include the intended recipient of the quarantined message
> (e.g., a Bcc:).
> It is better to do
> sendmail -i user at < quarantined_message_file
> where user at is the intended local recipient. Note that if the
> MTA is Postfix, the quarantined message will have a topmost Received:
> header of the form
> Received: from some server ...
> 	by your server ...
> 	for <user at> ...
> that will expose the recipient address.

On third thought, there will be issues with even the above because
Postfix will have put a Delivered-To: header in the message so
re-injecting it will result in it being rejected for a mail loop.

I wrote a little Python 3 script to address this. It is attached. You
can run it with the path to the saved message as the argument and it
will read and parse the message, look for " for <user at>;" in
the Received: headers, delete any Delivered-To: headers and pipe the
message to sendmail for user at

If necessary, it could be fairly easily converted to Python 2.

Mark Sapiro <mark at>        The highway is for gamblers,
San Francisco Bay Area, California    better use your sense - B. Dylan

-------------- next part --------------
#! /usr/bin/python3
"""Read a file containing an email message and the name of which is the
command argument. Find the recipient in a Received: header and pipe the
message to sendmail to resend it to the recipient.
import os
import re
import sys
import email
import subprocess

def main():
    if len(sys.argv) != 2:
            'usage: {} input_file'.format(os.path.basename(sys.argv[0])),
        fp = open(sys.argv[1], 'rb')
    except IOError as e:
            "Can't open {}: {}".format(sys.argv[1], e),
    msg = email.message_from_binary_file(fp)
    for h in msg.get_all('received', []):
        mo ='\sfor <([^>]*)>;', h)
        if mo:
    if not mo:
        print("Can't find recipient in message.", file=sys.stderr)
    del msg['delivered-to']
        p = subprocess.Popen(
            ['sendmail', '-i',],
    except OSError as e:
        print('error: {}'.format(e), file=sys.stderr)
    so, se = p.communicate(msg.as_bytes())
    if p.returncode:
        print('error: status={}: {}'.format(p.returncode, se), file=sys.stderr)
    if len(so) > 0:

if __name__ == '__main__':

More information about the MailScanner mailing list