1

Postfix/Dovecot

I want to create my simple custom autoresponder for Postfix, in Python, for instance. I don't need any third-party ready-to-user one.

I want it to have some custom conditions such as "autoreply only when 'from == A' or/and 'to == B' or/and "there's have been no autoprely to that email today', etc...

I've found out that I'll need to use either content_filter or spawn in master.cf. Not milter, because milter is triggered because a message has been put into a queue, whereas I'll need to autoreply to messages that already have come through. Probably.

Other better options?

How to do implement that?

Rajaru
  • 11

1 Answers1

1

I don't think there is a simple (ie trivial) way to do this, and there are most likely multiple solutions.

I implemented this for my mail system (which hosts a fair number of boxes and domains) and hooks into a custom written CMS (BLISS3) as follows:

Added to /etc/postfix/master.cf

autoresponder
        unix  -       n       n       -       -       pipe flags=Rq
    user=mailuser argv=/etc/postfix/scripts/autoresponder.php ${sender} ${recipient}

This will execute my script autoresponder.php, parsing the sender and recipient. You could write the appropriate autoresponder in python if you prefer.

I then added the following to /etc/postfix/transport

  .autoresponder autoresponder:

This command triggered the autoresponder as the appropriate transport when I foward a copy of an email to a special "user@domain.name.autoresponder" email. If you are looking to do this on a small scale, you can probably simply replace ".autoresponder" with your email address if you don't need to keep a copy of the incoming email.

All thats left is the autoresponder script itself.

My PHP script looks as follows:

#! /usr/bin/php
<?php
    #########################################################################################
    # Davids Autoresponder for BLISS3.  This has been designed to query a database to pull
    # the message contents from.
    #########################################################################################
# How frequently to resend messages, ie only send 1 message per person every period.
# The idea of this is to prevent mail loops.

$period='1 day';
$dbconnection=&quot;mysql://username:password@127.0.0.1/mail&quot;;

# We take the input, and strip off the &quot;.autoresponder&quot; part, revealing our actual address.
$from=mysqli_real_escape_string(substr($argv[2],0,-14));
$to=mysqli_real_escape_string($argv[1]);

#########################################################################################

include &quot;/usr/share/php/adodb/adodb.inc.php&quot;;
$ADODB_FETCH_MODE=ADODB_FETCH_ASSOC;
$conn=ADONewConnection($dbconnection);

$theargs=$argv[0].&quot; &quot;.$argv[1].&quot; &quot;.$argv[2].&quot;\n&quot;;
syslog (LOG_WARNING,&quot;Called autoresponder - $theargs&quot;);

# Check if the email is in our database of recently sent messages.   If not, add it.
# If it is, do not resend.   Also do not send emails if from = to

$sent=$conn-&gt;GetAll(&quot;select count(uid) from autoresponded where mailfrom='$from' and mailto='$to' and date &gt; current_timestamp - interval '$period'&quot;);

if ( $sent[0]['count'] &lt; 1 and $from != $to )
{
    $q=$conn-&gt;Execute(&quot;insert into autoresponded (date,mailfrom,mailto) values (current_timestamp,'$from','$to')&quot;);

    $messages=$conn-&gt;GetAll(&quot;select ar_subject, ar_body from virtual where mailfrom='&quot;.$from.&quot;'&quot;);

    # No point in sending if we don't have a message to send.
    if ($messages[0]['ar_subject'] != '' or $messages[0]['ar_body'] != '')
    {
        $headers='From: '.$from.&quot;\r\n&quot;;
        $subject=pg_unescape_bytea($messages[0]['ar_subject']);
        $message=pg_unescape_bytea($messages[0]['ar_body']);
        mail ($to, $subject, $message,$headers);
    }
}

# Automatically clean up after ourself.
$cleanup=$conn-&gt;Execute(&quot;delete from autoresponded where date &lt; current_timestamp - interval '$period'&quot;);

As you can see I use a simple database to keep track of when an email was last sent to a given address which I check to make sure I don't send more then 1 response per sender per day to prevent mail loops and other annoyances. The actual responder email is done with a simple mail command (6th last line)

In case you care to do something very similar,the schema for my autoresponded table is:

                                        Table "public.autoresponded"
  Column  |            Type             | Collation | Nullable |                  Default                   
----------+-----------------------------+-----------+----------+--------------------------------------------
 uid      | integer                     |           | not null | nextval('autoresponded_uid_seq'::regclass)
 date     | timestamp without time zone |           |          | now()
 mailfrom | character varying           |           |          | 
 mailto   | character varying           |           |          | 

The lines referring to ar_header and ar_body pull appropriate autoresponder header and body from a database. You can create/modify your own tables to do this or hard code them.

Hopefully the above gives you a solid starting point for doing what you want. As per @TobiM comment below, use this as the basis for your code - you probably should replace the sql with prepared statemements. I've not actually checked the modified version works, and it assumes a mysql database.

davidgo
  • 6,504