PHP Displaying unread mail count - php

I am using php imap class.
In my box I have a lot of mail, but with this script I would retrieve only the unreaded mail.
How can I do it?
if ($mbox=imap_open( "{" . $mailserver . ":" . $port . "}INBOX", $user, $pass ))
{
echo "Connected\n";
} else { exit ("Can't connect: " . imap_last_error() ."\n"); echo "FAIL!\n"; };
if ($hdr = imap_check($mbox)) {
$msgCount = $hdr->Nmsgs;
echo "Ci sono ".$msgCount." mail";
} else {
echo "Failed to get mail";
}
If I do
$overview=imap_fetch_overview($mbox,"1:$msgCount",0);
the script load to an infinity time.
The imap_search UNSEEN solution is not good because pop3 don't use this flag.
So how can I do??????
Thanks a lot.

There is two way you can follow:
1. Looping through the messages
$count = imap_num_msg($connection);
for($msgno = 1; $msgno <= $count; $msgno++) {
$headers = imap_headerinfo($connection, $msgno);
if($headers->Unseen == 'U') {
... do something ...
}
}
2. Using imap_search
There's a flag called UNSEEN which you can use to search for the unread emails. You would call the imap_search function with the UNSEEN flag like so:
$result = imap_search($connection, 'UNSEEN');
If you need to combine this with more search flags, for example searching for messages from me#example.com, you could do this:
$result = imap_search($connection, 'UNSEEN FROM "me#example.com"');
For a complete list of the available flags, refer to the criteria section of the imap_search manual page on the PHP website (www.php.net/imap_search)
Source: http://www.electrictoolbox.com/php-imap-unread-messages/

This was a tough one on Google: php imap unread
The first result:
http://www.electrictoolbox.com/php-imap-unread-messages/
There's a flag called UNSEEN which you can use to search for the unread emails. You would call the imap_search function with the UNSEEN flag like so:
view sourceprint?
$result = imap_search($connection, 'UNSEEN');
If you need to combine this with more search flags, for example searching for messages from me#example.com, you could do this:
view sourceprint?
$result = imap_search($connection, 'UNSEEN FROM "me#example.com"');
For a complete list of the available flags, refer to the criteria section of the imap_search manual page on the PHP website (www.php.net/imap_search)
Edit I had read this originally as IMAP. #fail.
Google: php pop3 unread
2nd link:
function CountUnreadMails($host, $login, $passwd) {
$mbox = imap_open("{{$host}/pop3:110}", $login, $passwd);
$count = 0;
if (!$mbox) {
echo "Error";
} else {
$headers = imap_headers($mbox);
foreach ($headers as $mail) {
$flags = substr($mail, 0, 4);
$isunr = (strpos($flags, "U") !== false);
if ($isunr)
$count++;
}
}
imap_close($mbox);
return $count;
}

Related

imap_setflag_full not working to change mail status

I am using below code to read my gmail inbox and it's working fine for reading.
But the issue is some of the mail are not set as seen so they comes every time.
As per my observation mails which do not change there flag from unseen to seen are the mails which contains some HTML in it.
Below is my code:
public function getMessages($type = 'text') {
$stream = $this->imapStream;
$emails = imap_search($stream, 'UNSEEN');
$messages = array();
if ($emails) {
$this->emails = $emails;
$i = 0;
foreach ($emails as $email_number) {
$this->attachments = array();
$uid = imap_uid($stream, $email_number);
$messages[] = $this->loadMessage($uid, $type);
if ($i == $this->limit) {
break;
}
$i++;
echo "seen status=>".imap_setflag_full($stream, $email_number, "\\Seen", ST_UID);
//echo "seen status=>".imap_clearflag_full($stream, $email_number, "\\Seen");
}
}
return $messages;
}
This is the line i am using to manually change status
echo "seen status=>".imap_setflag_full($stream, $email_number, "\\Seen", ST_UID);
seen status always return 1 as result but in inbox it shows as unread.
You are using Message Sequence Numbers (MSNs), but providing the ST_UID flag to your flag functions, changing them to use UIDs. Most MSNs will not generally be valid UIDs.
Either use UIDs everywhere (with FT_UID and ST_UID and the like to all functions) or MSNs everywhere (never use UID flags, and don't expunge anything while looping.)
imap_setflag_full($stream, $email_number, "\\Seen");
or
imap_setflag_full($stream, $uid, "\\Seen", ST_UID);
If you use the UID version of search, you don't need to call imap_uid.

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

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

Fetching mail from a POP3 server using php

I am trying to fetch a mail from POP3 (I am using POP3 mail server and I am trying to fetch the mail content and store into a database table for my project.), but I can't find any PHP script for that, all are only for IMAP.
Do you know how to fetch mail from a POP3 server?
Thanks.
Somewhat surprisingly, PHP's imap library can be also used for working with POP3 mailboxes. Most of the advanced IMAP features won't work, of course (e.g. folders or fetching message parts), but the basic POP3 functionality is implemented.
The main difference is the option string that you're passing to imap_open - to quote that page:
// To connect to a POP3 server on port 110 on the local server, use:
$mbox = imap_open ("{localhost:110/pop3}INBOX", "user_id", "password");
Other than that, it's fair sailing - you won't need more than imap_open, imap_num_msg, imap_body, imap_delete and imap_close for basic POP3 access.
PHP's IMAP functions can deal with both IMAP and POP3 boxes.
These functions enable you to operate with the IMAP protocol, as well as the NNTP, POP3 and local mailbox access methods.
Be warned, however, that some IMAP functions will not work correctly with the POP protocol.
there is a User Contributed Note that provides an interesting snippet. You may want to take a look at it. I can't say anything about its quality but from the surface, it looks okay.
Below, the Contributed Note:
For all the people coming here praying for:
1) a dead-easy way to read MIME attachments, or
2) a dead-easy way to access POP3 folders
Look no further.
function pop3_login($host,$port,$user,$pass,$folder="INBOX",$ssl=false)
{
$ssl=($ssl==false)?"/novalidate-cert":"";
return (imap_open("{"."$host:$port/pop3$ssl"."}$folder",$user,$pass));
}
function pop3_stat($connection)
{
$check = imap_mailboxmsginfo($connection);
return ((array)$check);
}
function pop3_list($connection,$message="")
{
if ($message)
{
$range=$message;
} else {
$MC = imap_check($connection);
$range = "1:".$MC->Nmsgs;
}
$response = imap_fetch_overview($connection,$range);
foreach ($response as $msg) $result[$msg->msgno]=(array)$msg;
return $result;
}
function pop3_retr($connection,$message)
{
return(imap_fetchheader($connection,$message,FT_PREFETCHTEXT));
}
function pop3_dele($connection,$message)
{
return(imap_delete($connection,$message));
}
function mail_parse_headers($headers)
{
$headers=preg_replace('/\r\n\s+/m', '',$headers);
preg_match_all('/([^: ]+): (.+?(?:\r\n\s(?:.+?))*)?\r\n/m', $headers, $matches);
foreach ($matches[1] as $key =>$value) $result[$value]=$matches[2][$key];
return($result);
}
function mail_mime_to_array($imap,$mid,$parse_headers=false)
{
$mail = imap_fetchstructure($imap,$mid);
$mail = mail_get_parts($imap,$mid,$mail,0);
if ($parse_headers) $mail[0]["parsed"]=mail_parse_headers($mail[0]["data"]);
return($mail);
}
function mail_get_parts($imap,$mid,$part,$prefix)
{
$attachments=array();
$attachments[$prefix]=mail_decode_part($imap,$mid,$part,$prefix);
if (isset($part->parts)) // multipart
{
$prefix = ($prefix == "0")?"":"$prefix.";
foreach ($part->parts as $number=>$subpart)
$attachments=array_merge($attachments, mail_get_parts($imap,$mid,$subpart,$prefix.($number+1)));
}
return $attachments;
}
function mail_decode_part($connection,$message_number,$part,$prefix)
{
$attachment = array();
if($part->ifdparameters) {
foreach($part->dparameters as $object) {
$attachment[strtolower($object->attribute)]=$object->value;
if(strtolower($object->attribute) == 'filename') {
$attachment['is_attachment'] = true;
$attachment['filename'] = $object->value;
}
}
}
if($part->ifparameters) {
foreach($part->parameters as $object) {
$attachment[strtolower($object->attribute)]=$object->value;
if(strtolower($object->attribute) == 'name') {
$attachment['is_attachment'] = true;
$attachment['name'] = $object->value;
}
}
}
$attachment['data'] = imap_fetchbody($connection, $message_number, $prefix);
if($part->encoding == 3) { // 3 = BASE64
$attachment['data'] = base64_decode($attachment['data']);
}
elseif($part->encoding == 4) { // 4 = QUOTED-PRINTABLE
$attachment['data'] = quoted_printable_decode($attachment['data']);
}
return($attachment);
}
you can use pop3 e-mail client class which can Access to e-mail mailboxes using the POP3 protocol.
You will get each e-mail body part and can store it in database, even you can retrieve attached files without deleting the original mail in the inbox.
For more go to http://www.phpclasses.org/package/2-PHP-Access-to-e-mail-mailboxes-using-the-POP3-protocol.html
IF you have PHP build with IMAP support, it would be easy, see IMAP documentation (especially comments at this page) at http://php.net/manual/en/book.imap.php
UPDATE: to clarify my answer - as you see in the comments and function reference, PHP imap_* functions can be used also for pop3.
You can open a socket connection and send POP3 commands directly to your server to retrieve emails.
The code below opens a connection to the server, authenticates, requests a count of available messages, downloads them one by one, then deletes them from the server. During the interaction with the server, if an unexpected response is received, the connection is closed.
You should be able to alter the code below to get what you need.
Create a config.ini file and populate it like this:
pop3_host=your.pop3.host
pop3_user=youremailusername
pop3_pass=youremailpassword
Obviously substitute the values with your actual host, username and password. Then change the parse_ini_file parameter to point to your config.ini file.
<?php
$config = parse_ini_file('/path/to/config.ini');
$stream = fsockopen('ssl://' . $config['pop3_host'], 995, $error_code, $error_message);
if (!$stream) {
die('fsockopen ' . $error_code . ' ' . $error_message);
}
$s = fgets($stream);
if (substr($s, 0, 3) !== '+OK') {
quit('OPEN');
}
chat('USER ' . $config['pop3_user']);
chat('PASS ' . $config['pop3_pass']);
$s = chat('STAT');
$stat = explode(' ', $s);
if (count($stat) !== 3) {
quit('STAT+');
}
$n = (integer)$stat[1];
for ($i = 1; $i <= $n; $i++) {
chat('RETR ' . $i);
$file = fopen($i . '.msg', 'wb');
if (!$file) {
quit('FILE ' . $i);
}
while (true) {
$s = fgets($stream);
if ($s === '.' . "\r\n") {
fclose($file);
break;
}
fputs($file, $s);
}
chat('DELE ' . $i);
}
chat('QUIT');
fclose($stream);
function chat(string $command): string {
global $stream;
fputs($stream, $command . "\r\n");
$s = fgets($stream);
if (substr($s, 0, 3) !== '+OK') {
quit(explode(' ', $command)[0]);
}
return $s;
}
function quit(string $message): void {
global $stream;
fputs($stream, 'QUIT' . "\r\n");
$s = fgets($stream);
fclose($stream);
die($message);
}

Categories