April 2011
« Mar   Jun »

Postfix : piping all mails to custom script

One of the project requires dynamic email account creation and pickup the attachment coming to their mailboxes from the application.

I have sex mx and spf record to my testing server and prepared postfix to access the mails from my testing domain. Now all the mails reached to users home directory and I want to be managed by the application.

I have done 3 steps for this.
a. modify the “default_privs” value in “/etc/postfix/” with system user who can execute the script.
b. Added a new transport in “/etc/postfix/’ virtual_transport = email_route

[root@rc-126 ~]# cat /etc/postfix/ | grep "default_privs"
# The default_privs parameter specifies the default rights used by
default_privs = rakesh
[root@rc-126 ~]# cat /etc/postfix/ | grep "virtual_transport"
virtual_transport = email_route

c. Now we need to add the email pipe for this transport in “/etc/“. My entry is as shown below,

   [root@rc-126 ~]# cat /etc/postfix/ | grep "email_route"
email_route unix -    n    n    -    -    pipe flags=FR user=rakesh  argv=/home/rakesh/public_html/goturi/trunk/emails/mail_handle.php  -f  $(sender) -- $(recipient)

note that it’s a single line. This shows that all the mails coming to postfix server is routed to this php script ‘/home/rakesh/public_html/goturi/trunk/emails/mail_handle.php” which will read the content and process it.

How do I verify that email piping working ?

This is my php script which will store everything coming through standard input and write it to a file (here “test.txt”).

$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd)) {
    $email .= fread($fd, 1024);
$fh = fopen('/home/rakesh/public_html/goturi/trunk/emails/test.txt','a');
fwrite($fh, $email."nn");

Now, I’m going to send a test mail to my mail server

[root@rc-126 emails]# echo " This mail is testing email piping " |  mail -s "Piped email  "

By verifying the postfix mail log

[root@rc-126 emails]# tail -f /var/log/maillog
Apr 26 10:22:02 rc-126 postfix/pickup[3650]: 4C0DE1684DD: uid=0 from=<root>
Apr 26 10:22:02 rc-126 postfix/cleanup[4637]: 4C0DE1684DD: message-id=<20110426045202.4C0DE1684DD@rc-126.rainconcert.intra>
Apr 26 10:22:02 rc-126 postfix/qmgr[3651]: 4C0DE1684DD: from=<root@rc-126.domain.intra>, size=364, nrcpt=1 (queue active)
Apr 26 10:22:02 rc-126 postfix/pipe[4640]: 4C0DE1684DD: to=<>, orig_to=<>, relay=subscribe, delay=0.06, delays=0.02/0/0/0.04, dsn=2.0.0, status=sent (delivered via email_route service)
Apr 26 10:22:02 rc-126 postfix/qmgr[3651]: 4C0DE1684DD: removed

Note the our transporter (email_route) is listed in the log

Verify my script’s output file having any entries,

#tail -f /home/rakesh/public_html/goturi/trunk/emails/test.txt
<em>From root@rc-126.rainconcert.intra  Tue Apr 26 10:22:02 2011
Return-Path: <root@rc-126.domain.intra>
Received: by rc-126.domain.intra (Postfix, from userid 0)
        id 4C0DE1684DD; Tue, 26 Apr 2011 10:22:02 +0530 (IST)
Subject: Piped email
Message-Id: <20110426045202.4C0DE1684DD@rc-126.mydomain.intra>
Date: Tue, 26 Apr 2011 10:22:02 +0530 (IST)
From: root@rc-126.domain.intra (root)
 This mail is testing email piping

Cool !! it’s recorded my email 🙂

We can make this similar setup easily in Cpanel based hosting. Ony thing we need to do is choose “default address” option from the Email menu to do that rather than creating custom user level filtering. This will help to use the email those who having email account created under the domain already. Suppose if you wish to operate a particular email operated by a script, You may use “user level filtering” in place.

Following screen shot will help you to do that.

Pls note that yu need to

1. choose your domain name where email routing going to enable
2. Chose only a path after your home directory
public_html/ rather than /home/em9876/public_html/
3. Use hashbang on the top of ur script. Here I uses #!/usr/local/bin/php -q

5 comments to Postfix : piping all mails to custom script

  • Anoop Kumar

    Please let me know, how we can pipe specific email address like “” to a script.

  • I know this is a year later, but I was wondering, each mail you send to the server, can you use the server in a general purpose way and STILL use your script?

    I tried this approach and what happened was that I can’t receive any email into the inbox, I can’t login, I can’t send email, it’s like this filter blocks everything else, so turns it into an “archiving server” only.

    This is the link I followed:

    what I would like, is to process all the email through my script, but still be able to send email, check email, login, etc, I just want to add an additional “filter”

    did you ever figure out how to do that ?

  • After trying different methods i came to this and this took only 2 minutes. Really great article and information. I have a question. Is it possible to deliver the mail to mailbox also? cause after running the script i am getting it processed in real time but i want the mail should go in mailbox dir also.

    Thanks for giving such a Very useful information. 🙂

  • Thank you for the good information! Simply adding the default_privs = (user) solved my problems, I had the alias set up in /etc/aliases table, however it was giving the error “Cannot append to file”, until I changed that. I’m also using the + delimiter to sort out emails, instead of blanket accepting all. Keep up the good work!

  • Sep

    I agree with Christopher and Vivek – Is there a way to run the script AND pass the mail to the mailbox as normal.

    For example, I have postfix setup with roundcube but when I use piping, roundcube does not receive the mail.

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>