Solved

write both the subject and the body of piped email

Posted on 2013-01-11
19
349 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 76

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 108

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 76

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
 

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 76

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 76

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 108

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 76

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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 76

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 76

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 76

Expert Comment

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

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 76

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 76

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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Foreword (July, 2015) Since I first wrote this article, years ago, a great many more people have begun using the internet.  They are coming online from every part of the globe, learning, reading, shopping and spending money at an ever-increasing ra…
Password hashing is better than message digests or encryption, and you should be using it instead of message digests or encryption.  Find out why and how in this article, which supplements the original article on PHP Client Registration, Login, Logo…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

747 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now