Can I stop imap_search from setting emails to READ - php

I have a function that connects to an imap email account (currently testing with gmail) to get emails that are UNSEEN. After getting the emails I loop through them and do imap_fetch_overview() and imap_fetchbody() on each email.
After running this function all the emails that have been searched get set to READ in the inbox.
Is there anyway to stop this happening? Ideally i'd like the email to remain UNSEEN.
Here is my function
function build_email_data(){
$this->connect();
/* grab emails */
$emails = imap_search($this->inbox,'UNSEEN');
/* if emails are returned, cycle through each... */
if($emails) {
/* put the newest emails on top */
rsort($emails);
$data = array();
/* for every email... */
foreach($emails as $email_number) {
/* get information specific to this email */
$overview = imap_fetch_overview($this->inbox,$email_number,0);
$message = imap_fetchbody($this->inbox,$email_number,1);
$_data['subject'] = $overview[0]->subject;
$_data['from'] = $overview[0]->from;
$_data['body'] = $message;
$_data['owner_id'] = 1;
$_data['email_number'] = $email_number;
$_data['folder_id'] = 1;
$_data['created'] = timestamp_to_mysqldatetime();
$_data['updated'] = timestamp_to_mysqldatetime();
$_data['email_date'] = timestamp_to_mysqldatetime(strtotime($overview[0]->date));
$data[] = $_data;
}
$this->disconnect();
return $data;
}
}

I figured out why they were getting set to READ and also how to stop it.
$message = imap_fetchbody($this->inbox,$email_number,1);
That code sets the message to READ. By adding FT_PEEK as an option it remains UNSEEN
$message = imap_fetchbody($this->inbox,$email_number,1, FT_PEEK);
or in case of using imap_body :
$message = imap_body($this->inbox,$email_number,1, FT_PEEK);
References: imap_body imap_fetchbody

Are you confusing UNSEEN and RECENT? Fetching messages will clear the RECENT flag, but only changing the flags (adding \Seen) should change the SEEN flag.

Related

issues with IMAP functions php

I am facing some problem with imap function. Basically What I need to do is to read unseen mails. There will be a url in all the mails, i should fetch that URL and store.
$inbox = imap_open($hostname,$username,$password);
if($inbox)//if **1
{
/* grab emails */
$emails = imap_search($inbox,'UNSEEN');
/* if emails are returned, cycle through each... */
if($emails) //if **2
{
/* put the newest emails on top */
rsort($emails);
/* for every email... */
$varients=array("1","1.1","1.2","2");
foreach($emails as $email_number) //for loop **1
{
$ids [] = $email_number;
foreach($varients as $cur_varient) //for loop **2
{
echo "\n\nstarting with imap function number ". $cur_varient."\n\n";
$overview = imap_fetch_overview($inbox,$email_number,0);//all varients of like subject, date etc.
$from = addslashes(trim($overview[0]->from));
$inboxed_time = addslashes(trim(strtotime($overview[0]->date)));
$message = (imap_body($inbox,$email_number,$cur_varient));
print addslashes(trim($overview[0]->subject));break;
preg_match_all('#\bhttp?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $message, $match);
$link_matched = $match[0];
$input = 'unsubscribe.php';
$linkexists = false;
foreach($link_matched as $curlink)
{
if(stripos($curlink, $input) !== false)
{
$linkexists = true;
$unsublink = $curlink;
$unsublink = str_replace('href="', '', $unsublink);
$unsublink = str_replace('"', '', $unsublink);
break;
}
}
if(isset($unsublink))
{
$unsublink = addslashes(trim(($unsublink)));
$thread = 1;
$time = date("Y-m-d H:i:s");
$iQry = " INSERT INTO `SPAMS`.url_queue VALUES(";
$iQry .= " 'default','".$unsublink."','".$thread."','";
$iQry .= "".$from."','".$inboxed_time."',UNIX_TIMESTAMP('".$time."'))";
//mysql_query($iQry);
print $iQry;
}
}//closing for loop **2
}//closing for loop **1
} //closing if **2
// Setting flag from un-seen email to seen on emails ID.
if(isset($ids))
{
imap_setflag_full($inbox,implode(",", $ids), "\\Seen \\Flagged"); //IMPORTANT
}
// colse the connection
imap_expunge($inbox);
imap_close($inbox);
}//closing if **1
I have used all different varients of imap to make sure it will read different types of mails. Now issue is, sometime the URL matched is broken. Only half URL will be fetched(I printed the entire message, saw that half URL is coming to next line). The other issue is, sometimes, the body fetched will not be the one which the current mail contains. It fetched some other mail content.
I am puzzled what to do, so putting my entire code, please help.
You will have to use a regex modifiers to match multiline texts too, or you can strip newlines and such from the body of the emails.
preg_match("/{pattern}/mi",'Testing');
//m for multiline matches and i for case-insensitive matches
Your second issue is a bit different than you'd think, emails have multiple bodies, one for simple texts, one for html, some for attachments (and their order is different in apple products).
https://www.electrictoolbox.com/php-imap-message-parts/
You are probably facing the issue of grabbing the wrong one. My recommendation would be to fetch all of the email bodies, like this:
$overview = imap_fetch_overview($this->connection, $email_number, 0);
$structure = imap_fetchstructure($this->connection, $email_number);
$message = "";
//$parts = [1, 1.1, 1.2, 2];
if (!$structure->parts)//simple email
$message .= "Simple: ". imap_fetchbody($this->connection, $email_number, 0). "<br/>";
else {
foreach ($structure->parts as $partNumber=>$part){
if ($partNumber != 0)
$message .= "Part ".$partNumber.": ". imap_fetchbody($this->connection, $email_number, $partNumber)."<br/>";
}
}

Find E-Mails with an exact e-mail address on an IMAP server using PHP

I want to connect to an IMAP-server and find all E-Mails that were sent to abc#server.tld. I tried:
$mbox = imap_open("{imap.server.tld/norsh}", "imap#server.tld", "5ecure3");
$result = imap_search($mbox, "TO \"abc#server.tld\"", SE_UID);
but this also listed e-Mails that were sent e.g. to 123abc#server.tld. Is it somehow possible to do a search for exact matches?
Short answer: you can't. I didn't find anything in RFC 2060 - Internet Message Access Protocol - Version 4rev1 saying that it can be done.
But, there is a workaround. First fetch all emails that contain abc#server.tld, then iterate through the results and select only the exact matches.
$searchEmail = "abc#server.tld";
$emails = imap_search($mbox, "TO $searchEmail");
$exactMatches = array();
foreach ($emails as $email) {
// get email headers
$info = imap_headerinfo($mbox, $email);
// fetch all emails in the TO: header
$toAddresses = array();
foreach ($info->to as $to) {
$toAddresses[] = $to->mailbox . '#' . $to->host;
}
// is there a match?
if (in_array($searchEmail, $toAddresses)) {
$exactMatches[] = $email;
}
}
Now you have all emails matching abc#server.tld in $exactMatches

Email-based PHP chat window

I am building a chat/SMS based system I have it sending out the messages but what I need to do is live update the textarea with data from incoming emails without the user reloading (ajax?) I need to pass a number from the main page to fetch.php which gets the emails and creates an array out of emails which have not been read and come from the right sender what I need to do yet is send the number from the main page to the fetch page and return a array of new messages to the main textarea but all the tutorials I have found on ajax seem to require a database and I have no idea how to go about running and returning data on a delay help would be appreciated.
Here is the content of fetch.php:
<?php
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
/* connect to gmail */
$hostname = '{imap.gmail.com:993/imap/ssl}INBOX';
$username = 'user#gmail.com';
$password = 'passwd';
/* try to connect */
$inbox = imap_open($hostname,$username,$password) or die('Cannot connect to Gmail: ' . imap_last_error());
/* grab emails */
$emails = imap_search($inbox,'ALL');
/* if emails are returned, cycle through each... */
if($emails) {
$messages[] = '';
/* begin output var */
$output = '';
/* put the newest emails on top */
rsort($emails);
/* for every email... */
foreach($emails as $email_number) {
/* get information specific to this email */
$overview = imap_fetch_overview($inbox,$email_number,0);
$message = imap_fetchbody($inbox,$email_number,1);
//print_r($overview);
$Is_sms = strpos($overview[0]->from, "txt.voice.google.com");
if($Is_sms === false) continue;
if($overview[0]->seen != 0) continue;
$pnl = strpos($overview[0]->from, ".");
$pnumber = substr($overview[0]->from, $pnl +2, 10);
if($pnumber != "3303331866") continue;
$messages[] = $message;
//$status = imap_setflag_full($mbox, $mail, "\\Seen \\Flagged", ST_UID);
/* output the email header information */
/*$output.= '<div class="toggler '.($overview[0]->seen ? 'read' : 'unread').'">';
$output.= '<span class="subject">'.$overview[0]->subject.'</span> ';
$output.= '<span class="from">'.$overview[0]->from.'</span>';
//$output.= '<span class="date">on '.$overview[0]->date.'</span>';
$output.= '<span class="pnumber">'.$pnumber.'</span>';
$output.= '</div>';*/
/* output the email body */
//$output.= '<div class="body">'.$message.'</div>';
}
//echo $output;
print_r($messages);
}
/* close the connection */
imap_close($inbox);
The main page is just a to number textbox, a content textarea, a message textbox, and a send button.
The database is required to store the messages for you to fetch later when the AJAX request from a browser needs it. This is because your PHP script does not retain its variables between two subsequent runs and therefor you will need to store the messages somewhere. So it will basically go like this:
Get new message
Place it in some kind of ordered queue where you will be able to fetch everything later than what the client already has.
Send it off to client.
The queue could be numbered with numbers counting upward from the first post, thus allowing clients to specify what the last received message they got was and request everything newer.
BTW, if i did not make it sufficiently clear above, what you said about AJAX requiring a database is somewhat misunderstood. AJAX can function properly without, its just your case that needs some storage and databases are a good way to do it.
Hope that helps :)

how can I display the contents of an email to a website?

I would like to display the body contents of an email. I have tried IMAP in php but something is VERY wrong. The IMAP isn't picking up the body of my message. It is picking up ONLY the signature in the body. So I am looking for alternative methods of reading email body contents to a webpage.
here is the original document of my email:
http://pastebin.com/WQra335P
the disclaimer/copyright blur is being grabbed by IMAP but nothing else in the body is being displayed. anyone have alternative methods of reading email from gmail or any other site that can display the contents to a webpage?
I have given up on making IMAP read it because no one has been able to figure out the problem...I have spent hours so I give up but here is the code...
<?php
/* connect to gmail */
$hostname = '{imap.gmail.com:993/imap/ssl}INBOX';
$username = 'username#gmail.com';
$password = 'password';
/* try to connect */
$inbox = imap_open($hostname,$username,$password) or die('Cannot connect to Gmail: ' . imap_last_error());
/* grab emails */
$emails = imap_search($inbox,'ALL');
/* if emails are returned, cycle through each... */
if($emails) {
/* begin output var */
$output = '';
/* put the newest emails on top */
rsort($emails);
/* for every email... */
foreach($emails as $email_number) {
/* get information specific to this email */
$overview = imap_fetch_overview($inbox, $email_number, 0);
$message = imap_fetchbody($inbox, $email_number, 2);
echo $message;
echo imap_qprint($message);
$message = imap_qprint($message);
echo imap_8bit ($message);
$DateFormatted = str_replace("-0500", "", $overview[0] -> date);
/* output the email header information */
$output .= $overview[0] -> subject ;
$output .= $DateFormatted ;
//$bodyFormatted = preg_replace("/This e-mail(.*)/","",$message);
//$bodyFormatted = preg_replace("/Ce courriel(.*)/","",$bodyFormatted);
/* output the email body */
$output .= $message;
}
echo $output;
}
/* close the connection */
imap_close($inbox);
?>
In Addition to what DmitryK suggested,
Adding the below makes everything work fine without the random "=" signs. The Str_replace is used to remove the "="s generated over the pages.
$message = imap_fetchbody($inbox, $email_number, "1.1");
$message = str_replace("=", "", $message);
I dont know 100% why the "="s are generated randomly but this is most likely due to some encryption issue from the Exchange Server's side as our server is about 10 years old.
You are dealing with the multi-part messages (looking at your pastebin e-mail sample).
As a test try using this line:
$message = imap_fetchbody($inbox, $email_number, "1.1");
Plain text version lives under 1.1
HTML version is 1.2
The signature is in the next part - it is 2. And this is what you retrieve in your code sample.
Do you have access to the raw email content (the stuff with all the headers etc)
If so, try using plancacke email parser
I have used it before with good success.
$emailParser = new PlancakeEmailParser(...raw email content...);
$emailTo = $emailParser->getTo();
$emailSubject = $emailParser->getSubject();
$emailCc = $emailParser->getCc();
$emailDeliveredToHeader = $emailParser->getHeader('Delivered-To');
$emailBody = $emailParser->getPlainBody();
$emailHtml = $emailParser->getHTMLBody();
Gmail has some different IMAP settings, follow the original code more closely:
http://davidwalsh.name/gmail-php-imap

Retrieve the 3 most recent email using imap and php

I'm trying to figure out how to get the latest 3 emails (SEEN and UNSEEN) using imap and php. It need to be ressource-efficient since the mailbox as 1 000 emails inside. Getting all header may need too much ressources I think.
I just need the sender, the subject and the date...
Any idea? Thanks for any syggestion/help/explaination/hint...
I did it like that:
$mbox = imap_open("{imap.myconnection.com:993/imap/ssl}INBOX", "username", "password");
// get information about the current mailbox (INBOX in this case)
$mboxCheck = imap_check($mbox);
// get the total amount of messages
$totalMessages = $mboxCheck->Nmsgs;
// select how many messages you want to see
$showMessages = 5;
// get those messages
$result = array_reverse(imap_fetch_overview($mbox,($totalMessages-$showMessages+1).":".$totalMessages));
// iterate trough those messages
foreach ($result as $mail) {
print_r($mail);
// if you want the mail body as well, do it like that. Note: the '1.1' is the section, if a email is a multi-part message in MIME format, you'll get plain text with 1.1
$mailBody = imap_fetchbody($mbox, $mail->msgno, '1.1');
// but if the email is not a multi-part message, you get the plain text in '1'
if(trim($mailBody)=="") {
$mailBody = imap_fetchbody($mbox, $mail->msgno, '1');
}
// just an example output to view it - this fit for me very nice
echo nl2br(htmlentities(quoted_printable_decode($mailBody)));
}
imap_close($mbox);
PHP-Ref IMAP: http://php.net/manual/en/ref.imap.php
Regards
Dominic
What about
imap_search($res, 'RECENT');
?
http://php.net/manual/en/function.imap-search.php
$msgnos = imap_search($mbox, "UNSEEN", SE_UID);
$i=0;
foreach($msgnos as $msgUID) {
$msgNo = imap_msgno($mbox, $msgUID);
$head = imap_headerinfo($mbox, $msgNo);
$mail[$i][] = $msgUID;
$mail[$i][] = $head->Recent;
$mail[$i][] = $head->Unseen;
$mail[$i][] = $head->from[0]->mailbox."#".$head->from[0]->host;
$mail[$i][] = utf8_decode(imap_utf8($head->subject));
$mail[$i][] = $head->udate;
}
return $mail;
imap_close($mbox);
Will do the job.

Categories