Resend mail that’s locally stored in a mbox format on a Linux box to a working email address

The specific use case is that I didn't have Postfix properly configured on some machine to send mail, and it was delivered locally to "/var/spool/mail/root". I fixed the problem by adding my actual email address in "/etc/aliases" such that mail sent to root will now be sent to my email, but would also like the old messages sent there as well.

TL;DR for the impatient

myemail=username@example.com
cat /var/spool/mail/root |
formail -k                \
        -X From:          \
        -X Subject:       \
        -X Message-Id:    \
        -X Date:          \
        -X To:            \
        -I "To: $myemail" \
        -s /usr/sbin/sendmail -t -f $myemail

Explanation

All the messages are stored in "/var/spool/mail/root" in a mbox file format, e.g.:

From root@somebox  Thu Jan  2 11:38:22 2014
Return-Path: <root@somebox>
X-Original-To: root
Delivered-To: root@somebox
Received: by somebox (Postfix, from userid 0)
        id B612F2C0E36; Thu,  2 Jan 2014 11:38:22 -0800 (PST)
From: some daemon <root@somebox>
To: root@somebox
Subject: Important message from some daemon on somebox
Message-Id: <2014010204825.B612F2C0E36@somebox>
Date: Thu,  2 Jan 2014 11:38:22 -0800 (PST)
 
This is a very important message from some daemon running on some box.
 
From root@somebox  Fri Jan  3 12:48:25 2014
Return-Path: <root@somebox>
X-Original-To: root
Delivered-To: root@somebox
Received: by somebox (Postfix, from userid 0)
        id B612F2C0E37 Fri,  3 Jan 2014 12:48:25 -0800 (PST)
From: some daemon <root@somebox>
To: root@somebox
Subject: Another important message from some daemon on somebox
Message-Id: <20140103204825.B612F2C0E37@somebox>
Date: Fri,  3 Jan 2014 12:48:25 -0800 (PST)
 
This is another very important message from some daemon running on some box.

First, I'm using "formail" (available from the "procmail" package on Debian and friends -- "sudo apt-get install procmail") to split the mbox file into individual email messages, just keeping some of the headers, and replacing the original recipient (i.e. root@somebox) with my working email address ($myemail in this example).

Second, formail feeds the messages one by one to Postfix (via sendmail command).

Without email header manipulation, the message looks like:

# cat msg-example
From root@somebox  Thu Jan  2 11:38:22 2014
Return-Path: <root@somebox>
X-Original-To: root
Delivered-To: root@somebox
Received: by somebox (Postfix, from userid 0)
        id B612F2C0E36; Thu,  2 Jan 2014 11:38:22 -0800 (PST)
From: some daemon <root@somebox>
To: root@somebox
Subject: Important message from some daemon on somebox
Message-Id: <2014010204825.B612F2C0E36@somebox>
Date: Thu,  2 Jan 2014 11:38:22 -0800 (PST)
 
This is a very important message from some daemon running on some box.

When I fed messages like this to Postfix, email delivery would fail with the errors like:

Jan  3 13:30:52 somebox postfix/local[13402]: 3FA762C12F6: to=<root@somebox>, relay=local, delay=0.01, delays=0.01/0/0/0, dsn=5.4.6, status=bounced (mail forwarding loop for root@somebox)

After header cleanup, the message looks like:

cat msg-example |
formail -k              \
        -X From:        \
        -X Subject:     \
        -X Message-Id:  \
        -X Date:        \
        -X To:          \
        -I "To: $myemail"
From: some daemon <root@somebox>
Subject: Important message from some daemon on somebox
Message-Id: <2014010204825.B612F2C0E36@somebox>
Date: Thu,  2 Jan 2014 11:38:22 -0800 (PST)
To: username@example.com
 
This is a very important message from some daemon running on some box.

And Postfix happily processed messages like that and delivered to $myemail.

1 Comment

  • 1. Remie Löwik replies at 21st December 2014, 6:43 pm :

    Helped me alot :), but when emails have images etc embedded(multipart email) in them some critical information gets lost(content type) when cleaning up the headers. I think adding -X Content-Type: to the formail solves this problem.

Leave a comment

NOTE: Enclose quotes in <blockquote></blockquote>. Enclose code in <pre lang="LANG"></pre> (where LANG is one of these).