[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 362
  • Last Modified:

write both the subject and the body of piped email

<?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
rgb192
Asked:
rgb192
  • 11
  • 6
  • 2
1 Solution
 
arnoldCommented:
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
 
Ray PaseurCommented:
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
 
arnoldCommented:
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
rgb192Author Commented:
<?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
 
arnoldCommented:
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
 
arnoldCommented:
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
 
Ray PaseurCommented:
@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
 
arnoldCommented:
IMHO,the testing for message data is unnecessary.  One should use the presumption that the formatting will be valid Per smtp/ESMTP.
0
 
rgb192Author Commented:
<?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
 
arnoldCommented:
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
 
arnoldCommented:
You need to,provide setup info in your related question, mailserver and its current configuration.
0
 
rgb192Author Commented:
<?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
 
arnoldCommented:
Run php -l <yourphp script>
0
 
arnoldCommented:
What is the goal of your setup?
Are you planning having this data added into a mysql database or something similar?
0
 
rgb192Author Commented:
>>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
 
arnoldCommented:
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
 
rgb192Author Commented:
i dont know perl well enough

and I think my hosting only allows php
0
 
arnoldCommented:
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
 
rgb192Author Commented:
even though this answer is not in php
I think perl would solve the problem

thank you
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 11
  • 6
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now