I'd like to manage all email incoming to *@example.com with a Python script running on my server, which will do various jobs.

  • I've already done a DNS MX record for example.com, directing it my server:

    mx.example.com                   MX     mailforwarder.example.com
    mailforwarder.example.com        A
  • I've done lots of trials and errors with both postfix and exim, and nothing was working, so I removed all of them: apt-get remove postfix and apt-get remove exim4, so I'm ready to start with a fresh install of one of them (which one would allow the shortest solution for this specific task?)

What are the main steps to direct all incoming email *@example.com to a Python script? (including: telling the MTA to accept emails coming from outside of the server, from whole internet, etc.)

  • 1
    Quick general answer: Install procmail ... procmail Mini-HowTo Nov 21 '17 at 14:05
  • Thanks for your comment @RubberStamp. Before diving in the deep doc of procmail, is it enough (I see there are MTA and MDA, don't know if both are needed or not) or will I need another tool in complement? If possible, could you post an answer with the relevant steps? I imagine the first step is apt-get install procmail but then how to tell the server to listen on port 25 with procmail, how to redirect the emails to a python script, etc.?
    – Basj
    Nov 21 '17 at 14:11
  • If I get a chance, I'll post a longer answer... I'm sure there are some better qualified to answer completely and quickly... the general flow of email traffic is something like this: MX record --> mail server IP --> postfix smtp --> procmail --> user mailbox .... so, you need to configure all of that. If you are not sending email, then the process is much simpler. Nov 21 '17 at 14:16
  • @RubberStamp Thanks. I was looking for MX record --> mail server IP --> postfix --> python mymailscript.py, is that possible? If it makes the answer simpler, I don't need sending emails for now (I'll add that later).
    – Basj
    Nov 21 '17 at 14:22
  • procmail is the general purpose glue to do things with email local processing... see this question on StackOverflow Pipe email from procmail to python script that parses body and saves as text file Nov 21 '17 at 14:29

procmail is considered problematical by Philip Guenther (and is quite possibly useless in this case, as .forward files or equivalent can send the mails directly to your program, skipping the thus needless complexity of procmail).

Executive summary: delete the procmail port; the code is not safe and should not be used as a basis for any further work.

As people may know, I was the upstream maintainer of procmail back in the late 1990's though 2001.

So some other solution may be advisable; this depends on the Mail Transport Agent (MTA). Another option would be to use the MTA to deliver to a local file or IMAP, then have your program parse that file or IMAP. This has the bonus of continuing to accept email and saving it somewhere; what happens when your program is buggy or otherwise fails to run? Less of a problem than during live mail delivery...


Probably either copy the Sendmail .forward method or figure out how to do this properly in Eximese. (I aborted as it was taking to much time to dig through the Exim docs.) There is elspy if you want to do at-SMTP-time scanning in a MILTER fashion...



Gosh that seems long and complicated.


Set a mailertable entry to forward all mails for the domain (and .domain for subdomains, if necessary) to a local user, here jdoe

example.com     local:jdoe
.example.com    local:jdoe

and then setup a .forward file for that user to run the necessary code

$ cat ~jdoe/.forward

which could be as simple as

$ cat /etc/smrsh/process
cat >> /home/jdoe/allmails

because the emails are fed in on standard input (this might be bad if multiple instances of this process run at once; presumably your actual code handles such race conditions or is otherwise idempotent...right?). This method may also work for any other MTA that copies Sendmail's forward syntax, assuming you can get the MTA to redirect all mails to a particular user.

This assumes mailertable support is enabled, confFORWARD_PATH is set, that Sendmail is allowed to run the code (see smrsh(8) though note that some vendors may change the directory without updating the documentation (running strings /the/path/to/smrsh | fgrep / may help)) and that something like selinux isn't also breaking things.

Another option for Sendmail is to use a MILTER such as MIMEDefang and perform whatever business logic is necessary there. (Various other MTA support MILTER, or have something like it.)

Simple Mail Transfer Protocol daemon (OpenBSD)

From a look at smtpd.conf(5) (updated for OpenBSD 6.4 changes)

action "mymda" mda "/path/to/your/command" user jdoe
match from any for domain example.com action "mymda"
  • And other persons have other opinions on procmail Is it safe to use procmail in 2017? ... One could argue that running anything on the Internet is unsafe. So let's not use it. Nov 21 '17 at 19:01
  • @RubberStamp given that MTA can directly run the desired program, what is the value add of tossing procmail into the mix? It's a useless use of cat in this case.
    – thrig
    Nov 22 '17 at 15:32
  • Just being picky... There are many ways to solve the problem. All of the methods involve some sort of security risk. For example, the postfix catch-all method will result in all incoming mail, including all spam mail sent to non-existent mail users, being sent to the processing script. I can imagine numerous security problems with that particular solution.... in many cases, the procmail problem is simply kicked over the fence to a different program or process. Nov 22 '17 at 16:14

This seemed like a common enough question... I found this already answered which is what I would suggest. Procmail is a local delivery agent.. which I think means something has already received the mail from the network and handed it off to procmail for local delivery or other filtering. In this case postfix would be that thing. Having run postfix in production it's a solid tool and very flexible for custom mail handling.



I like the mail-in-a-box stack which uses Postfix & Dovecot. Once you have those installed you can do the following to execute a script on receipt of mail to specific addresses:

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

    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 any mailbox with this sieve filter will be piped through mail_processor.py for action.

Pigeonhole Sieve: Extprograms Plugin for reference

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.