Pipe Email To PHP And Parse Content


 Pipe Email To PHP And Parse Content  
 

Did you ever think how an email group works, on behind the screen? You send an email to an email address(a unique email address dedicated to an email group), then it is being saved and show on the email group’s web page, and also sent out to all email addresses who are member of this group. So, basically, you will need to process the email contents to save them to db, publish on webpage and send email to others.

How PHP Email Piping Works:

On this tutorial, I will try to demonstrate the main part of similar application as follows, how you can send an email’s content/information to a php handler on Linux server and how we can parse the email contents into necessary parts like sender/subject/content etc. So, in this pipe email to php tutorial, we are going to do the following two tasks briefly:

  • Forward an email to a php script.
  • Retrieve the necessary contents by php.

Forward an email to a php script:

This part is pretty straight way and doesn’t involve any coding. However, your hosting may or may not support this feature, so make sure first and contact support if not supported to know whether any way to do so(may be by upgrading the hosting package,etc).

Firstly, login to your hosting cpanel(Screenshot here are from host-gator).
Hostgator Cpanel Email Section
Then, find the mail section where you should see one option named ‘Forwarder’ or similar. Enter to this section. And then click on the ‘Add forwarder’ button.
Adding Email Forwarder
This section provides you option to do several actions whenever an email reaches to an address it handles. We will be using the “Pipe to a program” option, which is the only option to forward it to a php script (Just to mention, you can use other languages too, not necessarily php, as long as that language is supported in your server). On this option, you will have to enter the path to the php handler file. Here carefully remember three things:

  • If you enter the php script’s url here, it won’t work, you have to provide the local path location.(like “public_html/handlers/email_handler.php” or something like it).
  • You should specify the php compiler path(like “/usr/bin/php”) at the beginning.
  • You must need to make sure that the handler file has ‘execute’ permission, otherwise this command won’t be executed at all.

So basically, your command string here will be like a terminal command. One example is as follows:

/usr/local/bin/php -q /home/yourdomain/public_html/handlers/mail_to_group.php 

Retrieve necessary contents from email by php:

First, we need to get the contents. To do so, on your handler php file, please add the following directive at the very top of the page(it may vary for you, refer to the previous section, need the path of php compiler correctly):

#!/usr/local/bin/php -q

This won’t be under php tag at all, will be outside. php tag should start after it.

Now, the following code snippet will retrieve the full content received:

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

After the execution of above code snippet, we will receive the full content in the “$email_content” variable.

Ok, so as we are now ready to get the contents from email, we can move ahead to parse it as you will receive the contents in some wired manner, not every piece differently. Wanna see how it look like? Here is an example :) :

Return-path: <senderemail@domain.com>
Received: from mail-wy0-f179.google.com ([74.125.82.179]:53218)
       by gator526.hostgator.com with esmtps (TLSv1:RC4-SHA:128)
       (Exim 4.69)
       (envelope-from <senderemail@domain.com>)
       id 1Qetnx-00061q-E5
       for recieveremail@domain.org; Thu, 07 Jul 2011 14:00:05 -0500
Received: by wyh21 with SMTP id 21so939158wyh.38
       for <recieveremail@domain.org>; Thu, 07 Jul 2011 12:00:06 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
       d=gmail.com; s=gamma;
       h=mime-version:date:message-id:subject:from:to:content-type;
       bh=aVvn1hmmUfdWAswRt69lpHB1V8XJtvcueoBNWIIKkV8=;
       b=o1jHeVKd8ollKyXuUlTpCG+DIS8eY1qoueyTaSYTyEqIFgiynuoX1NXTKzT9+l8SU/
        LCqUoNYxofOtjNhkhJ7wS5mOQvoZVEnMyONTwRrx024PJE4/Do5VLltwNjPRzqMrFPux
        otJCyqSddue/SGlTPxbBXiFsD7Gzl3TcTTdz8=
MIME-Version: 1.0
Received: by 10.216.237.131 with SMTP id y3mr7444080weq.87.1310065206713; Thu,
 07 Jul 2011 12:00:06 -0700 (PDT)
Received: by 10.216.237.170 with HTTP; Thu, 7 Jul 2011 12:00:06 -0700 (PDT)
Date: Fri, 8 Jul 2011 01:00:06 +0600
Message-ID: <CAAxg_qAWbasvps0Q-2FAjXZ73zWzMErztqp5U_aUYUTCsxP6LQ@mail.domain.com>
Subject: [Demo - Test Group] Test topic 6
From: "Sender Full Name" <senderemail@domain.com>
To: Email Group <recieveremail@domain.org>
Content-Type: multipart/alternative; boundary=0015175cfc46475cbc04a77f53d6

--0015175cfc46475cbc04a77f53d6
Content-Type: text/plain; charset=ISO-8859-1

another new test topic.
--
Regards

Rana

--0015175cfc46475cbc04a77f53d6
Content-Type: text/html; charset=ISO-8859-1

<br clear="all">another new test topic.<br>-- <br>Regards<br><br>Rana<br>

--0015175cfc46475cbc04a77f53d6--

So, how is it? Do you like it? Hope not, I didn’t like it at all :D. So, what we need now, is to parse it. Well, though you can do it yourself by spending some time, but here is some ready-made code that you can reuse all the times. Here we go:

//split the string into array of strings, each of the string represents a single line, received
$lines = explode("\n", $email_content);

// initialize variable which will assigned later on
$from = "";
$subject = "";
$headers = "";
$message = "";
$is_header= true;

//loop through each line
for ($i=0; $i < count($lines); $i++) {
if ($is_header) {
// hear information. instead of main message body, all other information are here.
$headers .= $lines[$i]."\n";

// Split out the subject portion
if (preg_match("/^Subject: (.*)/", $lines[$i], $matches)) {
$subject = $matches[1];
}
//Split out the sender information portion
if (preg_match("/^From: (.*)/", $lines[$i], $matches)) {
$from = $matches[1];
}
} else {
// content/main message body information
$message .= $lines[$i]."\n";
}
if (trim($lines[$i])=="") {
// empty line, header section has ended
$is_header = false;
}
}

So, after this, at the end, you should get from, to, subject, message information in their corresponding variables.

Final Words:

Remember, your message body structure will may differ a bit from one email client to another. So, you will have to take care of the client you are using. If you want to support most of the clients(yahoo/google/hotmail), you may have to apply several parsing rule on the message to get text and/or html version.

To debug how its working, you can’t do on browser as the contents will go from email, so you should use logging on an external text files and write log about each step, errors to get full details.

Hopefully, this pipe email to php tutorial will help you understand how the process works. That is just the basic parts(most important though :) ) in the way to build an email group. Let me hear if you have any question. Happy coding :)

Comments

  1. Stewart says

    Very good, thanks.

    I added an insert statement to drop the data from the email message including email address etc into a MySQL DB – but I get a bunch of unwanted stuff in the database appearing in the ‘message’ column which looks like headers of the email like this:

    “This is a multi-part message in MIME format.

    ——=_NextPart_000_0101_01CEAA6E.6A79E160
    Content-Type: text/plain;
    charset=”iso-8859-1″
    Content-Transfer-Encoding: quoted-printable

    I also see quotes appearing in the other columns – how to get rid of any unwanted characters?

    • says

      You will need to filter them with regular expression as far I can suggest. Don’t see any other way around atm, email contents usually do have such lots of unnecessary characters for formatting probably, which differs from client to client(yahoo/gmail/outlook etc).

  2. alby says

    I have my text in spanish but when I answer the mail with outlook, I get unwanted characters where I use spanish accents á ú í é ó and in the line breack I get =20, can you give me a hint on how can I replace this charaters with the vocals and with the accent again ?
    thanks for your help

  3. says

    Hello! I know this post is a little bit cold… but I wonder if you might help? I have implemented this code, and it works with one exception… each time a mail is successfully parsed i get 7 mails.

    The processing i have programmed is supposed to identify the subject, and then add that as the body of a mail to my office email address.

    only I get 7 identical emails!

    Any thoughts or direction would be much appreciated!

    cheers
    LAex

Trackbacks

Leave a Reply