How to create my own simple autoresponder for Postfix with custom conditions?
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 "[email protected]" 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="mysql://username:[email protected]/mail";
# We take the input, and strip off the ".autoresponder" part, revealing our actual address.
$from=mysqli_real_escape_string(substr($argv[2],0,-14));
$to=mysqli_real_escape_string($argv[1]);
#########################################################################################
include "/usr/share/php/adodb/adodb.inc.php";
$ADODB_FETCH_MODE=ADODB_FETCH_ASSOC;
$conn=ADONewConnection($dbconnection);
$theargs=$argv[0]." ".$argv[1]." ".$argv[2]."\n";
syslog (LOG_WARNING,"Called autoresponder - $theargs");
# 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->GetAll("select count(uid) from autoresponded where mailfrom='$from' and mailto='$to' and date > current_timestamp - interval '$period'");
if ( $sent[0]['count'] < 1 and $from != $to )
{
$q=$conn->Execute("insert into autoresponded (date,mailfrom,mailto) values (current_timestamp,'$from','$to')");
$messages=$conn->GetAll("select ar_subject, ar_body from virtual where mailfrom='".$from."'");
# 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."\r\n";
$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->Execute("delete from autoresponded where date < current_timestamp - interval '$period'");
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.