imap_search limit the number of messages returned
Asked Answered
T

4

11

I have PHP script that fetch messages from a mailbox. I use the imap_search function: $emails = imap_search($mbox, 'UNSEEN');

Is there a way to limit the number of returned messages. Right now on huge mailboxes i get like 5000 messages. I want only the top 20 ordered by date.

Is there a way to do that?

Thanks.

Tavie answered 1/2, 2010 at 14:26 Comment(0)
L
9

The imap_search function has a CRITERIA attribute you can use to limit the messages in a number of ways:

ALL - return all messages matching the rest of the criteria
ANSWERED - match messages with the \ANSWERED flag set
BCC "string" - match messages with "string" in the Bcc: field
BEFORE "date" - match messages with Date: before "date"
BODY "string" - match messages with "string" in the body of the message
CC "string" - match messages with "string" in the Cc: field
DELETED - match deleted messages
FLAGGED - match messages with the \FLAGGED (sometimes referred to as Important or Urgent) flag set
FROM "string" - match messages with "string" in the From: field
KEYWORD "string" - match messages with "string" as a keyword
NEW - match new messages
OLD - match old messages
ON "date" - match messages with Date: matching "date"
RECENT - match messages with the \RECENT flag set
SEEN - match messages that have been read (the \SEEN flag is set)
SINCE "date" - match messages with Date: after "date"
SUBJECT "string" - match messages with "string" in the Subject:
TEXT "string" - match messages with text "string"
TO "string" - match messages with "string" in the To : UNANSWERED - match messages that have not been answered
UNDELETED - match messages that are not deleted
UNFLAGGED - match messages that are not flagged
UNKEYWORD "string" - match messages that do not have the keyword "string"
UNSEEN - match messages which have not been read yet

Litho answered 1/2, 2010 at 14:30 Comment(4)
That will narrow down the search, but will that limit how much mail to return back?Portative
@Anthony: this is the only way to narrow down the stuff a bit no other way as far as i know. Is there one?Litho
To narrow it down, its the only way. But his criteria is a limit number for, what I am assuming to be, all messages, which imap_search does not provide. There might be a hack, see my edit and let me know what you think.Portative
How to get the mails from a particular label. ??Mecklenburg
H
1

imap_sort will allow you to both sort and filter at the same time

But still, it won't allow to limit to the 'top 20' right at the function call.

Hoyden answered 5/2, 2010 at 17:57 Comment(0)
W
1

imap_search docs indicate this function:

Returns an array of message numbers or UIDs.

imap_fetch_overview docs indicate this function also returns:

message_id - Message-ID, uid - UID the message has in the mailbox

So we can use the imap_fetch_overview and sort a certain number and order with the same return as the imap_search function.

// get information about the current mailbox
$mboxCheck = imap_check($mbox);

// get the total amount of messages
$totalMessages = $mboxCheck->Nmsgs;

// select how many messages you want to see
$showMessages = 20;

// get those messages    
$result = imap_fetch_overview($mbox($totalMessages-$showMessages+1).":".$totalMessages);

$n = 0;
$emails = array();
// loop through returned messages, collect message numbers in same format as output of imap_search
foreach ($result as $mail) {
    $emails[$n] = $mail->msgno;
    $n++;
}  

if($emails) {
// put the newest emails on top 
rsort($emails);
}

This is built with the concept from this answer

Weinman answered 5/4, 2019 at 20:34 Comment(0)
U
0

To solve this problem by so:

1.You could limit the no of result returned by reducing the no of data using the since criteria 2. Retreive few last returned messages e.g 15

$this->msgCounts = imap_search($imap_resource, 'SUBJECT "hello dolly" SINCE "8 April 2003"', SE_UID);

And then here is an example to retreive the last 15 returned and then toggle forward and backward to view more results or older.Note this assumes you have a button forward and older that set $_GET variables.

$this->msgCounts = $messageCounts;
        $multiarray=[];
        \Session::put('totalmsg',$this->msgCounts);             //Sav etotal no of message in folder to session to determine if to allow next or previous

        if($this->msgCounts > 15)                               //MESSAGES IS MORE THAN WE NEED GET 20
        {
            $offcut = 15;                                       //default offcut

            /**
            * Viewing previous or next messages
            **/
                if(isset($_GET['msgs']) && $_GET['msgs'] == 'older')
                {
                 $this->msgCounts =  \Cache::has('msgpointer') ? \Cache::get('msgpointer') : $this->msgCounts;
                    $msgOffset = $this->msgCounts - $offcut;    //get +15 messages

                    if($offcut > $msgOffset) {
                        $msgOffset = $msgOffset + 5;            //if less than 15 get 10
                        $offcut = 10;
                    }
                    if($offcut > $msgOffset) {
                        $msgOffset = $msgOffset + 5;            //if less than 10 get 5
                        $offcut = 5;
                    }
                    if($offcut > $msgOffset) {
                        $msgOffset = $msgOffset + 3;            //if less than 3 get 2
                        $offcut = 2;
                    }
                    if($offcut > $msgOffset) {
                        $msgOffset = $msgOffset + 2;            //if less than 2 get 1
                        $offcut = 1;
                    }


                    \Cache::put('msgpointer',$msgOffset,60 * 60 * 24);
                }

                if(isset($_GET['msgs']) && $_GET['msgs'] == 'newest')
                {
                    $this->msgCounts =  \Cache::has('msgpointer') ? \Cache::get('msgpointer') : $this->msgCounts;
                    $msgOffset = $this->msgCounts + $offcut;    //get +15 messages

                    if($msgOffset > $messageCounts) {
                        $msgOffset = $msgOffset - 5;            //if not up to 15 get 10
                        $offcut = 10;
                    }
                    if($msgOffset > $messageCounts) {
                        $msgOffset = $msgOffset - 5;            //if not up to 10 get 5
                        $offcut = 5;
                    }
                    if($msgOffset > $messageCounts) {
                        $msgOffset = $msgOffset - 3;            //if not up to 5 get 2
                        $offcut = 2;
                    }
                    if($msgOffset > $messageCounts) {
                        $msgOffset = $msgOffset - 2;            //if not up to 2 get 1
                        $offcut = 1;
                    }


                    \Cache::put('msgpointer',$msgOffset,60 * 60 * 24);
                }


            // LOOP THROUGH LAST 20 MESSAGES IF THERE MORE THAN 10 MESSAGES
            for ($i = $this->msgCounts; $i > $this->msgCounts - $offcut; $i--) 
            { 

                 $header = imap_header($this->conn,$i);                             //GET HEADER INFO USING IMAP FUNCTION
                 $uid    = imap_uid($this->conn,$i);                                //GET UNIQUE MESSAGE ID FOR READING MESSAGE LATER


                 //SAVE ALL MESSAGE INFO IN ARRAY
                 $tobox    = $header->reply_to[0]->mailbox ? $header->reply_to[0]->mailbox : 'noreply';
                 $tohost   = $header->reply_to[0]->mailbox ? $header->reply_to[0]->host : 'email.com';
                 $toaddress = $tobox.'@'.$tohost;


                 $mailbox = isset($header->from[0]->mailbox) ? $header->from[0]->mailbox : 'no-reply';
                 $host    = isset($header->from[0]->host) ? $header->from[0]->host : 'email.com';
                 $fromaddress = $mailbox.'@'.$host;

                 $array = ['toaddress' => isset($header->toaddress) ? $header->toaddress : isset($header->to) ? $header->to[0]->mailbox.'@'.$header->to[0]->host : $toaddress,'date' => isset($header->date) ? $header->date : date('Y-m-d'),'subject' => isset($header->subject) ? $header->subject : "no subject" ,'from' => isset($header->from[0]->personal) ? $header->from[0]->personal :$fromaddress,'unseen' => isset($header->Unseen) ? $header->Unseen : 'S', 'uid' => isset($uid) ? $uid : $i,'fromemail' => $fromaddress];
                //PASS A MESSAGE INFO INTO A MULTI ARRAY
                $multiarray[] = $array;

            }

You could set the date it get from to be 90 days before then if its a lot.return it chunk by chunk like above.My apologies for using some laravel helper classes there,all is well commented out. Hope this helps someone!

Unkind answered 27/8, 2015 at 18:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.