PHP: Parse emails with email piping – Part 1

Email piping is a really useful trick if you want to parse emails sent to you with PHP. I’ve used it a few times now for a support ticket system I built as well as to detect bounce emails from a mailing list and remove invalid emails from the list.

The first thing we need to do is set up an email account. For this example, the mail server I’m using is qmail and my email account is qmail email accounts have a .qmail file associated with each email account that tells the mail server what to do with an email that is sent to that account. This file is usually located at /var/qmail/mailnames/domain_name/email_username/.qmail. Depending on your mail server, the file you need to edit may differ so check with the manual of your mail server.

SSH into your web server and change to this directory where domain_name is your domain and email_username is the name of the email account you made (make sure your user has sufficient privileges to do this. may need root access).

Open up the .qmail file

[pre lang="UNIX"]
> vim .qmail

By default it will have this in it

[pre lang="text"]
| true

This tells qmail to put any incoming email into the Inbox.

Now, on a new line, add in the full absolute path to where your PHP script is.
[pre lang="text"]
| /home/user/script_dir/email_process.php
to get:

[pre lang="text"]
| true
| /home/user/script_dir/email_process.php

This tells the mail server to put an incoming email in the Inbox as well as to send it to our PHP script. Save the file and reboot your mail server to make the changes live.

[pre lang="UNIX"]
/etc/init.d/qmail restart

Now for our PHP script. When the mail server sends the email to our script, because this script is not being executed by our web server, we need to tell it where the PHP engine is so it knows how to process our script. This is similar to a shell or perl script you would run directly on your server.

This is the first line we need in our script:
[pre lang="PHP"]
This is usually the default location of the PHP engine.

Now lets get PHP to read in the email:
[pre lang="PHP"]
// read in email from stdin
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd)) {
$email .= fread($fd, 1024);

//send us the email to make sure it worked
mail('','someone sent us an email at',"Here is the the full email:\n\n$email");

So this is it. Pretty simple.

Now if I send an email to, I should get an email at with a full copy of the email in the body (including headers).

A couple notes:

  1. Each mail server is different. The line we added to the .qmail file is usually the same but the name of the file and location may be different
  2. Check with your hosting provider if you’re having any troubles.
  3. Make sure the PHP script is executable
  4. Make sure this is at the top of the file: #!/usr/bin/php
  5. For testing purposes I usually leave in the .qmail config line to deliver a copy of the email to the Inbox. In production I would remove this as I usually do not want to check the Inbox on this account because I don’t want unnecessary emails building up in the Inbox and taking up disk space.

Stay tuned for part 2 where I will show you how to break the email down and get all the details of it (To, From, Subject, Body, etc). Update: Part 2 is now posted: "PHP: Parse emails with email piping – Part 2"

Continue Reading

  • No Related Posts
  • Clean Web Design

    I’m looking forward to part 2! :-)

  • Skye

    Part 2 is now up. Sorry for the delays.

  • Adi

    Interesting, i am doing something similar. What I wanted to know is how are you deleting emails after reading them in your PHP script? Because unless they are deleted from email directory they will start to occupy to much hard disk.

    Am I not right?

    • Skye

      Yes you are correct. If you look at note #5, I like to have the emailed delivered to the inbox when I’m testing just so if I have problems with the piping script I know there is nothing wrong with the mail server as the Inbox received a copy of the email. Once I am confident that the script works and it moves into production, I will remove the top 2 lines from the .qmail file (| true and ./Maildir/). This will stop a copy of the email getting delivered to the Inbox so you don’t have to keep checking the Inbox and cleaning it out.

  • Ben


    for some reason i keep getting the subject in UTF-8

    what can i do to avoid that?

    Great article by the way!

  • Skye

    I think I get that sometimes too. I haven’t had time to look into it though. It’s likely to do with UTF8 encoding. Did you look into the $decoded array and see exactly what’s in the subject section?

    If you can, send me the entire email through the Contact link at the top and I will take a look into it.

  • Stove

    I spent hours chasing down a few problems with getting this working. Here is what I found. In my case SELinux was not allowing php to sendmail. So I temporarly disabled SELinux until I learn how to adjust its permission. Also, by default postfix doesn’t allow pipe so I changed postfix from allow_mail_to_commands = alias, forward to allow_mail_to_commands = alias, forward, include and allow_mail_to_files = alias, forward to allow_mail_to_files = alias, forward, include. Hope this helps others.

  • Real

    Just great ! Exactly what I was looking to do. Thanks to all of you.

    By trying toput it together I had problem getting the PHP script working with the email piping ptocess. I had spent two days looking, trying all these suitable #! commands and non whitespace to find out that a text file from a windows environment and a text file for Unix is not compatible (Sorry but I did’nt know). One of the uncompatibility is the End of line. EOL so critical to the #! line of the PHP script. Once converted, my PHP script worked like a charm just like stated in this forum.

    I want to share the different links for getting more information and tools to do so. If like me you are using Window to do development and using a Host for Web Site with Cpanel and Unix. You probably need to do so if you want to do mail piping and parsing.

    The post that made my day (beside the present one) is:

    When running my email piping parsing PHP script from Cron , the message I had was:

    ” A message that you sent could not be delivered to one or more recipients. This is a permanent error. The following(s) address(es)failed:”

    Using using GEDIT (freeware) a have “converted” my PHP script file to Unix type End Of line

    GEDIT Windows version link:

    Hope that will help some other fellows loosing their time troubleshooting the invisible.