X-Git-Url: https://vcs.fsf.org/?p=squirrelmail.git;a=blobdiff_plain;f=functions%2Fimap_messages.php;h=74a2448542e48d22739432351bd13cccfae71f4a;hp=cb2cf325c13f5caf35cf41ace1c2ca8ecc032a71;hb=e49ea4ad7de6429c8386860a6a74375f99b37228;hpb=598294a727a2789b7c562ee7083da703c8bb0628 diff --git a/functions/imap_messages.php b/functions/imap_messages.php index cb2cf325..74a24485 100755 --- a/functions/imap_messages.php +++ b/functions/imap_messages.php @@ -3,12 +3,11 @@ /** * imap_messages.php * - * Copyright (c) 1999-2005 The SquirrelMail Project Team - * Licensed under the GNU GPL. For full terms see the file COPYING. - * * This implements functions that manipulate messages * NOTE: Quite a few functions in this file are obsolete * + * @copyright © 1999-2007 The SquirrelMail Project Team + * @license http://opensource.org/licenses/gpl-license.php GNU Public License * @version $Id$ * @package squirrelmail * @subpackage imap @@ -20,11 +19,12 @@ * @param int $imap_stream The resource ID for the IMAP socket * @param string $id The list of messages to copy * @param string $mailbox The destination to copy to - * @return bool + * @param bool $handle_errors Show error messages in case of a NO, BAD or BYE response + * @return bool If the copy completed without errors */ -function sqimap_msgs_list_copy($imap_stream, $id, $mailbox) { +function sqimap_msgs_list_copy($imap_stream, $id, $mailbox, $handle_errors = true) { $msgs_id = sqimap_message_list_squisher($id); - $read = sqimap_run_command ($imap_stream, "COPY $msgs_id " . sqimap_encode_mailbox_name($mailbox), true, $response, $message, TRUE); + $read = sqimap_run_command ($imap_stream, "COPY $msgs_id " . sqimap_encode_mailbox_name($mailbox), $handle_errors, $response, $message, TRUE); if ($response == 'OK') { return true; } else { @@ -38,11 +38,17 @@ function sqimap_msgs_list_copy($imap_stream, $id, $mailbox) { * @param int $imap_stream The resource ID for the IMAP socket * @param string $id The list of messages to move * @param string $mailbox The destination to move to - * @return void + * @param bool $handle_errors Show error messages in case of a NO, BAD or BYE response + * @param string $source_mailbox (since 1.5.1) name of source mailbox. It is used to + * validate that target mailbox != source mailbox. + * @return bool If the move completed without errors */ -function sqimap_msgs_list_move($imap_stream, $id, $mailbox) { +function sqimap_msgs_list_move($imap_stream, $id, $mailbox, $handle_errors = true, $source_mailbox = false) { + if ($source_mailbox!==false && $source_mailbox==$mailbox) { + return false; + } $msgs_id = sqimap_message_list_squisher($id); - if (sqimap_msgs_list_copy ($imap_stream, $id, $mailbox)) { + if (sqimap_msgs_list_copy ($imap_stream, $id, $mailbox, $handle_errors)) { return sqimap_toggle_flag($imap_stream, $id, '\\Deleted', true, true); } else { return false; @@ -55,23 +61,22 @@ function sqimap_msgs_list_move($imap_stream, $id, $mailbox) { * @param resource imap connection * @param string $mailbox mailbox, used for checking if it concerns the trash_folder * @param array $id list with uid's - * @param bool $bypass_trash skip copy to trash + * @param bool $bypass_trash (since 1.5.0) skip copy to trash * @return array $aMessageList array with messages containing the new flags and UID @see parseFetch + * @since 1.4.0 */ function sqimap_msgs_list_delete($imap_stream, $mailbox, $id, $bypass_trash=false) { - // FIX ME, remove globals by introducing an associative array with properties - // as 4th argument as replacement for the bypass_trash var + // FIXME: Remove globals by introducing an associative array with properties as 4th argument as replacement for the $bypass_trash variable. global $move_to_trash, $trash_folder; - $bRes = true; if (($move_to_trash == true) && ($bypass_trash != true) && (sqimap_mailbox_exists($imap_stream, $trash_folder) && ($mailbox != $trash_folder)) ) { - $bRes = sqimap_msgs_list_copy ($imap_stream, $id, $trash_folder); - } - if ($bRes) { - return sqimap_toggle_flag($imap_stream, $id, '\\Deleted', true, true); - } else { - return false; + /** + * turn off internal error handling (fourth argument = false) and + * ignore copy to trash errors (allows to delete messages when overquota) + */ + sqimap_msgs_list_copy ($imap_stream, $id, $trash_folder, false); } + return sqimap_toggle_flag($imap_stream, $id, '\\Deleted', true, true); } @@ -87,38 +92,59 @@ function sqimap_msgs_list_delete($imap_stream, $mailbox, $id, $bypass_trash=fals function sqimap_toggle_flag($imap_stream, $id, $flag, $set, $handle_errors) { $msgs_id = sqimap_message_list_squisher($id); $set_string = ($set ? '+' : '-'); + + for ($i=0; $i $v) + if (isset($msgs[$k][strtolower($sSortField)])) + $msgs[$k][strtoupper($sSortField)] = $msgs[$k][strtolower($sSortField)]; + $aUid = array(); $walk = false; switch ($sSortField) { @@ -204,9 +248,9 @@ function get_squirrel_sort($imap_stream, $sSortField, $reverse = false, $aUid = $sPersonal = (isset($addr[SQM_ADDR_PERSONAL]) && $addr[SQM_ADDR_PERSONAL]) ? $addr[SQM_ADDR_PERSONAL] : ""; $sEmail = ($addr[SQM_ADDR_HOST]) ? - $addr[SQM_ADDR_HOST] . "@".$addr[SQM_ADDR_HOST] : + $addr[SQM_ADDR_MAILBOX] . "@".$addr[SQM_ADDR_HOST] : $addr[SQM_ADDR_HOST]; - $v[$f] = ($sPersonal) ? decodeHeader($sPersonal):$sEmail;'),$sSortField); + $v[$f] = ($sPersonal) ? decodeHeader($sPersonal, true, false):$sEmail;'),$sSortField); $walk = true; } // nobreak @@ -214,9 +258,9 @@ function get_squirrel_sort($imap_stream, $sSortField, $reverse = false, $aUid = if(!$walk) { array_walk($msgs, create_function('&$v,&$k,$f', '$v[$f] = (isset($v[$f])) ? $v[$f] : ""; - $v[$f] = strtolower(decodeHeader(trim($v[$f]))); - $v[$f] = (preg_match("/^(vedr|sv|re|aw|\[\w\]):\s*(.*)$/si", $v[$f], $matches)) ? - $matches[2] : $v[$f];'),$sSortField); + $v[$f] = strtolower(decodeHeader(trim($v[$f]), true, false)); + $v[$f] = (preg_match("/^(?:(?:vedr|sv|re|aw|fw|fwd|\[\w\]):\s*)*\s*(.*)$/si", $v[$f], $matches)) ? + $matches[1] : $v[$f];'),$sSortField); $walk = true; } foreach ($msgs as $item) { @@ -263,17 +307,72 @@ function get_squirrel_sort($imap_stream, $sSortField, $reverse = false, $aUid = return $aUid; } - /** - * Returns an indent array for printMessageinfo() - * This represents the amount of indent needed (value), - * for this message number (key) + * Returns an array with each element as a string representing one + * message-thread as returned by the IMAP server. + * @param resource $imap_stream IMAP socket connection + * @param string $search optional search string + * @return array + * @link http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-13.txt */ +function get_thread_sort($imap_stream, $search='ALL') { + global $sort_by_ref, $default_charset; + + if ($sort_by_ref == 1) { + $sort_type = 'REFERENCES'; + } else { + $sort_type = 'ORDEREDSUBJECT'; + } + $query = "THREAD $sort_type ".strtoupper($default_charset)." $search"; + + // TODO use sqimap_run_command_list as we do in get_server_sort() + $sRead = sqimap_run_command ($imap_stream, $query, false, $response, $message, TRUE); + /* fallback to default charset */ + if ($response == 'NO') { + if (strpos($message,'BADCHARSET') !== false || + strpos($message,'character') !== false) { + sqm_trigger_imap_error('SQM_IMAP_BADCHARSET',$query, $response, $message); + $query = "THREAD $sort_type US-ASCII $search"; + $sRead = sqimap_run_command ($imap_stream, $query, true, $response, $message, TRUE); + } else { + sqm_trigger_imap_error('SQM_IMAP_ERROR',$query, $response, $message); + } + } elseif ($response == 'BAD') { + sqm_trigger_imap_error('SQM_IMAP_NO_THREAD',$query, $response, $message); + } + $sThreadResponse = ''; + if (isset($sRead[0])) { + for ($i=0,$iCnt=count($sRead);$i<$iCnt;++$i) { + if (preg_match("/^\* THREAD (.+)$/", $sRead[$i], $aMatch)) { + $sThreadResponse = trim($aMatch[1]); + break; + } + } + } + unset($sRead); + + if ($response !== 'OK') { + return false; + } + + /* Example response + * S: * THREAD (2)(3 6 (4 23)(44 7 96)) + * -- 2 + * + * -- 3 + * \-- 6 + * |-- 4 + * | \-- 23 + * | + * \-- 44 + * \-- 7 + * \-- 96 + */ /* * Notes for future work: * indent_array should contain: indent_level, parent and flags, - * sibling notes .. + * sibling nodes .. * To achieve that we need to define the following flags: * 0: hasnochildren * 1: haschildren @@ -290,185 +389,68 @@ function get_squirrel_sort($imap_stream, $sSortField, $reverse = false, $aUid = * \-4 par = 3, level = 2, flag = 1 + 2 + 4 = 7 (haschildren, isfirst, islast) * \-5 par = 4, level = 3, flag = 0 + 2 + 4 = 6 (hasnochildren, isfirst, islast) */ -function get_parent_level($thread_new) { - $parent = ''; - $child = ''; - $cutoff = 0; - - /* - * loop through the threads and take unwanted characters out - * of the thread string then chop it up - */ - for ($i=0;$i (540) - * [1] => (1386) - * [2] => (1599 759 959 37) - * [3] => (492 1787) - * [4] => ((933)(1891)) - * [5] => (1030 (1497)(845)(1637)) - */ - for ($i=0,$iCnt=count($thread_temp);$i<$iCnt;$i++) { - if ($thread_temp[$i] != ')' && $thread_temp[$i] != '(') { - $thread_new[$k] = $thread_new[$k] . $thread_temp[$i]; - } elseif ($thread_temp[$i] == '(') { - $thread_new[$k] .= $thread_temp[$i]; - $counter++; - } elseif ($thread_temp[$i] == ')') { - if ($counter > 1) { - $thread_new[$k] .= $thread_temp[$i]; - $counter = $counter - 1; - } else { - $thread_new[$k] .= $thread_temp[$i]; - $k++; - $thread_new[$k] = ""; - $counter = $counter - 1; + $l = 0; + $aUidThread = array(); + $aIndent = array(); + $aUidSubThread = array(); + $aDepthStack = array(); + $sUid = ''; + + if ($sThreadResponse) { + for ($i=0,$iCnt = strlen($sThreadResponse);$i<$iCnt;++$i) { + $cChar = $sThreadResponse{$i}; + switch ($cChar) { + case '(': // new sub thread + // correction for a subthread of a thread with no parents in thread + if (!count($aUidSubThread) && $j > 0) { + --$l; + } + $aDepthStack[$j] = $l; + ++$j; + break; + case ')': // close sub thread + if($sUid !== '') { + $aUidSubThread[] = $sUid; + $aIndent[$sUid] = $j + $l - 1; + ++$l; + $sUid = ''; + } + --$j; + if ($j === 0) { + // show message that starts the thread first. + $aUidSubThread = array_reverse($aUidSubThread); + // do not use array_merge because it's extremely slow and is causing timeouts + foreach ($aUidSubThread as $iUid) { + $aUidThread[] = $iUid; + } + $aUidSubThread = array(); + $l = 0; + $aDepthStack = array(); + } else { + $l = $aDepthStack[$j]; + } + break; + case ' ': // new child + if ($sUid !== '') { + $aUidSubThread[] = $sUid; + $aIndent[$sUid] = $j + $l - 1; + ++$l; + $sUid = ''; + } + break; + default: // part of UID + $sUid .= $cChar; + break; } } } - - $thread_new = array_reverse($thread_new); - /* place the threads after each other in one string */ - $thread_list = implode(" ", $thread_new); - $thread_list = str_replace("(", " ", $thread_list); - $thread_list = str_replace(")", " ", $thread_list); - $thread_list = preg_split("/\s/", $thread_list, -1, PREG_SPLIT_NO_EMPTY); - $server_sort_array = $thread_list; - - $indent_array = get_parent_level ($thread_new); - return array($thread_list,$indent_array); + unset($sThreadResponse); + // show newest threads first + $aUidThread = array_reverse($aUidThread); + return array($aUidThread,$aIndent); } @@ -478,20 +460,6 @@ function elapsedTime($start) { return $timepassed; } - -function parsePriority($value) { - $value = strtolower(array_shift(split('/\w/',trim($value)))); - if ( is_numeric($value) ) { - return $value; - } - if ( $value == 'urgent' || $value == 'high' ) { - return 1; - } elseif ( $value == 'non-urgent' || $value == 'low' ) { - return 5; - } - return 3; -} - /** * Parses a string in an imap response. String starts with " or { which means it * can handle double quoted strings and literal strings @@ -566,18 +534,30 @@ function parseArray($read,&$i) { /** * Retrieves a list with headers, flags, size or internaldate from the imap server - * @param resource $imap_stream imap connection - * @param array $msg_list array with id's to create a msgs set from - * @param array $aHeaderFields requested header fields - * @param array $aFetchItems requested other fetch items like FLAGS, RFC822.SIZE - * @return array $aMessages associative array with messages. Key is the UID, value is an associative array + * + * WARNING: function is not portable between SquirrelMail 1.2.x, 1.4.x and 1.5.x. + * Output format, third argument and $msg_list array format requirements differ. + * @param stream $imap_stream imap connection + * @param array $msg_list array with id's to create a msgs set from + * @param array $aHeaderFields (since 1.5.0) requested header fields + * @param array $aFetchItems (since 1.5.0) requested other fetch items like FLAGS, RFC822.SIZE + * @return array $aMessages associative array with messages. Key is the UID, value is an associative array + * @since 1.1.3 */ function sqimap_get_small_header_list($imap_stream, $msg_list, - $aHeaderFields = array('Date', 'To', 'Cc', 'From', 'Subject', 'X-Priority', 'Importance', 'Priority', 'Content-Type'), + $aHeaderFields = array('Date', 'To', 'Cc', 'From', 'Subject', 'X-Priority', 'Content-Type'), $aFetchItems = array('FLAGS', 'RFC822.SIZE', 'INTERNALDATE')) { $aMessageList = array(); + /** + * Catch other priority headers as well + */ + if (in_array('X-Priority',$aHeaderFields,true)) { + $aHeaderFields[] = 'Importance'; + $aHeaderFields[] = 'Priority'; + } + $bUidFetch = ! in_array('UID', $aFetchItems, true); /* Get the small headers for each message in $msg_list */ @@ -626,23 +606,24 @@ function sqimap_get_small_header_list($imap_stream, $msg_list, * @return array $aMessageList associative array with messages. Key is the UID, value is an associative array * @author Marc Groot Koerkamp */ -function parseFetch($aResponse,$aMessageList = array()) { - foreach ($aResponse as $r) { - $msg = array(); - // use unset because we do isset below - $read = implode('',$r); +function parseFetch(&$aResponse,$aMessageList = array()) { + for ($j=0,$iCnt=count($aResponse);$j<$iCnt;++$j) { + $aMsg = array(); + $read = implode('',$aResponse[$j]); + // free up memmory + unset($aResponse[$j]); /* unset does not reindex the array. the for loop is safe */ /* - * #idFETCH( - */ + * #idFETCH( + */ /* extract the message id */ - $i_space = strpos($read,' ',2); - $id = substr($read,2,$i_space-2); - $msg['ID'] = $id; + $i_space = strpos($read,' ',2);/* position 2ed */ + $id = substr($read,2/* skip "*" */,$i_space -2); + $aMsg['ID'] = $id; $fetch = substr($read,$i_space+1,5); if (!is_numeric($id) && $fetch !== 'FETCH') { - $msg['ERROR'] = $read; // htmlspecialchars should be done just before display. this is backend code + $aMsg['ERROR'] = $read; // htmlspecialchars should be done just before display. this is backend code break; } $i = strpos($read,'(',$i_space+5); @@ -656,6 +637,9 @@ function parseFetch($aResponse,$aMessageList = array()) { $i = strpos($read,' '); $arg = substr($read,0,$i); ++$i; + /* + * use allcaps for imap items and lowcaps for headers as key for the $aMsg array + */ switch ($arg) { case 'UID': @@ -678,7 +662,7 @@ function parseFetch($aResponse,$aMessageList = array()) { $flag = strtolower($flag); $aFlags[$flag] = true; } - $msg['FLAGS'] = $aFlags; + $aMsg['FLAGS'] = $aFlags; break; case 'RFC822.SIZE': $i_pos = strpos($read,' ',$i); @@ -686,93 +670,101 @@ function parseFetch($aResponse,$aMessageList = array()) { $i_pos = strpos($read,')',$i); } if ($i_pos) { - $msg['SIZE'] = substr($read,$i,$i_pos-$i); + $aMsg['SIZE'] = substr($read,$i,$i_pos-$i); $i = $i_pos+1; } else { break 3; } - break; case 'ENVELOPE': - break; // to be implemented, moving imap code out of the nessages class - sqimap_parse_address($read,$i,$msg); - break; // to be implemented, moving imap code out of the nessages class + // sqimap_parse_address($read,$i,$aMsg); + break; // to be implemented, moving imap code out of the Message class case 'BODYSTRUCTURE': - break; + break; // to be implemented, moving imap code out of the Message class case 'INTERNALDATE': - $msg['INTERNALDATE'] = trim(str_replace(' ', ' ',parseString($read,$i))); + $aMsg['INTERNALDATE'] = trim(str_replace(' ', ' ',parseString($read,$i))); break; case 'BODY.PEEK[HEADER.FIELDS': case 'BODY[HEADER.FIELDS': - $i = strpos($read,'{',$i); + $i = strpos($read,'{',$i); // header is always returned as literal because it contain \n characters $header = parseString($read,$i); if ($header === false) break 2; /* First we replace all \r\n by \n, and unfold the header */ $hdr = trim(str_replace(array("\r\n", "\n\t", "\n "),array("\n", ' ', ' '), $header)); - /* Now we can make a new header array with */ - /* each element representing a headerline */ - $hdr = explode("\n" , $hdr); + /* Now we can make a new header array with + each element representing a headerline */ + $aHdr = explode("\n" , $hdr); $aReceived = array(); - foreach ($hdr as $line) { + foreach ($aHdr as $line) { $pos = strpos($line, ':'); if ($pos > 0) { $field = strtolower(substr($line, 0, $pos)); if (!strstr($field,' ')) { /* valid field */ $value = trim(substr($line, $pos+1)); - switch($field) - { - case 'to': $msg['TO'] = $value; break; - case 'cc': $msg['CC'] = $value; break; - case 'from': $msg['FROM'] = $value; break; - case 'date': - $msg['DATE'] = str_replace(' ', ' ', $value); - break; - case 'x-priority': - case 'importance': - case 'priority': - $msg['PRIORITY'] = parsePriority($value); break; - case 'subject': $msg['SUBJECT'] = $value; break; - case 'content-type': - $type = $value; - if ($pos = strpos($type, ";")) { - $type = substr($type, 0, $pos); - } - $type = explode("/", $type); - if(!is_array($type) || count($type) < 2) { - $msg['TYPE0'] = 'text'; - $msg['TYPE1'] = 'plain'; - } else { - $msg['TYPE0'] = strtolower($type[0]); - $msg['TYPE1'] = strtolower($type[1]); - } - break; - case 'received': - $aReceived[] = $value; - break; - default: break; + switch($field) { + case 'date': + $aMsg['date'] = trim(str_replace(' ', ' ', $value)); + break; + case 'x-priority': $aMsg['x-priority'] = ($value) ? (int) $value{0} : 3; break; + case 'priority': + case 'importance': + // duplicate code with Rfc822Header.cls:parsePriority() + if (!isset($aMsg['x-priority'])) { + $aPrio = preg_split('/\s/',trim($value)); + $sPrio = strtolower(array_shift($aPrio)); + if (is_numeric($sPrio)) { + $iPrio = (int) $sPrio; + } elseif ( $sPrio == 'non-urgent' || $sPrio == 'low' ) { + $iPrio = 5; + } elseif ( $sPrio == 'urgent' || $sPrio == 'high' ) { + $iPrio = 1; + } else { + // default is normal priority + $iPrio = 3; + } + $aMsg['x-priority'] = $iPrio; + } + break; + case 'content-type': + $type = $value; + if ($pos = strpos($type, ";")) { + $type = substr($type, 0, $pos); + } + $type = explode("/", $type); + if(!is_array($type) || count($type) < 2) { + $aMsg['content-type'] = array('text','plain'); + } else { + $aMsg['content-type'] = array(strtolower($type[0]),strtolower($type[1])); + } + break; + case 'received': + $aMsg['received'][] = $value; + break; + default: + $aMsg[$field] = $value; + break; } } } } - if (count($aReceived)) { - $msg['RECEIVED'] = $aReceived; - } break; default: ++$i; break; } } - $msgi ="$unique_id"; - $msg['UID'] = $unique_id; - - $aMessageList[$msgi] = $msg; - ++$msgi; + if (!empty($unique_id)) { + $msgi = "$unique_id"; + $aMsg['UID'] = $unique_id; + } else { + $msgi = ''; + } + $aMessageList[$msgi] = $aMsg; + $aResponse[$j] = NULL; } return $aMessageList; } - /** * Work in process * @private @@ -899,9 +891,10 @@ function sqimap_parse_address($read, &$i) { * @param resource $imap_stream imap connection * @param integer $id uid of the message * @param string $mailbox used for error handling, can be removed because we should return an error code and generate the message elsewhere - * @return Message Message object + * @param int $hide Indicates whether or not to hide any errors: 0 = don't hide, 1 = hide (just exit), 2 = hide (return FALSE), 3 = hide (return error string) (OPTIONAL; default don't hide) + * @return mixed Message object or FALSE/error string if error occurred and $hide is set to 2/3 */ -function sqimap_get_message($imap_stream, $id, $mailbox) { +function sqimap_get_message($imap_stream, $id, $mailbox, $hide=0) { // typecast to int to prohibit 1:* msgs sets $id = (int) $id; $flags = array(); @@ -909,17 +902,25 @@ function sqimap_get_message($imap_stream, $id, $mailbox) { if ($read) { if (preg_match('/.+FLAGS\s\((.*)\)\s/AUi',$read[0],$regs)) { if (trim($regs[1])) { - $flags = preg_split('/ /', $regs[1],-1,'PREG_SPLIT_NI_EMPTY'); + $flags = preg_split('/ /', $regs[1],-1,PREG_SPLIT_NO_EMPTY); } } } else { + + if ($hide == 1) exit; + if ($hide == 2) return FALSE; + /* the message was not found, maybe the mailbox was modified? */ - global $sort, $startMessage, $color; + global $sort, $startMessage; + + $errmessage = _("The server couldn't find the message you requested."); + + if ($hide == 3) return $errmessage; + + $errmessage .= '

'._("Most probably your message list was out of date and the message has been moved away or deleted (perhaps by another program accessing the same mailbox)."); - $errmessage = _("The server couldn't find the message you requested.") . - '

'._("Most probably your message list was out of date and the message has been moved away or deleted (perhaps by another program accessing the same mailbox)."); /* this will include a link back to the message list */ - error_message($errmessage, $mailbox, $sort, (int) $startMessage, $color); + error_message($errmessage, $mailbox, $sort, (int) $startMessage); exit; } $bodystructure = implode('',$read); @@ -928,48 +929,39 @@ function sqimap_get_message($imap_stream, $id, $mailbox) { $rfc822_header = new Rfc822Header(); $rfc822_header->parseHeader($read); $msg->rfc822_header = $rfc822_header; - return $msg; -} - -/** - * Deprecated !!!!!!! DO NOT USE THIS, use sqimap_msgs_list_copy instead - */ -function sqimap_messages_copy($imap_stream, $start, $end, $mailbox) { - $read = sqimap_run_command ($imap_stream, "COPY $start:$end " . sqimap_encode_mailbox_name($mailbox), true, $response, $message, TRUE); -} + parse_message_entities($msg, $id, $imap_stream); + return $msg; + } /** - * Deprecated !!!!!!! DO NOT USE THIS, use sqimap_msgs_list_delete instead + * Recursively parse embedded messages (if any) in the given + * message, building correct rfc822 headers for each one + * + * @param object $msg The message object to scan for attached messages + * NOTE: this is passed by reference! Changes made + * within will affect the caller's copy of $msg! + * @param int $id The top-level message UID on the IMAP server, even + * if the $msg being passed in is only an attached entity + * thereof. + * @param resource $imap_stream A live connection to the IMAP server. + * + * @return void + * + * @since 1.5.2 + * */ -function sqimap_messages_delete($imap_stream, $start, $end, $mailbox, $bypass_trash=false) { - global $move_to_trash, $trash_folder; - - if (($move_to_trash == true) && ($bypass_trash != true) && - (sqimap_mailbox_exists($imap_stream, $trash_folder) && ($mailbox != $trash_folder))) { - sqimap_messages_copy ($imap_stream, $start, $end, $trash_folder); +function parse_message_entities(&$msg, $id, $imap_stream) { + if (!empty($msg->entities)) foreach ($msg->entities as $i => $entity) { + if (is_object($entity) && strtolower(get_class($entity)) == 'message') { + if (!empty($entity->rfc822_header)) { + $read = sqimap_run_command($imap_stream, "FETCH $id BODY[". $entity->entity_id .".HEADER]", true, $response, $message, TRUE); + $rfc822_header = new Rfc822Header(); + $rfc822_header->parseHeader($read); + $msg->entities[$i]->rfc822_header = $rfc822_header; + } + parse_message_entities($msg->entities[$i], $id, $imap_stream); + } } - sqimap_messages_flag ($imap_stream, $start, $end, "Deleted", true); } - - -/** - * Deprecated !!!!!!! DO NOT USE THIS, use sqimap_toggle_flag instead - * Set a flag on the provided uid list - * @param resource imap connection - */ -function sqimap_messages_flag($imap_stream, $start, $end, $flag, $handle_errors) { - $read = sqimap_run_command ($imap_stream, "STORE $start:$end +FLAGS (\\$flag)", $handle_errors, $response, $message, TRUE); -} - - -/** - * @deprecated - */ -function sqimap_get_small_header($imap_stream, $id, $sent) { - $res = sqimap_get_small_header_list($imap_stream, $id, $sent); - return $res[0]; -} - -?> \ No newline at end of file