Skip to page content or Skip to Accesskey List.

Work

Main Page Content

Incoming Mail And Php

Rated 4.13 (Ratings: 14)

Want more?

 
Picture of gvtulder

Gijs van Tulder

Member info

User since: 05 Feb 2002

Articles written: 7

We all know how to send email from PHP. Actually, it's quite easy: 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_creator

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.

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

for ; Wed, 22 May 2002 18:00:41 +0200

From: "Gijs van Tulder"

To:

Subject: Test

Date: Wed, 22 May 2002 18:00:41 +0200

Message-ID: <KNEOKJCOCHEDPIMPAIMIOEOJCJAA.gijs@debian>

MIME-Version: 1.0

Content-Type: text/plain;

charset="iso-8859-1"

Content-Transfer-Encoding: 7bit

X-Priority: 3 (Normal)

X-MSMail-Priority: Normal

X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0)

Importance: Normal

X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000

This is my message.

Thank you.

The 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: 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

<?php

The 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);

// empty vars

$from = "";

$subject = "";

$headers = "";

$message = "";

$splittingheaders = true;

We have just set the $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]."

";

// 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;

}

}

?>

We now have the headers, the message, the From and Subject information and can save these in a database. You could also use the 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.

The process

When an email arrives at the address you configured, it is piped to the script we just wrote. The script processes the headers and the message and returns is in a few useful variables. You can use this as a first building block to write your own mailing list, or do something else with it.

As usually, you can copy and paste the parts of this script, or download it as a text file.

Gijs van Tulder is a Dutch student. He likes to play with all things web related and fancies himself as a part-time amateur web developer.

The access keys for this page are: ALT (Control on a Mac) plus:

evolt.org Evolt.org is an all-volunteer resource for web developers made up of a discussion list, a browser archive, and member-submitted articles. This article is the property of its author, please do not redistribute or use elsewhere without checking with the author.