Triggering a script using POSTFIX....

I have a mail server configured on my server (Postfix), I have a script which requires input to be provided to it.

I would like to know if there is a possibility to trigger this script by sending mail to the server.

This is what I am thinking:

Once the mail arrives on server, the mail will contain all the input that script needs.

The script will use these variables in it and get exeucted.

Example. The script needs following input:

1 : Firstname
2 : Lastname
3 : email address
4 : Group name

Is there a possibility to make the script run once a mail comes in and then use the inputs from the mail to finish the job?

Hi,

This is possible, yes. I've done it myself in the past when this has been absolutely the only way I could remotely trigger something on a system (i.e. when SMTP was the only port a server could take incoming connections on, and so I had to use it as a crude job control method). It's not ideal, and you have to be absolutely sure that things are as locked-down security-wise as you can make them to eliminate this being a potential security hole, but if you really have to/need to, this is do-able.

I did it by having an entry in /etc/aliases for the SMTP username that then forwarded into a local pipe to my script.

So an entry like this in /etc/aliases

scriptuser: "|/usr/bin/sudo /usr/local/bin/script.sh"

would pipe the full body of any e-mail received for the mailbox scriptuser into the script /usr/local/bin/script.sh , in this instance running it via sudo as well (assuming the script needs root access).

As I say, it's a crude method and you need to be as close to 100% sure as you can be that your script does every possible kind of sanity checking and input sanitising that you can think of. But it should work for you - it certainly has for me in the past, when I've had no other choice but to go down that road.

Man!! Thank you so much for taking time to reply to my question! I really appreciate it my friend. You have no idea, how happy I am to have someone give me some leads to do this.

Now, just to give an insight of what I am doing,
I have OpenLDAP, I have created a script for adding user in it and the script is interactive, it asks for first name, lastname , email id, server name on which access is needed and Group name.

I have to manually enter all these details EVERYDAY!! sometime as many as 25 requests...

I got tired of doing it manually, so I was thinking about it.

May I know, after you sent the mail to your server, and you had already configured the aliases...

A : How did you make the script take these inputs?

I am new to scripting, this is my 1st script!! LOL

So, yes I am a script kiddie,

B: The server is on AWS (so can i not implement some kind of a security for incoming mails?)

Hi,

The main thing to consider is that any e-mail that is fed in to your script will be taken as input. So, you'll decide on a format for your input, and write your script to handle that input when it arrives in the expected e-mail. The problem arises when you consider: what will your script do with e-mails it doesn't expect, and interprets them as valid input ?

For example, consider the following. Imagine you have a script whose purpose in life is to receive an e-mail containing a list of files or directories, and which then removes that list. Let's say you decide on a format like this for your input:

LIST
/tmp/file1.txt
/var/tmp/*
END

You write your script to read the input a line at a time, and when it sees a line starting with LIST it knows it's found valid input. It will then do an rm -rf on the contents of each line it reads from the e-mail until it sees a line starting with END , at which point it stops.

All reasonable, you might think. Now consider what would happen if your script's e-mail address were to randomly receive a spam e-mail with some lines that looked like this:

Amazing new deals !
You can trust us, because we've been
LISTED ON EBAY SINCE 2000 !
/* AMAZING BARGAINS \*
/* ASTONISHING PRICES \*
/* THESE DEALS WON'T LAST FOREVER... \*
ENDS TOMORROW !

Your script would dutifully read through the e-mail, see the line starting with LISTED , interpret the LIST as the start of input, and start removing files beginning with the next line....the first part of which is /* . So what will your script then do ? rm -rf /* , that's what. Bye-bye, server.

A very contrived example I'll grant you, but it demonstrates the point. E-mail interfaces are inherently risky because you never can say for sure what might be received in that mailbox, unless you have other ways of restricting that of course.

So you must be sure that your script checks every single bit of its input, and ensures it is absolutely 100% exactly in conformity with what you expect it to handle. If it isn't, it must handle it safely, or refuse to do anything with it.

In summary, the two main things you need to remember when writing scripts triggered by e-mails are:

  1. Make sure only allowed senders and/or servers can e-mail your server's script address to trigger the script.
  2. Make sure that the script does full complete sanity checking on the input anyway, just in case.

Hope this helps give you some pointers.

You are absolutely right with that example.

I will make sure that the script only works with desired inputs.

As far as security is concerned I will consult my network team...

Do you think IFS (line) would be a good option to input these variables?

this is an example:

echo -n "What is the firstname":
read FIRST
echo -n "What is the lastname":
read LAST
echo -n "Is this a new user (Y for yes, N for No)":
read NO
if [[ $NO =~ ^(y|Y)$ ]] ; then
file=`cat uid`

x=$file
y=1
userid=$(( x + y ))


#echo -n  "What is the uid":
#read userid
echo $userid > uid
echo -n "What is the email":
read EMAIL
#echo -n "What is username":
#read USERNAME

===============================================

I will have my mail body consisting of these variables, and then make the script use it.

Does it sound like a good idea?

Hi,

In terms of the implementation, your script would want to parse line-by-line whatever is piped in to it, and then act based on what it got. The format I've used in general for scripts that run in this way (input is directly piped into them) is:

#!/bin/bash
/bin/cat - | while read -r line
do
        #Code goes here
done

The point of /bin/cat - at the start is just to print out again whatever is passed into cat as standard input (represented by the - symbol), which will be whatever Postfix is piping into the script. So you can then do whatever you wan to do with each line to determine what it is, what to do with it, and so on.

So in your case, if you had lines that would define and set variables, you could look for them on a line-by-line basis. A quick example of one way of doing this would be the following.

Let's say our e-mail body will contain the following variables: UID , USERNAME and HOMEDIR . We want our script to find these matching lines, and assign the variables it reads in. Finally we'll terminate our message body with a single line reading END , and get the script to write out the variables it's read at that point.

Here's our code:

#!/bin/bash
/bin/cat - | while read -r line
do
        case "$line" in
                UID=*)
                        uid=`echo "$line" | /usr/bin/awk -F= '{print $2}'`
                        ;;
                USERNAME=*)
                        user=`echo "$line" | /usr/bin/awk -F= '{print $2}'`
                        ;;
                HOMEDIR=*)
                        home=`echo "$line" | /usr/bin/awk -F= '{print $2}'`
                        ;;
                END)
                        echo "The UID is $uid, the username is $user, and the homedir is $home"
                        exit 0
                        ;;
        esac
done

Here's our example input:

UID=1002
USERNAME=unixforum
HOMEDIR=/home/unixforum
END

And here's what happens when we run the script by piping the contents of our example input into it:

$ cat example.txt | ./script.sh
The UID is 1002, the username is unixforum, and the homedir is /home/unixforum
$

Hope this gives you an idea of how the implementation would work, and how your approach of reading in and assigning variables to work with might look.

Thanks man!! This is very informative. Let me try these stuff, I will let you know the results,

My only concern is security implications, lets see how it goes.