javanile / php-imap2

PHP IMAP with OAUTH2
https://php-imap2.javanile.org/
GNU General Public License v3.0
48 stars 28 forks source link

Message getting lost during iteration of mailbox if message moved #34

Open cjwnz opened 1 year ago

cjwnz commented 1 year ago

Please see example code below. I have found that I'm losing messages in the loop if the message is moved to a subfolder during processing. For example, let's say I have 3 messages to process. After message 1 is processed and moved to a subfolder then message 3 becomes the second message to be processed and message 2 is lost. This used to work fine before moving to php-imap2 functions. After processing message 2 will still be in the INBOX folder - its just not being picked up in the loop.

// get number of messages
$count = imap2_num_msg($mbox);

for ($msgno = 1; $msgno  <= $count; $msgno++)  {

  // get header
  $header = imap2_headerinfo($mbox, $msgno);

  // process message
  process_mesage($mbox,$msgno);

  // move message to subfolder
  imap2_mail_move($mbox, $msgno, "INBOX.PROCESSED");

}
cjwnz commented 1 year ago

UPDATE

If I use imap2_mail_copy() followed by imap2_delete() INSTEAD of imap2_mail_move() it works as expected. So the bug must be in imap2_mail_move() function.

Cheers

pjio commented 1 year ago

~Have you tried to move the messages in reverse? (for ($msgno = $count; $msgno >= 1; $msgno--) { ... }. After move or copy + delete + expunge the numbers of the mails change (I assume, copy + delete without expunge works because the number is unchanged until expunge.~

src/Roundcube/ImapClient.php in line 2428 calls expunge which likely causes the different behaviour from imap_mail_move()

cjwnz commented 1 year ago

great - well spotted. so for now I have a workaround but will it be fixed in new release?

IZSkiSurfer commented 1 year ago

Afaik this is not really a bug rather a lucky surprise that it works with the imap_ lib. You are working here with numbers rather than IDs. According to the official PHP doc the mail numbers may change with every imap command.

Instead of using imap(2)_headerinfo which only works with msgno you should use e.g. $hdr = imap2_rfc822_parse_headers(imap2_fetchheader()) and work with message IDs as those don't change.

To get a list of all UIDs you could use e.g. imap2_fetch_overview

IZSkiSurfer commented 1 year ago

~Have you tried to move the messages in reverse? (for ($msgno = $count; $msgno >= 1; $msgno--) { ... }. After move or copy + delete + expunge the numbers of the mails change (I assume, copy + delete without expunge works because the number is unchanged until expunge.~

src/Roundcube/ImapClient.php in line 2428 calls expunge which likely causes the different behaviour from imap_mail_move()

I guess you could simply replace the client->move call in Mail class by client->copy and add the expunge flag afterwards..