Main Page Content
Incoming Mail And Php
We all know how to send email from PHP. Actually, it's quite easy:
or:
myemail@example.com," /our/script.php"Watch out: if you don't add another address to your .forward file, the email is deleted after being sent to the script. You will lose your email.
or:
mail("to@me", "Hello", "Hello");
Handling mail the other way, sending email to PHP is a task much more unknown. In this article, we will write and install a script that we can send an email to.What do we want?
We want to write and install a script that handles incoming mail. We want our script not to be reachable by a web browser, but by our email client. Sending an email to script@example.com would suffice for running our script and processing the mail.Why would we want this?
Well, that's a stupid question, because we don't know how to do it and it's fun. You're reading evolt because you want to learn something, aren't you? But this script could be useful. For example:- we could write our own mailing list;
- we could send out a survey by email, that can be filled out by just clicking 'reply';
- we could manage parts of our site by sending commands by email;
- etc...
What do we need?
Because the script is triggered by an email, we will have to take a bit of a different approach than when our script is run by someone requesting a web page. Our script has to be started by the mail system. You will need:- PHP compiled as a CGI binary, not just as an Apache module;
- a local mail system or MTA, (are you using Sendmail, Exim, Qmail or some other system);
- shell access to your server, whether or not you have to be root depends on your mail system.
Step 1: Email to PHP
The first thing we have to do, is tell our mail system to send all mail addressed to script@example.com to our script. How to accomplish this, depends on which mail system you use.Sendmail
There are two different approaches for forwarding mail to a program in Sendmail. You can create a real user for our script and create a .forward file, or you can create an alias in your aliases file. If you have root access, the latter would be the best option.If using the aliases file, this can be found in /etc, you add the following line.script
is the email alias for our script, /our/script.php
should be substituted with the full path to the script.script: " /our/script.php"
If using a forward file, create a file named .forward
in your home dir. Then add the following line and save the file. Email sent to you, will be forwarded to the script. If you'd also like the email sent to another address, you can add that address before the script and tailed by a comma. /our/script.php
should be substituted with the full path to the script. " /our/script.php"
or:
myemail@example.com," /our/script.php"Watch out: if you don't add another address to your .forward file, the email is deleted after being sent to the script. You will lose your email.
Exim
There are two different approaches for forwarding mail to a program in Exim. You can create a real user for our script and create a .forward file, or you can create an alias in your aliases file. If you have root access, the latter would be the best option.If using the aliases file, this can be found in /etc, you add the following line.script
is the email alias for our script, /our/script.php
should be substituted with the full path to the script.script: /our/script.php
You also have to edit your exim.conf, found at /etc/exim.conf. Look for a part containing 'address_pipe'. If there is such a part, replace it with the text below. If there is no such text, paste this text somewhere in exim.conf. Save the file.address_pipe: driver = pipe pipe_as_creatorIf using a forward file, create a file named
.forward
in your home dir. Then add the following line and save the file. Email sent to you, will be forwarded to the script. If you'd also like the email sent to another address, you can add that address before the script and tailed by a comma. /our/script.php
should be substituted with the full path to the script. /our/script.php
or:
myemail@example.com, /our/script.php
Watch out: if you don't add another address to your .forward file, the email is deleted after being sent to the script. You will lose your email.Qmail
There are two different approaches for forwarding mail to a program in Qmail. You can create a real user for our script and create a .qmail file, or you can create an alias. If you have root access, the latter would be the best option.One thing I like about Qmail, is the possibility of creating custom aliases. If you are a normal user, you can create an alias by saving a file called .qmail-foo in your home directory. Email sent to yourusername-foo@example.com is then sent as specified in this file.If you want to create just an alias, without being an user, eg. myscript@example.com, you create a .qmail file in the /var/qmail/alias directory. .qmail-myscript should do it.Add the following to your .qmail file and save it./our/script.php
should be substituted with the full path to the script. /our/script.php
Step 2: The email
Because the email is passed to the script as a raw email, it is useful to take a closer look at the structure of an email.Received: from gijs ([192.168.55.2]) by debian with smtp (Exim 3.12 #1 (Debian)) id 17AYXZ-0002BE-00 forThe first part of the raw email contains the headers. A header contains information about the email. The header has a name, before the colon, and a value:; Wed, 22 May 2002 18:00:41 +0200From: "Gijs van Tulder" To: Subject: TestDate: Wed, 22 May 2002 18:00:41 +0200Message-ID: <KNEOKJCOCHEDPIMPAIMIOEOJCJAA.gijs@debian>MIME-Version: 1.0Content-Type: text/plain; charset="iso-8859-1"Content-Transfer-Encoding: 7bitX-Priority: 3 (Normal)X-MSMail-Priority: NormalX-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0)Importance: NormalX-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 This is my message.
Thank you.
Header-Name: Value
. Important headers are the Subject header, containing the subject of the email, the From header, containing the origin of the email, and the To header, which tells us something about the recipient. The other headers are of minor importance.An empty line marks the end of the header part. After the first empty line, follows the body of the email.Step 3: The script
Since our script will function as a shell script, the first line should contain the path to the PHP CGI program. This is most likely located at /usr/bin/php of /usr/local/bin/php. This tells the operating system that this script must be parsed by PHP.#!/usr/bin/php<?phpThe email is sent to the script through stdin. This is a special 'file' that can be reached by opening
php://stdin
. We will do that now and read the email.// read from stdin$fd = fopen("php://stdin", "r");$email = "";while (!feof($fd)) { $email .= fread($fd, 1024);}fclose($fd);Now we have the full text of the email in the
$email
variable, we can start splitting headers from body. We will do that line by line, so the first step would be splitting the email. We also empty the variables that we will fill with the From header, the Subject header, and save other information in.// handle email$lines = explode("", $email);We have just set the// empty vars
$from = "";$subject = "";$headers = "";$message = "";$splittingheaders = true;
$splittingheaders
variable to true. As long as this variable is true, and we have not yet seen an empty line, the text should be added to $headers
. If we find a Subject or a From header, we will save it in the appropriate variable.After we have seen the first empty line, we have processed the headers and can start adding the lines to $message
.for ($i=0; $i < count($lines); $i++) { if ($splittingheaders) { // this is a header $headers .= $lines[$i]."";We now have the headers, the message, the From and Subject information and can save these in a database. You could also use the// look out for special headers
if (preg_match("/^Subject: (.*)/", $lines[$i], $matches)) { $subject = $matches[1]; } if (preg_match("/^From: (.*)/", $lines[$i], $matches)) { $from = $matches[1]; } } else { // not a header, but message $message .= $lines[$i].""; }if (trim($lines[$i])=="") {
// empty line, header section has ended $splittingheaders = false; }}?>
mail()
function to send an automatic reply. That's up to you.Step 4: Copying
Now you wrote and saved the script, you have to copy it to its final destination, the location you configured in your mail system. You should also make the script executable:chmod 755
Remember: it's a shell script, not a web page.