In my previous article “PHP e-mail PIPE, cPanel PIPE forwarding” I was explaining how you can create an e-mail PIPE and get the e-mail with PHP.

This is the code you should use to get the email from stdin:

// read from stdin
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd)) {
$email .= fread($fd, 1024);
}
fclose($fd);

Now, we have the content of email in the $email variable.
For decoding the content I used several classes and the best I found is PEAR Mail_mimeDecode. I will continue my tutorial with PEAR’s MailDecode class. If you choose to use another class you can find plenty (search on PHPClasses.org).

We have to make sure we have the mimeDecode class installed on our host.
Run phpinfo().
If it is installed you should find it under ‘Mail_mimeDecode’ name. If you use cPanel you can install it from ‘PHP Pear Packages’.

How to install PEAR's Mail_mimeDecode class

In this screen search for ‘mail’ and you will find 2 useful classes:
Install PEAR mail and mail_mimeDecode classes

I recommend you install both of them!

Now, if the classes are installed let’s get dirty and start coding!

Include the class

require_once 'Mail/mimeDecode.php';

Decode the email

$params['include_bodies'] = true;
$params['decode_bodies']  = true;
$params['decode_headers'] = true;

$decoder = new Mail_mimeDecode($email); // create a new instance of Mail_mimeDecode class
$structure = $decoder->decode($params);//decode using parameters
$xml = $decoder->getXML($structure);//get XML (optional)

You have to specify an array of parameters in order to decode the mail.
$params['include_bodies'] = true;
$params['decode_bodies']  = true;
$params['decode_headers'] = true;
Set to `true` the sections you would like to decode!

The decoded e-mail will be contained by the $structure variable. Optionally you can create an XML too that will contain the decoded data, but I don’t recommend it. If you will have binary attachments you will have problems parsing the XML (XML parsing classes are waiting for UTF-8 data and binary files contain unicode).

To ease your work I attached a file with the structure of the $structure object.
Download

I will post a few examples of how to parse the object!

Get the subject

$structure->headers["subject"];

Get html text, plain text and attachments

$plain = "";
$html = "";
$attachments = null;
$i=0;
foreach ($structure->parts as $part) {
if (isset($part->disposition) && $part->disposition=='attachment')
{
$i++;
$attachments[$i]['body'] = $part->body;
$attachments[$i]['name'] =$part->ctype_parameters['name'];
}
else
{
if( isset($part->parts) && count($part->parts)>0)
{
foreach($part->parts as $sp)
{
if(strpos($sp->headers['content-type'],'text/plain')!==false)
$plain = $sp->body;
if(strpos($sp->headers['content-type'],'text/html')!==false)
$html = $sp->body;
}
}
else
{
if(strpos($part->headers['content-type'],'text/plain')!==false)
$plain = $part->body;
if(strpos($part->headers['content-type'],'text/html')!==false)
$html = $part->body;
}
}
}
if(trim($plain)=='' && isset($structure->body)) $plain = $structure->body;
if(trim($html)=='')$html = nl2br($plain);
if(trim($html)=='')$html = "---The body of this message is empty---";

This is the trickiest part!
I parsed the `parts` array to check for the type of content. If the `part` has a member called disposition with the value ‘attachment’ then this part is an attachment else it is an html or a text body (the body of the email).

If we have an email with attachments the `parts` array has `part` called members, else it has only text and html body `parts`and it has directly `headers` and `body` children.

If the e-mail is sent in a simple text format then the text will be saved in $structure->body, this is what are for the last 3 lines.

Extracting texts and attachments is the hardest part of all, the rest you can extract from $structure->headers.