how to extract full mail address in imap php - php

i use the below code to extract header details from the mail.. i could not get the mail address in from, to and cc as mentioned below..
$header = explode("\n", imap_fetchheader($mbox,$msgno));
echo "<br>";
for ($i=1; $i<count($header); $i++)
{
echo $header[$i] . "<br>";
}
output:
Delivered-To: user1#examplecom
X-WM-Delivered: user1#example.com
Received: from ElcotPC ([127.0.0.1])
(envelope-sender )
by 127.0.0.1 with ESMTP
for ; Wed, 31 Jul 2013 09:14:19 +0530
From: "user1"
To:
Cc:
Subject: testing with attachment
Date: Wed, 31 Jul 2013 09:14:18 +0530
The "from","to", "cc" field are empty without the mail address..
i want the output like this..
Delivered-To: user1#examplecom
X-WM-Delivered: user1#example.com
Received: from ElcotPC ([127.0.0.1])
(envelope-sender )
by 127.0.0.1 with ESMTP
for ; Wed, 31 Jul 2013 09:14:19 +0530
From: "user1" <user1#example.com>
To: <user2#example.com>
Cc: <user1#example.com>
how to get the email address to "from", "to" and "cc" field?

Update:
It's always best to use code that is readily available, so I checked if a imap-parsing function exists already. It does: imap_rfc822_parse_headers. Read the docs for details, and links to all sorts of imap_* functions. Perhaps imap_rfc822_parse_adrlist is exactly what you need?
A basic preg_match_all call could do the job, I think:
if (preg_match_all('/^\s*(From|To|Cc):[^<]*<([^>]+)\>/m',$string, $addresses)
{
$addresses = array_merge($addresses[1], $addresses[2]);
print_r($addresses);
}
Should output:
array (
'From' => 'user1#example.com',
'To' => 'user2#example.com',
'Cc' => 'user1#example.com',
)
I think that's what you were looking for.
The regex explained:
^\s* matches the start of the line, and zero or more whitespace chars
(From|To|Cc) matches (and groups) From, To or Cc
:[^<]*<: Matches (but doesn't group) the colon, and any char, except for the address delimiting <
([^>]+): Mathces (and groups) everything after the <, that isn't >
\>: Can be left out, but matches address-delimiting >
m: multi-line. If left out the leading ^ means start of string, now it means start of line
Notes: This expression doesn't deal with comma separated addresses or multiple addresses, and it might be usefull to call:
filter_var($addresses['From'], FILTER_VALIDATE_EMAIL)
or use array_map to filter $addresses[2] prior to merging...

Related

file_get_contents() with newLine for Regex

I have a file called mail.txt with the following contents :
From: elvis#tabloid.org (The King)
Subject: be seein' ya around
Date: Mon, 23 Oct 2006 11:04:13
From: The Prez <president#whitehouse.gov>
Date: Wed, 25 Oct 2006 8:36:24
Subject: now, about your vote
I'm using Sublime Text in which the Regex ^\w+: works properly.
I'm using file_get_contents() to read the content from mail.txt and then use the same Regex for preg_replace() to highlight the output.
The issue is, when I use file_get_contents(), it doesn't consider \n and for that I tried nl2br(), but that didn't work either.
Below are the outputs in Sublime and PHP :
Sublime
PHP
Below is the PHP code :
<?php
$path = "./mail.txt";
if(!file_exists($path))
die("File does not exist");
else {
if(!($handle = fopen($path, "r")))
die("File could not be opened");
else {
$file_data = file_get_contents($path);
}
}
$mod_file = preg_replace("/^\w+:/", "<span class='replaced'>$0</span>", $file_data);
echo "<pre>".$mod_file."</pre>";
?>
How to solve this issue?
You need to use m or Multiline flag.See demo.
https://regex101.com/r/cT0hV4/12
$re = "/^\\w+:/m";
$str = "From: elvis#tabloid.org (The King)\nSubject: be seein' ya around\nDate: Mon, 23 Oct 2006 11:04:13\nFrom: The Prez <president#whitehouse.gov>\nDate: Wed, 25 Oct 2006 8:36:24\nSubject: now, about your vote";
preg_match_all($re, $str, $matches);

Split PHP string from a specified word

I have this php string
$mystring ="Yes YEs I am answering! On Fri, Mar 21, 2014 at 2:49 PM, Ajey Charantimath wrote: > answer to this question > > -- >"
I want to split the string starting from "On Fri, Mar 21, 2014".How do I achieve this?
Note - the spilt condition can be general. i.e it can also be 'On Sat, Mar 22' or 'On Wed, Mar 29' etc
Also mention which php function should I use?
Because it would not work very good if you just split at the "On" word (could also exist in the text before, which I assume may be different), I suggest the following possibility:
$str = "Yes YEs I am answering! On Fri, Mar 21, 2014 at 2:49 PM, Ajey Charantimath wrote: > answer to this question > > -- >";
if (preg_match('/^(.*)(On (Mon|Tue|Wed|Thu|Fri|Sat|Sun).*)$/', $str, $matches)) {
print_r($matches);
}
This gives you an output like the following, which should include all necessary values. Feel free to add an "i" after the second slash in the preg_match regex for case insensitive.
Array
(
[0] => Yes YEs I am answering! On Fri, Mar 21, 2014 at 2:49 PM, Ajey Charantimath wrote: > answer to this question > > -- >
[1] => Yes YEs I am answering!
[2] => On Fri, Mar 21, 2014 at 2:49 PM, Ajey Charantimath wrote: > answer to this question > > -- >
[3] => Fri
)
I would suggest a regex in order to do this, dieBeiden basically has it, though I would modify his regex a bit:
^(.*)(On (Mon|Tue|Wed|Thu|Fri|Sat|Sun), \w{3} \d{2}.*)$
$arr = explode('Yes YEs I am answering! ', $string);
It will find that word, delete it, and split on that place array!
And then you get
On Fri, Mar 21, 2014 at 2:49 PM, Ajey Charantimath wrote: > answer to this question > > -- >"
next explode on ','
$arr = explde(',',$arr);
$strings = $arr[0].','.$arr[1];
Check this,this example I did found
<?php
$whois = "Record last updated on 10-Apr-2011.Record expires on 08-Oct-2012.Record Expires on 08-Oct-2008.";
$expires = preg_split('/Expires|expires/', $whois);
array_shift($expires);
echo "<pre>";
print_r($expires);
?>
gives
Array
(
[0] => on 08-Oct-2012.Record
[1] => on 08-Oct-2008.
)
You can also this
http://board.phpbuilder.com/showthread.php?10384775-RESOLVED-Split-String-at-first-word-match
you can use exploade function
http://in2.php.net/explode
Try with explode() like
$tempArr1 = explode('!' , $mystring);
$tempArr2 = explode(',' , $tempArr1);
echo $tempArr2[0].', '.$tempArr[1].', '.$tempArr[2];
If the initial part the string is ALWAYS "Yes YEs I am answering! " you can delete the first 24 characters from the string with the function
$mystring2 = substr($mystring, 24);
Also take a look at the explode() function ;)
You could us the explode function for this (http://nl1.php.net/explode) and split it on the word 'On', but when 'On' also occurs in the string, you're in trouble.
A better idea would be to use a regular expression with preg_split (http://www.php.net/manual/en/function.preg-split.php), with something like this:
<?php
$mystring ="Yes YEs I am answering! On Fri, Mar 21, 2014 at 2:49 PM, Ajey Charantimath wrote: > answer to this question > > -- >";
$splitted = preg_split('/On ..., ... [0-9]{2}, [0-9]{4} at [0-9]:[0-9]{2} (AM|PM)/', $mystring);
var_dump($splitted);
?>
Feel free to make the regular expression more sophisticated :)
If you want to retain the datetime substring, then you can consume the leading space, then lookahead for as much of the datetime substring as you like.
Code: (Demo)
$mystring ="Yes YEs I am answering! On Fri, Mar 21, 2014 at 2:49 PM, Ajey Charantimath wrote: > answer to this question > > -- >";
var_export(
preg_split('/ (?=On (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun))/', $mystring)
);
Output:
array (
0 => 'Yes YEs I am answering!',
1 => 'On Fri, Mar 21, 2014 at 2:49 PM, Ajey Charantimath wrote: > answer to this question > > -- >',
)

Regular expression not working

I´m trying to get the email from and cc from a forwarded email, when the body looks like this:
$body = '-------
Begin forwarded message:
From: Sarah Johnson <blabla#gmail.com>
Subject: email subject
Date: February 22, 2013 3:48:12 AM
To: Email Recipient <thatwouldbe#yayyy.com>
Cc: Ralph Johnson <johnson#gmail.com>
Hi,
hello, thank you and goodbye!
blabla#gmail.com'
Now, when I do the following:
$body = strtolower($body);
$pattern = '#from: \D*\S([\w-\.]+)#((?:[\w]+\.)+)([a-zA-Z]{2,4})\S#';
if (preg_match($pattern, $body, $arr_matches)) {
echo htmlentities($arr_matches[0]);
die();
}
I correctly get:
from: sarah johnson <blabla#gmail.com>
Now, why does the cc don't work? I do something very similar, only changing from to cc:
$body = strtolower($body);
$pattern = '#cc: \D*\S([\w-\.]+)#((?:[\w]+\.)+)([a-zA-Z]{2,4})\S#';
if (preg_match($pattern, $body, $arr_matches)) {
echo htmlentities($arr_matches[0]);
die();
}
and I get:
cc: ralph johnson <johnson#gmail.com> hi, hello, thank you and goodbye! blabla#gmail.com
If I remove the email from the original body footer (removing blabla#gmail.com) then I correctly get:
cc: ralph johnson <johnson#gmail.com>
It looks like that email is affecting the regular expression. But how, and why doesn't it affect it in the from? How can I fix this?
The problem is, that \D* matches too much, i.e. it is also matching newline characters. I would be more restrictive here. Why do you use \D(not a Digit) at all?
With e.g. [^#]* it is working
cc: [^#]*\S([\w-\.]+)#((?:[\w]+\.)+)([a-zA-Z]{2,4})\S
See it here on Regexr.
This way, you are sure that this first part is not matching beyond the email address.
This \D is also the reason, it is working for the first, the "From" case. There are digits in the "Date" row, therefore it does not match over this row.
Try like this
$body = '-------
Begin forwarded message:
From: Sarah Johnson <blabla#gmail.com>
Subject: email subject
Date: February 22, 2013 3:48:12 AM
To: Email Recipient <thatwouldbe#yayyy.com>
Cc: Ralph Johnson <johnson#gmail.com>
Hi,
hello, thank you and goodbye!
blabla#gmail.com';
$pattern = '#(?:from|Cc):\s+[^<>]+<([^#]+#[^>\s]+)>#is';
preg_match_all($pattern, $body, $arr_matches);
echo '<pre>' . htmlspecialchars(print_r($arr_matches, 1)) . '</pre>';
Output
Array
(
[0] => Array
(
[0] => From: Sarah Johnson <blabla#gmail.com>
[1] => Cc: Ralph Johnson <johnson#gmail.com>
)
[1] => Array
(
[0] => blabla#gmail.com
[1] => johnson#gmail.com
)
)
$arr_matches[1][0] - "From" email
$arr_matches[1][1] - "Cc" email

Issue with 'From' header when sending SMS via PHP mail() function

I'm using PHP's mail() function to send SMS messages. It works fine, except that the message shows as coming from 'myuser#mr2.websitewelcome.com' when I want it to show as 'test#mydomain.com'. Here's the relevant code:
//Set headers and send mail.
$headers = "From: " . "test#mydomain.com" . "\r\n";
$headers .= "Reply-To: ". "test#mydomain.com" . "\r\n";
mail( $from, '', $message, $headers );
I know this question has been asked before, but nothing has helped me so far. I've tried setting the header as '-f test#mydomain.com'. No luck.
Btw, if I send to an email address rather than a phone number, the headers work just fine.
Idk if this has anything to do with it, but my script gets called from an email forwarder that I set up in cpanel like:
Address Forward To
test#mydomain.com |/home/myuser/public_html/handler.php
Also, here are the full headers of an email send to an email address:
Return-Path: <itch3#mr2.websitewelcome.com>
Received: from gateway01.websitewelcome.com (gateway01.websitewelcome.com [67.18.65.19])
by mtain-mk01.r1000.mx.aol.com (Internet Inbound) with ESMTP id 1B28B3800008B
for <myemail#me.com>; Wed, 8 Feb 2012 20:25:56 -0500 (EST)
Received: by gateway01.websitewelcome.com (Postfix, from userid 5007)
id A69B35C21D4BD; Wed, 8 Feb 2012 19:25:55 -0600 (CST)
Received: from mr2.websitewelcome.com (mr2.websitewelcome.com [74.53.229.178])
by gateway01.websitewelcome.com (Postfix) with ESMTP id 9CBAF5C21D49D
for <myemail#me.com>; Wed, 8 Feb 2012 19:25:55 -0600 (CST)
Received: from itch3 by mr2.websitewelcome.com with local (Exim 4.69)
(envelope-from <itch3#mr2.websitewelcome.com>)
id 1RvIln-0003AQ-Cv
for myemail#me.com; Wed, 08 Feb 2012 19:25:55 -0600
To: myemail#me.com
Subject: subject
From: "test#mydomain.com" <test#mydomain.com>
Reply-To: test#mydomain.com
Message-Id: <E1RvIln-0003AQ-Cv#mr2.websitewelcome.com>
Date: Wed, 08 Feb 2012 19:25:55 -0600
X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
X-AntiAbuse: Primary Hostname - mr2.websitewelcome.com
X-AntiAbuse: Original Domain - aol.com
X-AntiAbuse: Originator/Caller UID/GID - [2146 32003] / [47 12]
X-AntiAbuse: Sender Address Domain - mr2.websitewelcome.com
X-BWhitelist: no
X-Source: /usr/bin/php
X-Source-Args: /usr/bin/php -q /home/itch3/public_html/handler.php
X-Source-Dir: switchon3.com:/public_html
X-Source-Sender:
X-Source-Auth: itch3
X-Email-Count: 2
X-Source-Cap: aXRjaDM7Y3ZncnViYnM7bXIyLndlYnNpdGV3ZWxjb21lLmNvbQ==
x-aol-global-disposition: G
X-AOL-SCOLL-SCORE: 0:2:199012208:93952408
X-AOL-SCOLL-URL_COUNT: 0
x-aol-sid: 3039ac1d61854f3320a4018d
X-AOL-IP: 67.18.65.19
X-AOL-SPF: domain : mr2.websitewelcome.com SPF : none
Can you use the additional parameters argument to (again) declare the from address?
mail('nobody#example.com', 'the subject', 'the message',
"From: webmaster#example.com\r\n", '-fwebmaster#example.com');
I generally add on the additional parameter when using mail() and it tends to fix most issues I've experienced.
You can set the Return-Path to test#mydomain.com, like so:
mail( $from, '', $message, $headers, '-ftest#mydomain.com');
(note the lack of space after -f)
The variable $from is not set, so it defaults. Your code should be:
//Set headers and send mail.
$headers = "From: " . "test#mydomain.com" . "\r\n";
$headers .= "Reply-To: ". "test#mydomain.com" . "\r\n";
$from = "test#mydomain.com";
mail( $from, '', $message, $headers );

Regular expression to parse Final-Recipient email header

I have to get any text between:
Final-Recipient: RFC822; !HERE! Action
I need !HERE! from this example. There could be any string.
I tried something like:
$Pattern = '/Final-Recipient: RFC822; (.*) Action/';
But it doesn't work.
upd
Here is the string I'm trying to parse: http://dpaste.com/187638/
Since you said "any string" which may contain spaces, the closest approximate would be
$Pattern = '/Final-Recipient: RFC822; (.*?) Action/s';
# ^ ^
# lazy match instead of greedy match ----' |
# allow . to match newline -----'
Of course it won't match "Final-Recipient: RFC822; Action Action".
Your pattern works fine for me:
$i = 'This is a MIME-encapsulated message --o3ONXoEH01blah3:35:33 +0400 (MSD) Final-Recipient: RFC822; !HERE! Action: failed Status: 4.4.7 Lblahru> From: *
#*.ru';
$pattern = '/Final-Recipient: RFC822; (.*) Action/';
$matches = Array();
preg_match($pattern, $i, $matches);
print_r($matches);
Output:
Array
(
[0] => Final-Recipient: RFC822; !HERE! Action
[1] => !HERE!
)
Note also that your pattern will fail if the "any text" contains new lines. Use the DOTALL modifier /.../s to allow the dot to also match new lines. Also note that if the text " Action" appears elsewhere in the message it will cause your regular expression to fail. Matching dot is dangerous. Try to find a more specific pattern if possible.
$Pattern = '/Final-Recipient:[^;]+[;|<|\s]+([^\s|^<|^>]+)/i';
The following expression turned out to be the best for my problems, because sometimes there are lines of the following kind:
Final-Recipient: LOCAL;<example#rambler.ru>
I am going to suggest a method that does not use them, which requires extra busywork.
<?php
$message = 'This is a MIME-encapsulated message --o3ONXoEH016763.1272152184/zvm19.host.ru The original message was received at Fri, 23 Apr 2010 03:35:33 +0400 (MSD) from roller#localhost ----- The following addresses had permanent fatal errors ----- "Flucker" ----- Transcript of session follows ----- 451 grl.unibel.by: Name server timeout Message could not be delivered for 2 days Message will be deleted from queue --o3ONXoEH016763.1272152184/*.host.ru Content-Type: message/delivery-status Reporting-MTA: dns; zvm19.host.ru Arrival-Date: Fri, 23 Apr 2010 03:35:33 +0400 (MSD) Final-Recipient: RFC822; !HERE! Action: failed Status: 4.4.7 Last-Attempt-Date: Sun, 25 Apr 2010 03:36:24 +0400 (MSD) --o3ONXoEH016763.1272152184/zvm19.host.ru Content-Type: message/rfc822 Content-Transfer-Encoding: 8bit Return-Path: Received: (from *#localhost) by *.host.ru (8.13.8/Zenon/Postman) id o3MNZX5h059932; Fri, 23 Apr 2010 03:35:33 +0400 (MSD) (envelope-from *#roller.ru) Date: Fri, 23 Apr 2010 03:35:33 +0400 (MSD) Message-Id: <201004222335.o3MNZX5h059932#*.host.ru> From: *
#*.ru';
$left_delimiter = 'Final-Recipient: RFC822; ';
$right_delimiter = ' Action';
$left_delimiter_pos = strrpos($message, $left_delimiter);
$right_delimiter_pos = strpos($message, $right_delimiter);
$desired_message_fragment = '';
if ($left_delimiter_pos !== false && $right_delimiter_pos !== false) {
$fragment_start = $left_delimiter_pos + strlen($left_delimiter);
$fragment_length = $right_delimiter_pos - $fragment_start;
$desired_message_fragment = substr(
$message, $fragment_start, $fragment_length
);
}
var_dump($desired_message_fragment);
a bit late....
but has been asked in terms of how to solve a problem that is not quite his requirements Op perhaps has joined multiple lines onto one line?(imho).
This might help others....
I'm assuming that op is trying to parse the Final-Recipient header field of a delivery status notification.
The spec for the Final-Recipient field can be seen here: https://www.rfc-editor.org/rfc/rfc3464#page-15
If the problem is broken down, op can pull the final recipient field as a single field (Final recipient followed by a char/blank line on the next line.
e.g.
Original-recipient: rfc822;some-email-that-does-not-exist#gmail.com
Final-recipient: rfc822;some-email-that-does-not-exist#gmail.com
Action: failed
Status: 5.1.1 (Remote SMTP server has rejected address)
Final recipient is followed by the start of the next field, Action which has A on the next line. ie not followed by a space or blank line.
then all he has to do is split the line on ; and take the second part
ie
String[] twoparts = "Final-recipient: rfc822;some-email-that-does-not-exist#gmail.com".split(";",2) // 2 here means (2-1) = 1 match
String email = twoparts[1]

Categories