6

I want to parse and insert some information from the mail that just arrived in a mission critical application's mail server.

I there any way to configure my mail server so that it run a script when mail arrives.

Although I have a debian system but any generic solution (Linux) will do.

6

6 Answers 6

7

Looks like someone else has already answered this but thought I'd put down a specific answer for you.

I would use procmail and use a recipe in your .procmailrc similar to this:

#turn this off when you're finished testing :)
VERBOSE=on
LOGFILE=/home/user/procmail.log

:0 c #the c means continue on after this recipe is parsed
| /path/to/your/script

You'll also need a default recipe at the bottom to direct the mail into your maildir.

4
4

You can use /etc/aliases to pipe email directly to a program to process, so if you wanted to run a script to process all email to [email protected] you would put this line in /etc/aliases (works for postfix, sendmail, etc.):

test:              "|/usr/local/bin/processtestemail.php"

Then run "newaliases" to update the database.

Then make sure you have a working program in /usr/local/bin named processtestemail.php.

It can be written in php, bash, perl, python, whatever you want and whatever you have for an interpeter. You could even launch a compiled binary written in c/c++, etc.

There were suggestions for using procmail above, it is a great product, but honestly what I have presented is the fastest and simplest solution and it works in more versions of *NIX with more mailers than any other.

Too, non of the other answers really tell you how to process the inbound message and so you would, in your script read input from standard "in" (stdin) and then parse that data using whatever algorithms you may have to process it properly as follows:

<?php

$fd = fopen('php://stdin','r');
if ($fd) then
    {
    $email = '';                         // initialize buffer
    while (!feof ($fd))                  // read as long as message
        {
        $rawemail .= fread($fd,1024);    // read up to 1K at a time
        ProcessTheMessageChunk($rawEmail);
        }
    fclose($fd);                         // done so close file handle
    $fd=NULL;                            // clear file handle
    }
else
    {
    print("ERROR:  Could could open stdin...");
    };

/* 
** Now write your code to fill in the function ProcessMessageChunk()
** and then process the data you have collected altogether using
** that function/subroutine.
*/

?>
3

Here's a good howto on incoming mail processing. The simplese thing to do is to use the .forward mechanism as described, to pipe a message through a script. Create a mode 600 .forward file in the user's home directory and put a pipe to a script in it:

"|$HOME/bin/your.program -and some arguments" 

However, you should look at using procmail instead, as that howto details. Procmail gives you a lot of advantages, such as more sophisticated logging and mail processing. Here's a simple .procmailrc example (again from that same howto):

:0
* !^FROM_DAEMON
* !^FROM_MAILER
* !^X-Loop: [email protected]
| $HOME/bin/my.script 

which has some nice features, like the ability to detect and stop mail loops.

1

The question was "how do I run a script when mail arrives", not how to use procmail, not a bunch of other things. All the other answers are very helpful, but they require installation of other software such as procmail or are MTA dependent.

The most generic answer that works on all flavors of *NIX no matter what mail transfer agent (MTA) you have (e.g., sendmail, postfix, exim, etc.) is to put a PIPE on an alias to a script in /etc/aliases like so:

mytest:              "|/usr/local/bin/mytestscript -args"

Then, any message that gets sent to "mytest@" will get routed to the script.

Now, I am a huge fan of procmail and other solutions and am not trying ot take away from all the great info presented.

1

If your server uses Dovecot you could do the following:

  1. create your script (ie. mail_processor.py) in the /usr/lib/dovecot/sieve-execute/ directory:

    #!/usr/bin/python3
    from sys import stdin
    with open('/var/log/mail_processor.log', 'a') as logfile:
        for line in stdin:
            print(line.rstrip(), file=logfile)
    
    • ensure your script and target files have correct permissions:

      $ chmod +rx /usr/lib/dovecot/sieve-execute/mail_processor.py
      $ chmod 0777 /var/log/mail_processor.log
      
  2. enable the sieve_extprograms plugin:

    • modify \etc\dovecot\conf.d\90-sieve.conf's plugin section with the following:

      sieve_extensions = +vnd.dovecot.execute
      sieve_plugins = sieve_extprograms
      sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute
      
    • reload dovecot:

      $ service dovecot restart
      
  3. create sieve filter (ie. in Roundcube goto settings -> filters -> actions -> edit filter set):

    require ["vnd.dovecot.execute"];
    # rule:[mail processing]
    if true
    {
        execute :pipe "mail_processor.py";
    }
    

Now all mail delivered to mailboxes with this sieve filter will be piped through mail_processor.py for action.

Pigeonhole Sieve: Extprograms Plugin documentation for reference

0

In postfix you could hold all incoming messages (that matches some pattern, or simply all of them), have your application pick them up in the hold/ directory and then place them back to the incoming/ directory once done. This is how the antispam filter MailScanner works when used with postfix.


In the Postfix configuration file /etc/postfix/main.cf add this line:
header_checks = regexp:/etc/postfix/header_checks
In the file /etc/postfix/header_checks add this line:
/^Received:/ HOLD

The effect of this is to tell Postfix to move all messages to the HOLD queue, when your application is done I believe you should put the mails in the incoming/ directory.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .