Solved

write both the subject and the body of piped email

Posted on 2013-01-11
19
353 Views
Last Modified: 2013-01-17
<?php // RAY_temp_rgb192.php
error_reporting(E_ALL);
date_default_timezone_set('America/Chicago');


// THIS IS THE SORT OF THING THAT MIGHT BE FOUND BY THE EMAIL PIPE
$email = <<<ENDEMAIL
MIME-Version: 1.0
Received: by 10.217.5.194 with HTTP; Tue, 23 Oct 2012 07:02:46 -0700 (PDT)
Date: Tue, 23 Oct 2012 10:02:46 -0400
Delivered-To: ray.paseur@gmail.com
Message-ID: <CALik7L8mmDoneUaWdO+Or1MJFFDQ27YJtEd7Gx_hut9Th_dSww@mail.gmail.com>
Subject: A Sample Message
From: Ray <ray.paseur@gmail.com>
To: Ray <ray.paseur@gmail.com>
Content-Type: text/plain; charset=ISO-8859-1

Hello World
ENDEMAIL;


// A REGULAR EXPRESSION TO FIND THE FROM-EMAIL ADDRESS
$regex
= '#'         //REGEX DELIMITER
. 'From:'     // LITERAL STRING
. '.*?'       // ANYTHING OR NOTHING
. '\<'        // ESCAPED WICKET
. '(.*?)'     // GROUP OF CHARACTERS WITH EMAIL ADDRESS
. '\>'        // ESCAPED WICKET
. '#'         // REGEX DELIMITER
;

// A DATE PATTERN THAT WILL CREATE ISO-8601 FORMAT
$datep = 'Y_m_d_H_i_s_';

// ISOLATE THE FROM EMAIL ADDRESS
$from = preg_match($regex, $email, $matches);

// REMOVE DOTS
$from = str_replace('.', '_', $matches[1]);

// REMOVE @-SIGN
$from = str_replace('@', '_AT_', $from);

// PREFIX DATETIME AND SUFFIX FILE TYPE
$file = date($datep) . $from . '.txt';

// WRITE THE FILE
file_put_contents($file, $email);
echo "FILE: <b>$file</b> WRITTEN";

Open in new window



email pipe
want to know the subject and the body

subject would be
Subject: A Sample Message
\(*)\space : (*)

but body is not
body: sample body
0
Comment
Question by:rgb192
  • 11
  • 6
  • 2
19 Comments
 
LVL 77

Expert Comment

by:arnold
ID: 38770504
A single empty line (zero length) separates the body from the header of the message.
A line by line search for subject, from would

@emailarray=split(/\r*\n/,$email);
$body=0;
$messagebody='';

foreach $line (@emailarray) {
If ( $body <> 1 ) {
      $messagebody .="$line\n";
}
elseif ( $line =~ /^(From|Subject):(.*)$/i ) {
           $headers{$1}=$2;
}
elseif (length($line)<1 ) {
           $body=1;
}

}

$headers{'From'} will have the from info
Similarly for Subject.

$messagebody will contain th entire message body including any attachments.

If you are passing the data via pipe, yo would replace the foreach with a while <stdin> and line variable would either need to replaced with $_ or assign $_ to $line.

There are modules that help if needed.
0
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 38770555
The comment on line 33 no longer applies to the date pattern code on line 34.

Here is what I would do.  First, I would not assume that what you have here is actually a valid representation of an incoming email message.  To test, I would set up the email PIPE and send it several email messages.  Send from GMail, Outlook, Hotmail, etc., so you have a representative collection of messages written to files on your server.  Then read those files and look for the common and different patterns.  You may find that the body is separated from the headers by a "blank" line or you may not.  You may find other blank lines in the headers or you may not.  There really are no standards in email, so you would want to prepare the widest possible set of test cases and let those guide your research and the resulting programming.
0
 
LVL 77

Expert Comment

by:arnold
ID: 38770766
RFC822, 2821 define email formatting.

If you see an occurrence to which ray_pasteur referenced, this means there is an errand/noncompliant email client or the message was generated as spam/virus.  You can try to make adjustments to compensate for this other non-compliant email.

http://php.net/manual/en/ref.mailparse.php
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 

Author Comment

by:rgb192
ID: 38770878
<?php // RAY_temp_rgb192.php
error_reporting(E_ALL);
date_default_timezone_set('America/Chicago');


// THIS IS THE SORT OF THING THAT MIGHT BE FOUND BY THE EMAIL PIPE
$email = <<<ENDEMAIL
MIME-Version: 1.0
Received: by 10.217.5.194 with HTTP; Tue, 23 Oct 2012 07:02:46 -0700 (PDT)
Date: Tue, 23 Oct 2012 10:02:46 -0400
Delivered-To: ray.paseur@gmail.com
Message-ID: <CALik7L8mmDoneUaWdO+Or1MJFFDQ27YJtEd7Gx_hut9Th_dSww@mail.gmail.com>
Subject: A Sample Message
From: Ray <ray.paseur@gmail.com>
To: Ray <ray.paseur@gmail.com>
Content-Type: text/plain; charset=ISO-8859-1

Hello World
ENDEMAIL;


// A REGULAR EXPRESSION TO FIND THE FROM-EMAIL ADDRESS
$regex
= '#'         //REGEX DELIMITER
. 'From:'     // LITERAL STRING
. '.*?'       // ANYTHING OR NOTHING
. '\<'        // ESCAPED WICKET
. '(.*?)'     // GROUP OF CHARACTERS WITH EMAIL ADDRESS
. '\>'        // ESCAPED WICKET
. '#'         // REGEX DELIMITER
;

// A DATE PATTERN THAT WILL CREATE ISO-8601 FORMAT
$datep = 'Y_m_d_H_i_s_';

// ISOLATE THE FROM EMAIL ADDRESS
$from = preg_match($regex, $email, $matches);

// REMOVE DOTS
$from = str_replace('.', '_', $matches[1]);

// REMOVE @-SIGN
$from = str_replace('@', '_AT_', $from);

// PREFIX DATETIME AND SUFFIX FILE TYPE
$file = date($datep) . $from . '.txt';




@emailarray=split(/\r*\n/,$email);
$body=0;
$messagebody='';

foreach $line (@emailarray) {
If ( $body <> 1 ) {
      $messagebody .="$line\n";
}
else if ( $line =~ /^(From|Subject):(.*)$/i ) {
           $headers{$1}=$2;
}
else if (length($line)<1 ) {
           $body=1;
}

}











// WRITE THE FILE
file_put_contents($file, $email);
echo "FILE: <b>$file</b> WRITTEN";

Open in new window



line 51,60,62 have errors

I want to forward all my received email from gmail to the pipe email address (which gets parsed by this pipe script)
So would this make all the email in the same format (because it is gmail)
0
 
LVL 77

Expert Comment

by:arnold
ID: 38770920
You seem to be set on attempting to reprocess the data over and over and over and over depending on how many data points you would like to extract.  Using the mailparse to extract the data or use the read in nd process the input buffer one line at a time.  A better and simpler approach depending on your mail server and whether it is passing the incoming mail through an LDA dovcot, procmail. The from and the body can be extracted and presented to your php with the from and subject as arguments to your script and the body of the message as input on stdin.
0
 
LVL 77

Expert Comment

by:arnold
ID: 38770934
On the split error,you have to use "\r*\n" as the pattern.

Or try "\n" on which to split the line.

The hash assignment which is whatn 61 and 62 may have to be changed to an array
$headers[$1]=$2;
http://stackoverflow.com/questions/3134296/hash-tables-vs-associative-arrays-php
0
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 38770948
@arnold: I am complimented by your reference to me as ray_pasteur since that might imply a relationship to the great chemist!

@rgb192: Your success in this will be somewhat dependent on your patience and willingness to test many messages.  If your script reads from stdin here is a strategy that might be useful.

Set ob_start(), then set a counter to zero.  When your script reads a line from stdin, echo the counter and the line that was just read.  Increment the counter.  When your script detects EOF on stdin, use ob_get_clean() to capture the output buffer.  Use PHP mail() to send the output buffer to yourself.  Examine it carefully, looking for the nearly invisible \r\n character combinations.  

This is not really a question with any "answer" so much as a requirement for step-by-step programming and debugging.  We've done the best we can to equip you with the tools and process, so I'll sign off for now.  Best of luck with it, ~Ray
0
 
LVL 77

Expert Comment

by:arnold
ID: 38770987
IMHO,the testing for message data is unnecessary.  One should use the presumption that the formatting will be valid Per smtp/ESMTP.
0
 

Author Comment

by:rgb192
ID: 38771041
<?php // RAY_temp_rgb192.php
error_reporting(E_ALL);
date_default_timezone_set('America/Chicago');


// THIS IS THE SORT OF THING THAT MIGHT BE FOUND BY THE EMAIL PIPE
$email = <<<ENDEMAIL
MIME-Version: 1.0
Received: by 10.217.5.194 with HTTP; Tue, 23 Oct 2012 07:02:46 -0700 (PDT)
Date: Tue, 23 Oct 2012 10:02:46 -0400
Delivered-To: ray.paseur@gmail.com
Message-ID: <CALik7L8mmDoneUaWdO+Or1MJFFDQ27YJtEd7Gx_hut9Th_dSww@mail.gmail.com>
Subject: A Sample Message
From: Ray <ray.paseur@gmail.com>
To: Ray <ray.paseur@gmail.com>
Content-Type: text/plain; charset=ISO-8859-1

Hello World
ENDEMAIL;


// A REGULAR EXPRESSION TO FIND THE FROM-EMAIL ADDRESS
$regex
= '#'         //REGEX DELIMITER
. 'From:'     // LITERAL STRING
. '.*?'       // ANYTHING OR NOTHING
. '\<'        // ESCAPED WICKET
. '(.*?)'     // GROUP OF CHARACTERS WITH EMAIL ADDRESS
. '\>'        // ESCAPED WICKET
. '#'         // REGEX DELIMITER
;

// A DATE PATTERN THAT WILL CREATE ISO-8601 FORMAT
$datep = 'Y_m_d_H_i_s_';

// ISOLATE THE FROM EMAIL ADDRESS
$from = preg_match($regex, $email, $matches);

// REMOVE DOTS
$from = str_replace('.', '_', $matches[1]);

// REMOVE @-SIGN
$from = str_replace('@', '_AT_', $from);

// PREFIX DATETIME AND SUFFIX FILE TYPE
$file = date($datep) . $from . '.txt';




@emailarray=split("\n",$email);
$body=0;
$messagebody='';

foreach $line (@emailarray) {
If ( $body <> 1 ) {
      $messagebody .="$line\n";
}
else if ( $line =~ /^(From|Subject):(.*)$/i ) {
           $headers[$1]=$2;
}
else if (length($line)<1 ) {
           $body=1;
}

}











// WRITE THE FILE
file_put_contents($file, $email);
echo "FILE: <b>$file</b> WRITTEN";

Open in new window



line 51,60,62 have still have errors





and based upon a comment,  I have a related question

parse email with php (LDA dovcot, procmail)
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_27993541.html
0
 
LVL 77

Expert Comment

by:arnold
ID: 38771090
Sorry, strlen should be used instead of length on line 62.
51 might be an issue depending on the php version.
str_split.

Need to try to read data from stdin.
0
 
LVL 77

Expert Comment

by:arnold
ID: 38771095
You need to,provide setup info in your related question, mailserver and its current configuration.
0
 

Author Comment

by:rgb192
ID: 38771142
<?php // RAY_temp_rgb192.php
error_reporting(E_ALL);
date_default_timezone_set('America/Chicago');


// THIS IS THE SORT OF THING THAT MIGHT BE FOUND BY THE EMAIL PIPE
$email = <<<ENDEMAIL
MIME-Version: 1.0
Received: by 10.217.5.194 with HTTP; Tue, 23 Oct 2012 07:02:46 -0700 (PDT)
Date: Tue, 23 Oct 2012 10:02:46 -0400
Delivered-To: ray.paseur@gmail.com
Message-ID: <CALik7L8mmDoneUaWdO+Or1MJFFDQ27YJtEd7Gx_hut9Th_dSww@mail.gmail.com>
Subject: A Sample Message
From: Ray <ray.paseur@gmail.com>
To: Ray <ray.paseur@gmail.com>
Content-Type: text/plain; charset=ISO-8859-1

Hello World
ENDEMAIL;


// A REGULAR EXPRESSION TO FIND THE FROM-EMAIL ADDRESS
$regex
= '#'         //REGEX DELIMITER
. 'From:'     // LITERAL STRING
. '.*?'       // ANYTHING OR NOTHING
. '\<'        // ESCAPED WICKET
. '(.*?)'     // GROUP OF CHARACTERS WITH EMAIL ADDRESS
. '\>'        // ESCAPED WICKET
. '#'         // REGEX DELIMITER
;

// A DATE PATTERN THAT WILL CREATE ISO-8601 FORMAT
$datep = 'Y_m_d_H_i_s_';

// ISOLATE THE FROM EMAIL ADDRESS
$from = preg_match($regex, $email, $matches);

// REMOVE DOTS
$from = str_replace('.', '_', $matches[1]);

// REMOVE @-SIGN
$from = str_replace('@', '_AT_', $from);

// PREFIX DATETIME AND SUFFIX FILE TYPE
$file = date($datep) . $from . '.txt';




@emailarray=str_split("\n",$email);
$body=0;
$messagebody='';

foreach $line (@emailarray) {
If ( $body <> 1 ) {
      $messagebody .="$line\n";
}
else if ( $line =~ /^(From|Subject):(.*)$/i ) {
           $headers[$1]=$2;
}
else if (strlen($line)<1 ) {
           $body=1;
}

}











// WRITE THE FILE
file_put_contents($file, $email);
echo "FILE: <b>$file</b> WRITTEN";

Open in new window


line 51,60,62
still same error in my code editor for
PHP Version 5.2.17
0
 
LVL 77

Expert Comment

by:arnold
ID: 38771160
Run php -l <yourphp script>
0
 
LVL 77

Expert Comment

by:arnold
ID: 38771206
What is the goal of your setup?
Are you planning having this data added into a mysql database or something similar?
0
 

Author Comment

by:rgb192
ID: 38772043
>>Run php -l <yourphp script>
I am using hostgator shared and I cant do command line


>>What is the goal of your setup?
Are you planning having this data added into a mysql database or something similar?

store subject and body in mysql
0
 
LVL 77

Accepted Solution

by:
arnold earned 500 total points
ID: 38772178
You might want to reconsider whether PHP which is geared more to a web based application.
An equivalent resource would be to use a perl script.

The same process outlined earlier.
The example below deals with getting the email message passed on the command line
cat email_message | processemail.pl

#!/usr/bin/perl

use strict;
my %header; # hash of header entries from, subject, body.
my $body=0;# marker to detect beginning of message body.
#begin loop of reading data on standard input

while (<STDIN>) { # each line is assigned to $_
chomp(); #strip crlf if present
if ( $body==1 ) {
           $header{'body'}.="$_\n";
}
elsif ( /^(From|Subject): (.*)$/i ) {
             $header{lc($1)}=$2; # all reference to from and subject hashed reference will be lower case
}
elsif (length($_) <1 ) {
             $body=1;
}

}# close while loop

#the below is just to show the data
foreach $key (keys %header) {
           print "$key: $header{$key}\n------------------------------\n";
}

Open in new window


To incorporated the mysql connection is fairly simple
Look at DBI and DBD::Mysql modules.
0
 

Author Comment

by:rgb192
ID: 38773181
i dont know perl well enough

and I think my hosting only allows php
0
 
LVL 77

Expert Comment

by:arnold
ID: 38773337
Within the shell which is where the script will run, perl is often ubiquitous. Php is built on several used languages including perl.

Hashes %variablename in perl is not included in PHP.

Depending on the mailserver and how the email is handled routed within the hosted platform is something you have to determine what you will use.

The process is straight forward, a text is being passed on standard input.  You o line by line looking for the entry you want until an single empty line which separates the header portion from the body of the message.

Do you have shell access from this hosting provider?
0
 

Author Closing Comment

by:rgb192
ID: 38788305
even though this answer is not in php
I think perl would solve the problem

thank you
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Things That Drive Us Nuts Have you noticed the use of the reCaptcha feature at EE and other web sites?  It wants you to read and retype something that looks like this.Insanity!  It's not EE's fault - that's just the way reCaptcha works.  But it is …
3 proven steps to speed up Magento powered sites. The article focus is on optimizing time to first byte (TTFB), full page caching and configuring server for optimal performance.
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to count occurrences of each item in an array.

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question