While programming a PHP application I came across one very weird problem with IMAP functions some days ago. I was struggling with email messages retrieved from an inbox over IMAP protocol. The basic functionality seemed to be working fine, but determining the read/unread flag caused me lot of headache. Although the inbox contained some read messages I kept getting all messages flagged as unread or rather seen/unseen, when referring to IMAP vocabulary. This anomaly was pretty annoying and took me hours and hours to solve. I started to investigate the problem by first ripping off the quite rich snippet I had already coded. The result was the simplest working procedure to ensure that the basic functionality really works. The first attempt to read the message flags had the following code:
$mailbox = imap_open($host, $username, $password);
for ($i = 1; $i <= imap_num_msg($mailbox); $i++) {
$headers = imap_fetchheader($mailbox, $i);
$info = imap_fetch_overview($mailbox, $i);
echo ($info[0]->seen == 1);
}
imap_close($mailbox);
The original loop included more code to work with the message headers first and then with other values, like flags and message body. This reduced sample opens the mailbox and loops through the messages in order to check whether the message has already been read or not. I kept two most important lines while I took away unnecessary ones in order to find out why the loop always indicated that the messages had unread (unseen) flag set. The mailbox had two messages. The first one was unread and the other one was read. The loop reported:
false
false
The expected result should have been: true and false as described. Before I ended up to this minimal loop I had reduced the code line by line to see, which program lines were actually causing the problem. My next attempt was to swap the lines:
$mailbox = imap_open($host, $username, $password);
for ($i = 1; $i <= imap_num_msg($mailbox); $i++) {
$info = imap_fetch_overview($mailbox, $i);
$headers = imap_fetchheader($mailbox, $i);
echo ($info[0]->seen == 1);
}
imap_close($mailbox);
To my surprise the loop now reported correctly:
true
false
So, there was anything wrong with neither mailbox settings nor my basic PHP function. It proved to be the order of the execution of the lines, which turned to be somehow wrong. Calling the imap_fetchheader() function before checking the flags seems to reset the message flag information. Reversing the execution of these lines gives the correct results. I was happy for now, but wanted to know, if there were any means to programmatically to cut the knot. I added imap_fetchbody() function between the lines and the loop, once again, printed the correct information although the two lines were in their original order.
$mailbox = imap_open($host, $username, $password);
for ($i = 1; $i <= imap_num_msg($mailbox); $i++) {
$headers = imap_fetchheader($mailbox, $i);
$body = imap_fetchbody($mailbox, $i, 1, FT_PEEK);
$info = imap_fetch_overview($mailbox, $i);
echo ($info[0]->seen == 1);
}
imap_close($mailbox);
Strange enough, retrieving the message body overrides the problematic effect of fetching the header before checking the message flags. I coul’dnt find out the root cause to this anomaly, but was happy to get the code finally working. I simply moved the imap_fetch_overview() function after the imap_fetchbody() and that was all.
Final words
Investigating a strange behavior in an application may take lot of time. In such cases one way to face the problem is to get the program work at the lowest level. After the basic code works fine then it is time to add more functionality line by line to see it the contraption still works as expected. My case was one of the oddest peculiarities for awhile. The testing server was running PHP Version 5.2.11 and IMAP c-Client Version 2007e, but I cannot say, if these versions had anything to do with the message flag jumble. The usually so ever solving Google search gave me no answers and I was forced to stay with this exact order of execution and now hope I could help someone who is struggling with similar specialties.