reading inbox with IMAP is not very fast - php

I am using IMAP to read my last 3 unseen emails.
I am using php. The email provider is fastmail.
I use the following approach.
I get the emails where $d is yesterday.
$s = 'SUBJECT "New email from " SINCE "'.$d.'" UNSEEN';
$emails = imap_search($this->conn,$s);
$emails is an array of email ids.
I loop over them like so:
foreach ($emails as $index => $i) {
$message = imap_body($this->conn, $i) . '<br>';
$overview = imap_fetch_overview($this->conn, $i, 0);
$structure = imap_fetchstructure($this->conn, $i);
if (!empty($overview[0])) {
$subject = $overview[0]->subject;
}
//from this point i get some html and i just process it.
$mes = imap_body($this->conn, $i);
}
How can i make the whole process faster? Any ideas?
I am not an expert in IMAP.
Is there any way that i can just get the text body, and not the rest of the email?
Thanks in advance!

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/>";
}
}

Send email with multiple messages to different users in sendgrid

We are using sendgrid for email,
we have tried,
$email = new SendGrid\Email();
$emails = array("foo#bar.com", "another#another.com", "other#other.com");
$email->setTos($emails);
$email->setHtml(array($message1,$message1));
$sendgrid->send($email);
How to set different - different $email->setHtml(array($message1,$message1)) at a time.
As per I understand from your question you want to send different messages to different email ids. Which can be achieve by
$email = new SendGrid\Email();
$emails = array("foo#bar.com", "another#another.com", "other#other.com");
$message = array("message1","message2","message3"); //create a array of messages according to email ids
$i =0 ;
foreach ($emails as $value) {
$email->setTos($value);
$email->setHtml($message[$i]);
$sendgrid->send($email);
$i++;
}
As your question is confusing, I will assume you want to send different email messages to all users in the list. So:
$email = new SendGrid\Email();
$emails = array("foo#bar.com", "another#another.com", "other#other.com");
$messages = array("message1", "message2");
foreach ($messages as $msg) { // Grab every message...
$email->setTos($emails); // for everyone...
$email->setHtml($msg); // set it as the body...
$sendgrid->send($email); // and send it.
}

imap_search() for unseen messages does not returning anything

I am currently trying to get the UNSEEN/UNREAD messages from my server. Currently, I have this:
$openmail = imap_open($dns, $email, $password) or die("Cannot Connect " . imap_last_error());
if ($openmail) {
/* grab emails */
$emails = imap_search($openmail, 'UNSEEN');
if ($emails) {
//For every e-mail.
$tot = imap_num_msg($openmail);
for ($i = $tot; $i > 0; $i--) {
$structure = imap_fetchstructure($openmail, $i);
if (isset($structure->parts) && is_array($structure->parts) && isset($structure->parts[1])) {
$part = $structure->parts[1];
$message = imap_fetchbody($openmail, $i, 2, FT_PEEK);
if ($part->encoding == 3) {
$message = imap_base64($message);
} else if ($part->encoding == 1) {
$message = imap_8bit($message);
} else {
$message = imap_qprint($message);
}
}
$header = imap_header($openmail, $i);
$from = imap_utf8($header->fromaddress);
$subject = $header->Subject;
$subject = substr($subject, 0, 150);
$date = $header->Date;
}
/* Print out the Unseen messages in here! */
} else {
/* No unseen messages */
echo "No unseen";
}
}
I've tried sending multiply emails to my mailserver, refreshed the page with the above script. But I keep getting the "No unseen".
I've tried to output the $emails but it's empty. It can't find anything.
If I try to just get ALL the messages (no unseen filter), I can see the emails I've sent to the mailbox, although, they're all marked as read.
Your code $message = imap_fetchbody($openmail, $i, 2, FT_PEEK); uses hardcoded part offsets, i.e. it assumes that a message is always multipart/alternative with text/plain and text/html. That's a very wrong assumption.
You have to look at the output of the BODYSTRUCTURE to see what the MIME structure of your mail is.
With that out of the way, be sure that none of your commands use the BODY fetch operation; you have to use BODY.PEEK. I have no idea how this is accessible within the PHP c-client bindings.

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

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