autoreply.py
is a Postfix filter to send auto-reply emails when a message sent to a qualifying email address enters the Postfix mail system.
It supports authentication, StartTLS and HTML for the auto-reply.
The proposed Postfix configuration uses check_recipient_access
to instruct Postfix to only pipe emails that are addressed to these qualifying email addresses to autoreply.py
, while the rest continue their normal flow. The script, using settings stored in autoreply.json
, sends the auto-reply and re-injects the original email into Postfix for delivery.
The look up table related to check_recipient_access
is used for any mail received by SMTP but not for emails sent locally, using sendmail.
autoreply.py
could be easily adapted to do other things with the original email like extracting information or storing attachments.
The following sections provide a step-by-step guide on how to set up autoreply.py
and Postfix to send auto-replies.
One of our clients had a complex email infrastructure and they wanted a script that would trigger auto-replies when emails sent to some specific addresses entered one of their MTAs. Normally, these auto-replies would have been configured at an MDA/mailbox level.
The MTA in question was Postfix and it relayed all the emails to another SMTP server which they couldn't/wanted to configure differently.
After some consideration, it was deemed viable to use an after-queue content filter in Postfix to achieve this.
As the email addresses that would need to auto-reply would change over time, as well as the subjects and wording of the auto-reply emails, we decided to use a JSON file to store that information which could be changed without having to edit the script.
This section is somehow optional but please note that, as per Postfix's FILTER documentation, filter scripts should be run using a separate account, as these are handling potentially malicious emails. To quote their documentation, do not use "nobody", and most certainly do not use "root" or "postfix".
- Add autoreply user with home directory /opt/autoreply and nologin.
sudo useradd -d /opt/autoreply -s /usr/sbin/nologin autoreply
- Create autoreply's home directory.
sudo mkdir /opt/autoreply
- Change autoreply's home directory ownership.
sudo chown autoreply:autoreply /opt/autoreply
- Restrict access to autoreply's home directory.
sudo chmod 700 /opt/autoreply
- Change to autoreply user.
sudo su - autoreply -s /bin/bash
- Download
autoreply.py
.
wget https://github.com/innovara/autoreply/raw/master/autoreply.py
- Change permissions.
chmod 700 autoreply.py
- Run ./autoreply.py -j to generate ~/autoreply.json.
./autoreply.py -j
- Edit autoreply.json.
nano autoreply.json
{
"logging": false,
"SMTP": "localhost",
"port": 25,
"starttls": false,
"ssl": false,
"smtpauth": false,
"username": "user",
"password": "pass",
"autoreply": [
{
"email": "foo@bar",
"from": "Foo Bar <foo@bar>",
"reply-to": "foo@bar",
"subject": "RE: {ORIGINAL_SUBJECT}",
"body": "Email body here, autoreply for {ORIGINAL_DESTINATION}",
"html": false,
"_comment": "If you set html to true, set body to the full path of your html file"
}
]
}
Explanation:
- logging: true or false to enable/disable logging to ~/autoreply.log.
- SMTP: server that will send the auto-reply emails.
- port: SMTP port of the server.
- starttls: true to enable STARTTLS.
- ssl: true to enable SSL when it is required from the beginning of the connection and using STARTTLS is not appropriate.
- smtpauth: true if authentication is required.
- username: SMTP user.
- password: SMTP user's password.
- email: email address, or list of email addresses, that would trigger an auto-reply.
- from: email address that you want to show the auto-reply coming from.
- reply-to: the reply-to email address the auto-reply receivers will see. Useful when using noreply@...
- subject: the subject of the auto-reply email. Use {ORIGINAL_SUBJECT} to include the original subject from the sender.
- body: text of auto-reply email when using plain-text format, or path to HTML file when using it. Use {ORIGINAL_DESTINATION}, here or on the HTML file, to include the email address of the recipient that triggered the autoreply.
- html: true when using HTML auto-reply emails.
Note about upgrades and the configuration file:
auto-reply.py
doesn't implement any version control nor is developed with much attention to issues arising from the script encountering previous versions of the configuration file. Therefore, the script can crash when a new setting is not present because of this. The recommendation when upgrading is to create a new JSON config file and to port the existing settings to it. And of course, it is expected that you will test this on a pre-production environment to ensure new changes won't break anything for you in production. If copying existing settings isn't a viable solution because of the size of your deployment, considering reaching out to us for a commercial engagement to further develop upgrade paths.
- If you want to set up a few email addresses that share the same auto-reply configuration, the JSON file would look something like this.
{
"logging": false,
"SMTP": "localhost",
"port": 25,
"starttls": false,
"ssl": false,
"smtpauth": false,
"username": "user",
"password": "pass",
"autoreply": [
{
"email": "foo1@bar, foo2@bar",
"from": "Foo Bar <foo@bar>",
"reply-to": "foo@bar",
"subject": "RE: {ORIGINAL_SUBJECT}",
"body": "/path/to/email.html",
"html": true,
"_comment": "If you set html to true, set body to the full path of your html file"
}
]
}
- If you want to set up various email addresses with different auto-reply configuration, the JSON file would look something like this.
{
"logging": false,
"SMTP": "localhost",
"port": 25,
"starttls": false,
"ssl": false,
"smtpauth": false,
"username": "user",
"password": "pass",
"autoreply": [
{
"email": "foo1@bar",
"from": "Foo1 Bar <foo1@bar>",
"reply-to": "foo1@bar",
"subject": "RE: {ORIGINAL_SUBJECT}",
"body": "/path/to/email.html",
"html": true,
"_comment": "If you set html to true, set body to the full path of your html file"
},
{
"email": "foo2@bar",
"from": "Foo2 Bar <foo2@bar>",
"reply-to": "foo2@bar",
"subject": "RE: {ORIGINAL_SUBJECT}",
"body": "Email body here, autoreply for {ORIGINAL_DESTINATION}",
"html": false,
"_comment": "If you set html to true, set body to the full path of your html file"
}
]
}
- If you want to create an email file for testing, use
./autoreply.py -t
and edittest.txt
to changeFrom
,To
andReply-to
accordingly.
./autoreply.py -t
nano test.txt
- Run a test from the command line.
./autoreply.py from@bar to@bar < test.txt
At this point, the recipient of the test email should have received the test email from the sender, and the sender an auto-reply message from the recipient.
- Exit autoreply shell
exit
Now, you have to edit the configuration of the Postfix server to pipe emails to the script.
You could pipe all the emails to autoreply.py
, but the script would unnecessarily handle a number of emails that would not trigger an auto-reply.
To avoid emails out of the scope of autoreply.py
being piped to it, we use check_recipient_access
under smtpd_recipient_restrictions
in main.cf
.
Bear in mind that, if there are multiple recipients, Postfix will pipe the email as long as at least one of them is in the lookup table.
- Create a Postfix lookup table input file.
sudo nano /etc/postfix/autoreply
- Add one line per recipient:
foo@bar FILTER autoreply:dummy
- Create its corresponding Postfix lookup table.
sudo postmap /etc/postfix/autoreply
- Back up
main.cf
.
sudo cp /etc/postfix/main.{cf,cf.bak}
- Edit
main.cf
.
sudo nano /etc/postfix/main.cf
- Add the new lookup table as the first item in
smtpd_recipient_restrictions
.
smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/autoreply
- Back up
master.cf
.
sudo cp /etc/postfix/master.{cf,cf.bak}
- Edit
master.cf
.
sudo nano /etc/postfix/master.cf
- Add the autoreply pipe at the end of the file. Edit user and script path if you are not following the instructions regarding system configuration.
# autoreply pipe
autoreply unix - n n - - pipe
flags= user=autoreply null_sender=
argv=/opt/autoreply/autoreply.py ${sender} ${recipient}
- Restart Postfix.
sudo systemctl restart postfix
You are ready to go. If everything went well, when Postfix receives emails that are addressed to your target auto-reply recipients, it will pass them to autoreply.py
and the script will send the auto-reply email according to your configuration.