PHP provides a great deal of functions to operate with the IMAP protocol, but implementing them isn’t always so straightforward. For example, how to best mark multiple messages as read or unread, move them to a different folder or mark them as deleted without running into a situation where some of them “return” to your inbox next time you sync to the account or worse, you end up marking as deleted other messages you did not intend to. This is actually a real-life issue we ran into at work.
Given a sequence of messages, you have a message number and a unique UID that you can use to mark messages as deleted, read, unread, etc. using functions such as imap_mail_move() and imap_delete(). The problem is, the sequential number and the UID are only good for the current session. Also, every time you call imap_mail_move() for one message in the list, the whole sequence rearranges, which means you can no longer trust you have the right numbers or UIDs for the messages you wish to move.
A solution we found was to send the function a list of the messages we wanted to move in one single call, instead of calling the function for each one of them separately. We also found that using the UIDs works best than using the sequential numbers. In fact, using the message number does not even work for GMail, for instance.
Call the IMAP functions using the UIDs in this fashion:
imap_mail_move($imap_stream, "{$msglist}", $mailbox, CP_UID); imap_delete($imap_stream, "{$msglist}", FT_UID); imap_setflag_full($imap_stream, "{$msglist}", "\\Seen", ST_UID); imap_clearflag_full($imap_stream, "{$msglist}", "\\Seen", ST_UID);
Where $msglist is a comma separated list of UIDs for the messages you wish to move and the constants CP_UID, FT_UID and ST_UID indicate that you are passing to the function a list of UIDs instead of message numbers. Don’t forget to call imap_expunge afterwards.