Ahmed
Ahmed

Reputation: 1533

PHP imap_search UNSEEN SINCE date with time

I am using PHP imap_search to fetch list of unseen messages since a given date like this:

imap_search($stream, 'UNSEEN SINCE 20-Sep-2015');

This is working fine. However, I am periodically every few minutes checking for new emails and then storing the last check time in a session. I want to be able to run the imap_search with the UNSEEN SINCE date including time. But it just does not seem to work. I've tried:

imap_search($stream, 'UNSEEN SINCE 20-Sep-2015 12:35:03 +0000 (UTC)');
imap_search($stream, 'UNSEEN SINCE 20-Sep-2015 12:35:03 +0000');
imap_search($stream, 'UNSEEN SINCE 20-Sep-2015 12:35:03');

Nothing seems to work. Any ideas if this can be done?

Upvotes: 12

Views: 24357

Answers (3)

Sunil Kumar
Sunil Kumar

Reputation: 6630

You cannot achieve that with "SINCE"

Another way to do this is to remember the UID of the latest message you've seen, and then search for messages above that: (thanks to @legoscia)

According to http://php.net/manual/en/function.imap-search.php

$emails = imap_search($inbox, "UID 1:*", SE_UID); 

is not valid, it is not working. Use

$emails = imap_fetch_overview($inbox, "$latest_uid:*", FT_UID); 

Here * refers to the latest mail UID. This will return an array of objects from which you can extract the UIDs of emails. You can use a loop to make an array of the UIDs separately. As answered at PHP imap_search UID SEARCH returns false

Upvotes: 4

legoscia
legoscia

Reputation: 41568

Looking at the definition of SINCE in RFC 3501:

  SINCE <date>
     Messages whose internal date (disregarding time and timezone)
     is within or later than the specified date.

And a date is defined as just a date, without a time:

date            = date-text / DQUOTE date-text DQUOTE

date-day        = 1*2DIGIT
                    ; Day of month

date-month      = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
                  "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"

date-text       = date-day "-" date-month "-" date-year

date-year       = 4DIGIT

So you can't use SINCE to search for messages based on a time more specific than a day.


Another way to do this is to remember the UID of the latest message you've seen, and then search for messages above that:

imap_search($stream, 'UID ' . $latest_uid . ':*', SE_UID);

The SE_UID option is required to make imap_search return UIDs instead of message sequence numbers.

To get the UID of the latest message in the first place, search for *, which represents the highest-numbered message in the mailbox:

imap_search($stream, 'UID *', SE_UID);

Upvotes: 27

Pablo Flores
Pablo Flores

Reputation: 1400

I don't think it's possible using php and the IMAP protocol. It seems that IMAP has a WITHIN Search Extension defined in rfc 5032, but it looks like php doesn't have this criteria yet. Also the SINCE criteria (and basically all the datetime criteria in the IMAP protocol) just ignores the time and timezone when you do a search operation. A workaround could be to get the emails with your current query, and then get the internal date and implementing the filter function with php datetime functions. Hope this helps. More info about IMAP: rfc 3501

Upvotes: 2

Related Questions