imap_thread() returns threads, but are confined to the current open mailbox you defined in imap_open(). This is not useful for, lets say, getting full threads ( from "Sent Messages" and "Inbox" [took me a day to figure this out]).
If you compare threads on Outlook vs gmail.com you will find that Outlook determines threads by subject title, not actual parent > child relationships.
Gmail however, seems to get threads right, but does not include mail you send using their web interface in {imap.google.com:993/imap/ssl}Sent Messages . What this means is that threads using php imap won't be perfect for gmail.
If you send mail using Outlook (or any mail client), gmail.com does put it in their "Sent Mail".
So all in all, threads for PHP imap are not perfect. But I blame the imap specifications (DEAR IMAP GUYS, please add better uids and parent ids. thx Chris) more than PHP
So I created the Outlook method for threading (comparing subjects) below:
<?php
$imap = imap_open('{imap.gmail.com:993/imap/ssl}INBOX', 'youremail@gmail.com', 'yourpassword');
$subject = 'Item b';
$threads = array();
$subject = trim(preg_replace("/Re\:|re\:|RE\:|Fwd\:|fwd\:|FWD\:/i", '', $subject));
$results = imap_search($imap, 'SUBJECT "'.$subject.'"', SE_UID);
if(is_array($results)) {
$emails = imap_fetch_overview($imap, implode(',', $results), FT_UID);
foreach ($emails as $email) {
$threads[strtotime($email->date)] = $email;
}
}
imap_reopen($imap, '{imap.gmail.com:993/imap/ssl}Sent Messages');
$results = imap_search($imap, 'SUBJECT "'.$subject.'"', SE_UID);
if(is_array($results)) {
$emails = imap_fetch_overview($imap, implode(',', $results), FT_UID);
foreach ($emails as $email) {
$threads[strtotime($email->date)] = $email;
}
}
ksort($threads);
echo '<pre>'.print_r($threads, true).'</pre>';
exit;
?>
so if you are going to use imap_thread() for something useful. This is probably the most optimal way I can think of:
<?php
$imap = imap_open('{imap.gmail.com:993/imap/ssl}INBOX', 'youremail@gmail.com', 'password');
$threads = $rootValues = array();
$thread = imap_thread($imap);
$root = 0;
foreach ($thread as $i => $messageId) {
list($sequence, $type) = explode('.', $i);
if($type != 'num' || $messageId == 0
|| ($root == 0 && $thread[$sequence.'.next'] == 0)
|| isset($rootValues[$messageId])) {
continue;
}
if($root == 0) {
$root = $messageId;
}
$rootValues[$messageId] = $root;
if($thread[$sequence.'.next'] == 0) {
$root = 0;
}
}
$emails = imap_fetch_overview($imap, implode(',', array_keys($rootValues)));
foreach ($emails as $email) {
$root = $rootValues[$email->msgno];
$threads[$root][] = $email;
}
echo '<pre>'.print_r($threads, true).'</pre>';
imap_close($imap);
exit;
?>