function walkTreeInPreOrderEmptyTrash($index, $imap_stream, $tree) { global $trash_folder; if ($tree[$index]['doIHaveChildren']) { for ($j = 0; $j < count($tree[$index]['subNodes']); $j++) { walkTreeInPreOrderEmptyTrash($tree[$index]['subNodes'][$j], $imap_stream, $tree); } if ($tree[$index]['value'] != $trash_folder) { sqimap_mailbox_delete($imap_stream, $tree[$index]['value']); } else { $mbx_response = sqimap_mailbox_select($imap_stream, $trash_folder); if ($mbx_response['EXISTS'] > 0) { sqimap_messages_flag($imap_stream, 1, '*', 'Deleted', true); sqimap_mailbox_expunge($imap_stream, $trash_folder, true); } } } else { if ($tree[$index]['value'] != $trash_folder) { sqimap_mailbox_delete($imap_stream, $tree[$index]['value']); } else { $mbx_response = sqimap_mailbox_select($imap_stream, $trash_folder); if ($mbx_response['EXISTS'] > 0) { sqimap_messages_flag($imap_stream, 1, '*', 'Deleted', true); sqimap_mailbox_expunge($imap_stream, $trash_folder, true); } } } }
/** * FIXME: Undocumented function * @access private */ function spam_filters($imap_stream) { global $data_dir, $username, $uid_support; global $SpamFilters_YourHop; global $SpamFilters_DNScache; global $SpamFilters_SharedCache; global $SpamFilters_BulkQuery; $filters_spam_scan = getPref($data_dir, $username, 'filters_spam_scan'); $filters_spam_folder = getPref($data_dir, $username, 'filters_spam_folder'); $filters = load_spam_filters(); if ($SpamFilters_SharedCache) { filters_LoadCache(); } $run = false; foreach ($filters as $Key => $Value) { if ($Value['enabled']) { $run = true; break; } } // short-circuit if (!$run) { return; } sqimap_mailbox_select($imap_stream, 'INBOX'); $search_array = array(); if ($filters_spam_scan == 'new') { $read = sqimap_run_command($imap_stream, 'SEARCH UNSEEN', true, $response, $message, $uid_support); if (isset($read[0])) { for ($i = 0, $iCnt = count($read); $i < $iCnt; ++$i) { if (preg_match("/^\\* SEARCH (.+)\$/", $read[$i], $regs)) { $search_array = explode(' ', trim($regs[1])); break; } } } } if ($filters_spam_scan == 'new' && count($search_array)) { $msg_str = sqimap_message_list_squisher($search_array); $imap_query = 'FETCH ' . $msg_str . ' (FLAGS BODY.PEEK[HEADER.FIELDS (RECEIVED)])'; } else { if ($filters_spam_scan != 'new') { $imap_query = 'FETCH 1:* (FLAGS BODY.PEEK[HEADER.FIELDS (RECEIVED)])'; } else { return; } } $read = sqimap_run_command_list($imap_stream, $imap_query, true, $response, $message, $uid_support); if (isset($response) && $response != 'OK') { return; } $messages = parseFetch($read); $bulkquery = strlen($SpamFilters_BulkQuery) > 0 ? true : false; $aSpamIds = array(); foreach ($messages as $id => $message) { if (isset($message['UID'])) { $MsgNum = $message['UID']; } else { $MsgNum = $id; } if (isset($message['received'])) { foreach ($message['received'] as $received) { if (is_int(strpos($received, $SpamFilters_YourHop))) { if (preg_match('/([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})/', $received, $matches)) { $IsSpam = false; if (filters_spam_check_site($matches[1], $matches[2], $matches[3], $matches[4], $filters)) { $aSpamIds[] = $MsgNum; $IsSpam = true; } if ($bulkquery) { array_shift($matches); $IP = explode('.', $matches); foreach ($filters as $key => $value) { if ($filters[$key]['enabled'] && $filters[$key]['dns']) { if (strlen($SpamFilters_DNScache[$IP . '.' . $filters[$key]['dns']]) == 0) { $IPs[$IP] = true; break; } } } } if ($SpamFilters_YourHop == ' ' || $IsSpam) { break; } } } } } } if (count($aSpamIds) && sqimap_mailbox_exists($imap_stream, $filters_spam_folder)) { sqimap_msgs_list_move($imap_stream, $aSpamIds, $filters_spam_folder); sqimap_mailbox_expunge($imap_stream, 'INBOX', true, $aSpamIds); } if ($bulkquery && count($IPs)) { filters_bulkquery($filters, $IPs); } if ($SpamFilters_SharedCache) { filters_SaveCache(); } else { sqsession_register($SpamFilters_DNScache, 'SpamFilters_DNScache'); } }
} else { $location = str_replace('search.php', 'compose.php', $location); $location = str_replace('right_main.php', 'compose.php', $location); } } } else { $exception = true; } } else { // Move messages if (count($id)) { // move messages only when target mailbox is not the same as source mailbox if ($mailbox != $targetMailbox) { sqimap_msgs_list_move($imapConnection, $id, $targetMailbox); if ($auto_expunge) { $cnt = sqimap_mailbox_expunge($imapConnection, $mailbox, true); } else { $cnt = 0; } if ($startMessage + $cnt - 1 >= $mbx_response['EXISTS']) { if ($startMessage > $show_num) { $location = set_url_var($location, 'startMessage', $startMessage - $show_num, false); } else { $location = set_url_var($location, 'startMessage', 1, false); } } } } else { $exception = true; } }
/** * Process messages list form and handle the cache gracefully. If $sButton and * $aUid are provided as argument then you can fake a message list submit and * use it i.e. in read_body.php for del move next and update the cache * * @param resource $imapConnection imap connection * @param array $aMailbox (reference) cached mailbox * @param string $sButton fake a submit button * @param array $aUid fake the $msg array * @return string $sError error string in case of an error * @author Marc Groot Koerkamp */ function handleMessageListForm($imapConnection, &$aMailbox, $sButton = '', $aUid = array()) { /* incoming formdata */ $sButton = sqgetGlobalVar('moveButton', $sTmp, SQ_POST) ? 'move' : $sButton; $sButton = sqgetGlobalVar('expungeButton', $sTmp, SQ_POST) ? 'expunge' : $sButton; $sButton = sqgetGlobalVar('attache', $sTmp, SQ_POST) ? 'attache' : $sButton; $sButton = sqgetGlobalVar('delete', $sTmp, SQ_POST) ? 'setDeleted' : $sButton; $sButton = sqgetGlobalVar('undeleteButton', $sTmp, SQ_POST) ? 'setDeleted' : $sButton; $sButton = sqgetGlobalVar('markRead', $sTmp, SQ_POST) ? 'setSeen' : $sButton; $sButton = sqgetGlobalVar('markUnread', $sTmp, SQ_POST) ? 'unsetSeen' : $sButton; $sButton = sqgetGlobalVar('markFlagged', $sTmp, SQ_POST) ? 'setFlagged' : $sButton; $sButton = sqgetGlobalVar('markUnflagged', $sTmp, SQ_POST) ? 'unsetFlagged' : $sButton; sqgetGlobalVar('targetMailbox', $targetMailbox, SQ_POST); sqgetGlobalVar('bypass_trash', $bypass_trash, SQ_POST); sqgetGlobalVar('msg', $msg, SQ_POST); $sError = ''; $mailbox = $aMailbox['NAME']; /* retrieve the check boxes */ $aUid = isset($msg) && is_array($msg) ? array_values($msg) : $aUid; if (count($aUid) && $sButton != 'expunge') { $aUpdatedMsgs = false; $bExpunge = false; switch ($sButton) { case 'setDeleted': // check if id exists in case we come from read_body if (count($aUid) == 1 && is_array($aMailbox['UIDSET'][$aMailbox['SETINDEX']]) && !in_array($aUid[0], $aMailbox['UIDSET'][$aMailbox['SETINDEX']])) { break; } $aUpdatedMsgs = sqimap_msgs_list_delete($imapConnection, $mailbox, $aUid, $bypass_trash); $bExpunge = true; break; case 'unsetDeleted': case 'setSeen': case 'unsetSeen': case 'setFlagged': case 'unsetFlagged': // get flag $sFlag = substr($sButton, 0, 3) == 'set' ? '\\' . substr($sButton, 3) : '\\' . substr($sButton, 5); $bSet = substr($sButton, 0, 3) == 'set' ? true : false; $aUpdatedMsgs = sqimap_toggle_flag($imapConnection, $aUid, $sFlag, $bSet, true); break; case 'move': $aUpdatedMsgs = sqimap_msgs_list_move($imapConnection, $aUid, $targetMailbox); sqsession_register($targetMailbox, 'lastTargetMailbox'); $bExpunge = true; break; case 'attache': $aMsgHeaders = array(); foreach ($aUid as $iUid) { $aMsgHeaders[$iUid] = $aMailbox['MSG_HEADERS'][$iUid]; } if (count($aMsgHeaders)) { $composesession = attachSelectedMessages($imapConnection, $aMsgHeaders); // dirty hack, add info to $aMailbox $aMailbox['FORWARD_SESSION'] = $composesession; } break; default: // Hook for plugin buttons do_hook_function('mailbox_display_button_action', $aUid); break; } /** * Updates messages is an array containing the result of the untagged * fetch responses send by the imap server due to a flag change. That * response is parsed in a array with msg arrays by the parseFetch function */ if ($aUpdatedMsgs) { // Update the message headers cache $aDeleted = array(); foreach ($aUpdatedMsgs as $iUid => $aMsg) { if (isset($aMsg['FLAGS'])) { /** * Only update the cached headers if the header is * cached. */ if (isset($aMailbox['MSG_HEADERS'][$iUid])) { $aMailbox['MSG_HEADERS'][$iUid]['FLAGS'] = $aMsg['FLAGS']; } /** * Count the messages with the \Delete flag set so we can determine * if the number of expunged messages equals the number of flagged * messages for deletion. */ if (isset($aMsg['FLAGS']['\\deleted']) && $aMsg['FLAGS']['\\deleted']) { $aDeleted[] = $iUid; } } } if ($bExpunge && $aMailbox['AUTO_EXPUNGE'] && ($iExpungedMessages = sqimap_mailbox_expunge($imapConnection, $aMailbox['NAME'], true))) { if (count($aDeleted) != $iExpungedMessages) { // there are more messages deleted permanently then we expected // invalidate the cache $aMailbox['UIDSET'][$aMailbox['SETINDEX']] = false; $aMailbox['MSG_HEADERS'] = false; } else { // remove expunged messages from cache $aUidSet = $aMailbox['UIDSET'][$aMailbox['SETINDEX']]; if (is_array($aUidSet)) { // create a UID => array index temp array $aUidSetDummy = array_flip($aUidSet); foreach ($aDeleted as $iUid) { // get the id as well in case of SQM_SORT_NONE if ($aMailbox['SORT'] == SQSORT_NONE) { $aMailbox['ID'] = false; //$iId = $aMailbox['MSG_HEADERS'][$iUid]['ID']; //unset($aMailbox['ID'][$iId]); } // unset the UID and message header unset($aUidSetDummy[$iUid]); unset($aMailbox['MSG_HEADERS'][$iUid]); } $aMailbox['UIDSET'][$aMailbox['SETINDEX']] = array_keys($aUidSetDummy); } } // update EXISTS info if ($iExpungedMessages) { $aMailbox['EXISTS'] -= (int) $iExpungedMessages; } // Change the startMessage number if the mailbox was changed if ($aMailbox['PAGEOFFSET'] - 1 >= $aMailbox['EXISTS']) { $aMailbox['PAGEOFFSET'] = $aMailbox['PAGEOFFSET'] > $aMailbox['LIMIT'] ? $aMailbox['PAGEOFFSET'] - $aMailbox['LIMIT'] : 1; $aMailbox['OFFSET'] = $aMailbox['PAGEOFFSET'] - 1; } } } } else { if ($sButton == 'expunge') { /** * on expunge we do not know which messages will be deleted * so it's useless to try to sync the cache * Close the mailbox so we do not need to parse the untagged expunge * responses which do not contain uid info. * NB: Closing a mailbox is faster then expunge because the imap * server does not need to generate the untagged expunge responses */ sqimap_run_command($imapConnection, 'CLOSE', false, $result, $message); $aMbxResponse = sqimap_mailbox_select($imapConnection, $aMailbox['NAME']); // update the $aMailbox array $aMailbox['EXISTS'] = $aMbxResponse['EXISTS']; $aMailbox['UIDSET'] = false; } else { if ($sButton) { $sError = _("No messages were selected."); } } } return $sError; }
function showMessagesForMailbox($imapConnection, $mailbox, $num_msgs, $start_msg, $sort, $color, $show_num, $use_cache, $mode = '') { global $msgs, $msort, $auto_expunge, $thread_sort_messages, $allow_server_sort, $server_sort_order; /* * For some reason, on PHP 4.3+, this being unset, and set in the session causes havoc * so setting it to an empty array beforehand seems to clean up the issue, and stopping the * "Your script possibly relies on a session side-effect which existed until PHP 4.2.3" error */ if (!isset($msort)) { $msort = array(); } if (!isset($msgs)) { $msgs = array(); } //$start = microtime(); /* If autoexpunge is turned on, then do it now. */ $mbxresponse = sqimap_mailbox_select($imapConnection, $mailbox); $srt = $sort; /* If autoexpunge is turned on, then do it now. */ if ($auto_expunge == true) { $exp_cnt = sqimap_mailbox_expunge($imapConnection, $mailbox, false, ''); $mbxresponse['EXISTS'] = $mbxresponse['EXISTS'] - $exp_cnt; $num_msgs = $mbxresponse['EXISTS']; } if ($mbxresponse['EXISTS'] > 0) { /* if $start_msg is lower than $num_msgs, we probably deleted all messages * in the last page. We need to re-adjust the start_msg */ if ($start_msg > $num_msgs) { $start_msg -= $show_num; if ($start_msg < 1) { $start_msg = 1; } } /* This code and the next if() block check for * server-side sorting methods. The $id array is * formatted and $sort is set to 6 to disable * SM internal sorting */ if ($thread_sort_messages == 1) { $mode = 'thread'; } elseif ($allow_server_sort == 1) { $mode = 'serversort'; } else { $mode = ''; } if ($use_cache) { sqgetGlobalVar('msgs', $msgs, SQ_SESSION); sqgetGlobalVar('msort', $msort, SQ_SESSION); } else { sqsession_unregister('msort'); sqsession_unregister('msgs'); } switch ($mode) { case 'thread': $id = get_thread_sort($imapConnection); $msgs = getServerMessages($imapConnection, $start_msg, $show_num, $num_msgs, $id); if ($msgs === false) { echo '<b><small><center><font color="red">' . _("Thread sorting is not supported by your IMAP server.") . '<br />' . _("Please contact your system administrator and report this error.") . '</font></center></small></b>'; $thread_sort_messages = 0; $msort = $msgs = array(); } else { $msort = $msgs; $sort = 6; } break; case 'serversort': $id = sqimap_get_sort_order($imapConnection, $sort, $mbxresponse); $msgs = getServerMessages($imapConnection, $start_msg, $show_num, $num_msgs, $id); if ($msgs === false) { echo '<b><small><center><font color="red">' . _("Server-side sorting is not supported by your IMAP server.") . '<br />' . _("Please contact your system administrator and report this error.") . '</font></center></small></b>'; $sort = $server_sort_order; $allow_server_sort = FALSE; $msort = $msgs = array(); $id = array(); } else { $msort = $msgs; $sort = 6; } break; default: if (!$use_cache) { $msgs = getSelfSortMessages($imapConnection, $start_msg, $show_num, $num_msgs, $sort, $mbxresponse); $msort = calc_msort($msgs, $sort); } /* !use cache */ break; } // switch sqsession_register($msort, 'msort'); sqsession_register($msgs, 'msgs'); } /* if exists > 0 */ $res = getEndMessage($start_msg, $show_num, $num_msgs); $start_msg = $res[0]; $end_msg = $res[1]; if ($num_msgs > 0) { $paginator_str = get_paginator_str($mailbox, $start_msg, $end_msg, $num_msgs, $show_num, $sort); } else { $paginator_str = ''; } $msg_cnt_str = get_msgcnt_str($start_msg, $end_msg, $num_msgs); do_hook('mailbox_index_before'); $safe_name = preg_replace("/[^0-9A-Za-z_]/", '_', $mailbox); $form_name = "FormMsgs" . $safe_name; echo '<form name="' . $form_name . '" method="post" action="move_messages.php">' . "\n" . '<input type="hidden" name="mailbox" value="' . htmlspecialchars($mailbox) . '">' . "\n" . '<input type="hidden" name="startMessage" value="' . htmlspecialchars($start_msg) . '">' . "\n"; echo '<table border="0" width="100%" cellpadding="0" cellspacing="0">'; echo '<tr><td>'; mail_message_listing_beginning($imapConnection, $mailbox, $sort, $msg_cnt_str, $paginator_str, $start_msg); /* line between the button area and the list */ echo '<tr><td height="5" bgcolor="' . $color[4] . '"></td></tr>'; echo '<tr><td>'; echo ' <table width="100%" cellpadding="1" cellspacing="0" align="center"' . ' border="0" bgcolor="' . $color[9] . '">'; echo ' <tr><td>'; echo ' <table width="100%" cellpadding="1" cellspacing="0" align="center" border="0" bgcolor="' . $color[5] . '">'; printHeader($mailbox, $srt, $color, !$thread_sort_messages); displayMessageArray($imapConnection, $num_msgs, $start_msg, $msort, $mailbox, $sort, $color, $show_num, 0, 0); echo '</table></td></tr></table>'; mail_message_listing_end($num_msgs, $paginator_str, $msg_cnt_str, $color); echo '</table>'; echo "\n</form>\n\n"; //$t = elapsed($start); //echo("elapsed time = $t seconds\n"); }
/** * Process messages list form and handle the cache gracefully. If $sButton and * $aUid are provided as argument then you can fake a message list submit and * use it i.e. in read_body.php for del move next and update the cache * * @param resource $imapConnection imap connection * @param array $aMailbox (reference) cached mailbox * @param string $sButton fake a submit button * @param array $aUid fake the $msg array * @param string $targetMailbox fake the target mailbox for move operations * @param boolean $bypass_trash fake the bypass trash checkbox for delete operations * @return string $sError error string in case of an error * @since 1.5.1 * @author Marc Groot Koerkamp */ function handleMessageListForm($imapConnection, &$aMailbox, $sButton = '', $aUid = array(), $targetMailbox = '', $bypass_trash = NULL) { /* incoming formdata */ $sButton = sqgetGlobalVar('moveButton', $sTmp, SQ_FORM) ? 'move' : $sButton; $sButton = sqgetGlobalVar('copyButton', $sTmp, SQ_FORM) ? 'copy' : $sButton; $sButton = sqgetGlobalVar('expungeButton', $sTmp, SQ_FORM) ? 'expunge' : $sButton; $sButton = sqgetGlobalVar('forward', $sTmp, SQ_FORM) ? 'forward' : $sButton; $sButton = sqgetGlobalVar('delete', $sTmp, SQ_FORM) ? 'setDeleted' : $sButton; $sButton = sqgetGlobalVar('undeleteButton', $sTmp, SQ_FORM) ? 'unsetDeleted' : $sButton; $sButton = sqgetGlobalVar('markRead', $sTmp, SQ_FORM) ? 'setSeen' : $sButton; $sButton = sqgetGlobalVar('markUnread', $sTmp, SQ_FORM) ? 'unsetSeen' : $sButton; $sButton = sqgetGlobalVar('markFlagged', $sTmp, SQ_FORM) ? 'setFlagged' : $sButton; $sButton = sqgetGlobalVar('markUnflagged', $sTmp, SQ_FORM) ? 'unsetFlagged' : $sButton; if (empty($targetMailbox)) { sqgetGlobalVar('targetMailbox', $targetMailbox, SQ_FORM); } if (is_null($bypass_trash)) { sqgetGlobalVar('bypass_trash', $bypass_trash, SQ_FORM); } sqgetGlobalVar('msg', $msg, SQ_FORM); if (sqgetGlobalVar('account', $iAccount, SQ_FORM) === false) { $iAccount = 0; } $sError = ''; $mailbox = $aMailbox['NAME']; /* retrieve the check boxes */ $aUid = isset($msg) && is_array($msg) ? array_values($msg) : $aUid; if (count($aUid) && $sButton != 'expunge') { // don't do anything to any messages until we have done security check // FIXME: not sure this code really belongs here, but there's nowhere else to put it with this architecture sqgetGlobalVar('smtoken', $submitted_token, SQ_FORM, ''); sm_validate_security_token($submitted_token, -1, TRUE); // make sure message UIDs are sanitized (BIGINT) foreach ($aUid as $i => $uid) { $aUid[$i] = preg_match('/^[0-9]+$/', $uid) ? $uid : '0'; } $aUpdatedMsgs = false; $bExpunge = false; switch ($sButton) { case 'setDeleted': // check if id exists in case we come from read_body if (count($aUid) == 1 && is_array($aMailbox['UIDSET'][$aMailbox['SETINDEX']]) && !in_array($aUid[0], $aMailbox['UIDSET'][$aMailbox['SETINDEX']])) { break; } $aUpdatedMsgs = sqimap_msgs_list_delete($imapConnection, $mailbox, $aUid, $bypass_trash); $bExpunge = true; //} break; case 'unsetDeleted': case 'setSeen': case 'unsetSeen': case 'setFlagged': case 'unsetFlagged': // get flag $sFlag = substr($sButton, 0, 3) == 'set' ? '\\' . substr($sButton, 3) : '\\' . substr($sButton, 5); $bSet = substr($sButton, 0, 3) == 'set' ? true : false; $aUpdatedMsgs = sqimap_toggle_flag($imapConnection, $aUid, $sFlag, $bSet, true); break; case 'move': $aUpdatedMsgs = sqimap_msgs_list_move($imapConnection, $aUid, $targetMailbox, true, $mailbox); sqsession_register($targetMailbox, 'lastTargetMailbox'); $bExpunge = true; break; case 'copy': // sqimap_msgs_list_copy returns true or false. // If error happens - fourth argument handles it inside function. sqimap_msgs_list_copy($imapConnection, $aUid, $targetMailbox, true); sqsession_register($targetMailbox, 'lastTargetMailbox'); break; case 'forward': $aMsgHeaders = array(); foreach ($aUid as $iUid) { $aMsgHeaders[$iUid] = $aMailbox['MSG_HEADERS'][$iUid]; } if (count($aMsgHeaders)) { $composesession = attachSelectedMessages($imapConnection, $aMsgHeaders); // dirty hack, add info to $aMailbox $aMailbox['FORWARD_SESSION']['SESSION_NUMBER'] = $composesession; $aMailbox['FORWARD_SESSION']['UIDS'] = $aUid; } break; default: // Hook for plugin buttons $temp = array(&$sButton, &$aMailbox, $iAccount, $aMailbox['NAME'], &$aUid); do_hook('mailbox_display_button_action', $temp); break; } /** * $aUpdatedMsgs is an array containing the result of the untagged * fetch responses send by the imap server due to a flag change. That * response is parsed in an array with msg arrays by the parseFetch function */ if ($aUpdatedMsgs) { // Update the message headers cache $aDeleted = array(); foreach ($aUpdatedMsgs as $iUid => $aMsg) { if (isset($aMsg['FLAGS'])) { /** * Only update the cached headers if the header is * cached. */ if (isset($aMailbox['MSG_HEADERS'][$iUid])) { $aMailbox['MSG_HEADERS'][$iUid]['FLAGS'] = $aMsg['FLAGS']; } /** * Also update flags in message object */ //FIXME: WHY are we keeping flags in TWO places?!? This is error-prone and some core code uses the is_xxxx message object values while other code uses the flags array above. That's a mess. if (isset($aMailbox['MSG_HEADERS'][$iUid]['MESSAGE_OBJECT'])) { $message = $aMailbox['MSG_HEADERS'][$iUid]['MESSAGE_OBJECT']; $message->is_seen = false; $message->is_answered = false; $message->is_forwarded = false; $message->is_deleted = false; $message->is_flagged = false; $message->is_mdnsent = false; foreach ($aMsg['FLAGS'] as $flag => $value) { if (strtolower($flag) == '\\seen' && $value) { $message->is_seen = true; } else { if (strtolower($flag) == '\\answered' && $value) { $message->is_answered = true; } else { if (strtolower($flag) == '$forwarded' && $value) { $message->is_forwarded = true; } else { if (strtolower($flag) == '\\deleted' && $value) { $message->is_deleted = true; } else { if (strtolower($flag) == '\\flagged' && $value) { $message->is_flagged = true; } else { if (strtolower($flag) == '$mdnsent' && $value) { $message->is_mdnsent = true; } } } } } } } $aMailbox['MSG_HEADERS'][$iUid]['MESSAGE_OBJECT'] = $message; } /** * Count the messages with the \Delete flag set so we can determine * if the number of expunged messages equals the number of flagged * messages for deletion. */ if (isset($aMsg['FLAGS']['\\deleted']) && $aMsg['FLAGS']['\\deleted']) { $aDeleted[] = $iUid; } } } if ($bExpunge && $aMailbox['AUTO_EXPUNGE'] && ($iExpungedMessages = sqimap_mailbox_expunge($imapConnection, $aMailbox['NAME'], true))) { if (count($aDeleted) != $iExpungedMessages) { // there are more messages deleted permanently then we expected // invalidate the cache $aMailbox['UIDSET'][$aMailbox['SETINDEX']] = false; $aMailbox['MSG_HEADERS'] = false; } else { // remove expunged messages from cache $aUidSet = $aMailbox['UIDSET'][$aMailbox['SETINDEX']]; if (is_array($aUidSet)) { // create a UID => array index temp array $aUidSetDummy = array_flip($aUidSet); foreach ($aDeleted as $iUid) { // get the id as well in case of SQM_SORT_NONE if ($aMailbox['SORT'] == SQSORT_NONE) { $aMailbox['ID'] = false; //$iId = $aMailbox['MSG_HEADERS'][$iUid]['ID']; //unset($aMailbox['ID'][$iId]); } // unset the UID and message header unset($aUidSetDummy[$iUid]); unset($aMailbox['MSG_HEADERS'][$iUid]); } $aMailbox['UIDSET'][$aMailbox['SETINDEX']] = array_keys($aUidSetDummy); } } // update EXISTS info if ($iExpungedMessages) { $aMailbox['EXISTS'] -= (int) $iExpungedMessages; $aMailbox['TOTAL'][$aMailbox['SETINDEX']] -= (int) $iExpungedMessages; } if ($aMailbox['PAGEOFFSET'] - 1 >= $aMailbox['EXISTS']) { $aMailbox['PAGEOFFSET'] = $aMailbox['PAGEOFFSET'] > $aMailbox['LIMIT'] ? $aMailbox['PAGEOFFSET'] - $aMailbox['LIMIT'] : 1; $aMailbox['OFFSET'] = $aMailbox['PAGEOFFSET'] - 1; } } } } else { if ($sButton == 'expunge') { /** * on expunge we do not know which messages will be deleted * so it's useless to try to sync the cache * * Close the mailbox so we do not need to parse the untagged expunge * responses which do not contain uid info. * NB: Closing a mailbox is faster then expunge because the imap * server does not need to generate the untagged expunge responses */ sqimap_run_command($imapConnection, 'CLOSE', false, $result, $message); $aMailbox = sqm_api_mailbox_select($imapConnection, $iAccount, $aMailbox['NAME'], array(), array()); } else { // this is the same hook as above, but here it is called in the // context of not having had any messages selected and if any // plugin handles the situation, it should return TRUE so we // know this was not an erroneous user action // global $null; $temp = array(&$sButton, &$aMailbox, $iAccount, $aMailbox['NAME'], $null); if (!boolean_hook_function('mailbox_display_button_action', $temp, 1) && $sButton) { $sError = _("No messages were selected."); } } } return $sError; }
function bayesspam_prune($args) { if ($args[0] != 'left_main_before' || !isset($_SESSION['just_logged_in']) || $_SESSION['just_logged_in'] != true) { return; } if ($GLOBALS['bayesdbhandle'] == null) { return; } if ($GLOBALS['bayesspam_prune_threshold'] == 0) { return; } $secsago = 86400 * ($GLOBALS['bayesspam_prune_threshold'] - 1); /* Convert days to seconds */ $cutoffdate = date('d-M-Y', time() - $secsago); if (!sqimap_mailbox_exists($GLOBALS['imapConnection'], $GLOBALS['bayesspam_folder'])) { return; } $notrash = false; if (!sqimap_mailbox_exists($GLOBALS['imapConnection'], $GLOBALS['trash_folder'])) { $notrash = true; } else { $trashbox = sqimap_mailbox_select($GLOBALS['imapConnection'], $GLOBALS['trash_folder']); if (strtolower($trashbox['RIGHTS']) != "read-write") { $notrash = true; } } $mbx = sqimap_mailbox_select($GLOBALS['imapConnection'], $GLOBALS['bayesspam_folder']); if (strtolower($mbx['RIGHTS']) != "read-write") { return; } $query = "SEARCH SENTBEFORE {$cutoffdate}"; $read = sqimap_run_command($GLOBALS['imapConnection'], $query, TRUE, $response, $message, $GLOBALS['uid_support']); $results = str_replace(' ', ',', substr($read[0], 9)); $msglist = trim($results); /* get rid of that nasty whitespace */ if (strlen($msglist) < 1) { return; } $msglist = sqimap_message_list_squisher(explode(' ', $msglist)); if (!$notrash && $GLOBALS['default_move_to_trash']) { sqimap_msgs_list_move($GLOBALS['imapConnection'], $msglist, $GLOBALS['trash_folder']); } else { sqimap_msgs_list_delete($GLOBALS['imapConnection'], $GLOBALS['bayesspam_folder'], $msglist); } if ($GLOBALS['auto_expunge']) { sqimap_mailbox_expunge($GLOBALS['imapConnection'], $GLOBALS['bayesspam_folder']); } }
function delete_move_expunge_from_all($id) { global $msgs, $msort, $sort, $imapConnection, $mailbox, $uid_support; $delAt = -1; if (isset($msort) && count($msort) > 0) { for ($i = 0; $i < count($msort); $i++) { if ($msgs[$i]['ID'] == $id) { $delAt = $i; } elseif ($msgs[$i]['ID'] > $id) { if (!$uid_support) { $msgs[$i]['ID']--; } } } $msgs = delete_move_del_arr_elem($msgs, $delAt); $msort = delete_move_del_arr_elem($msort, $delAt); if ($sort < 6) { if ($sort % 2) { asort($msort); } else { arsort($msort); } } sqsession_register($msgs, 'msgs'); sqsession_register($msort, 'msort'); } sqimap_mailbox_expunge($imapConnection, $mailbox, true); }
function delete_move_next_move() { global $imapConnection, $move_id, $targetMailbox, $auto_expunge, $mailbox; // Move message sqimap_messages_copy($imapConnection, $move_id, $move_id, $targetMailbox); sqimap_messages_flag($imapConnection, $move_id, $move_id, "Deleted"); if ($auto_expunge == true) { sqimap_mailbox_expunge($imapConnection, $mailbox, true); } }
/** * Process messages that are submitted by email. * * Delete spam if user wants to delete it. Don't save submitted emails. * Implement overrides that fix compose.php behavior. * @since 1.5.1 * @access private */ function spamcop_while_sending_function() { global $mailbox, $spamcop_delete, $spamcop_save, $spamcop_is_composing, $auto_expunge, $username, $imapServerAddress, $imapPort, $imap_stream_options; if (sqgetGlobalVar('spamcop_is_composing', $spamcop_is_composing)) { // delete spam message if ($spamcop_delete) { $imapConnection = sqimap_login($username, false, $imapServerAddress, $imapPort, 0, $imap_stream_options); sqimap_mailbox_select($imapConnection, $mailbox); sqimap_msgs_list_delete($imapConnection, $mailbox, array($spamcop_is_composing)); if ($auto_expunge) { sqimap_mailbox_expunge($imapConnection, $mailbox, true); } } if (!$spamcop_save) { // disable use of send folder. // Temporally override in order to disable saving of 'reply anyway' messages. global $default_move_to_sent; $default_move_to_sent = false; } // change default email composition setting. Plugin always operates in right frame. // make sure that compose.php redirects to right page. Temporally override. global $compose_new_win; $compose_new_win = false; } }
function bayesspam_filters($imap_stream, $use_mailbox = 0) { $spam_stats = 0; $ham_stats = 0; $unsure_stats = 0; $total_messages = 0; $run_folders = array(); $boxes = sqimap_mailbox_list($imap_stream); foreach ($boxes as $box) { if ($GLOBALS['bayesspam_inboxonly'] != 1 || $GLOBALS['bayesspam_inboxonly'] == 1 && 'INBOX' == $box['unformatted-dm']) { if ($use_mailbox == 1 && $box['unformatted-dm'] == $GLOBALS['mailbox'] && !in_array($box['unformatted-dm'], $GLOBALS['bayesspam_ignore_folders']) || $use_mailbox == 0 && !in_array($box['unformatted-dm'], $GLOBALS['bayesspam_ignore_folders'])) { if ((array_search('noselect', $box['flags']) === FALSE || array_search('noselect', $box['flags']) === NULL) && $GLOBALS['sent_folder'] != $box['unformatted-dm'] && sqimap_unseen_messages($imap_stream, $box['unformatted-dm']) > 0) { $run_folders[] = $box['unformatted-dm']; } } } } foreach ($run_folders as $box) { $spam_messages = array(); $uncertain_messages = array(); $mbxresponse = sqimap_mailbox_select($imap_stream, $box); $messages = array(); $search = "SEARCH UNSEEN UNDELETED"; if (isset($_SESSION['bayesspam_last_filter'])) { $search .= " SINCE " . date('d-M-Y', $_SESSION['bayesspam_last_filter']); } $_SESSION['bayesspam_last_filter'] = time(); $read = sqimap_run_command($imap_stream, $search, TRUE, $response, $message, TRUE); if (isset($read[0])) { for ($i = 0, $iCnt = count($read); $i < $iCnt; ++$i) { if (preg_match("/^\\* SEARCH (.+)\$/", $read[$i], $regs)) { $messages = preg_split("/ /", trim($regs[1])); break; } } } foreach ($messages as $passed_id) { bayesspam_set_message_id($imap_stream, $passed_id); $bayesspam_check_messageid = bayesspam_check_messageid(); if ($GLOBALS['bayesspam_do_stats'] && $GLOBALS['bayesspam_do_user_stats']) { $bayesspam_old_message_score = bayesspam_get_old_message_score(); } $is_spam = bayesspam_get_probability($imap_stream, $passed_id, 1); if ($is_spam > 0.9) { $spam_messages[] = $passed_id; } elseif ($is_spam >= 0.1) { $uncertain_messages[] = $passed_id; } if ($GLOBALS['bayesspam_do_stats'] && $GLOBALS['bayesspam_do_user_stats'] && $bayesspam_old_message_score === FALSE) { if ($is_spam > 0.9) { $spam_stats++; $total_messages++; } if ($is_spam <= 0.9 && $is_spam >= 0.1) { $unsure_stats++; $total_messages++; } if ($is_spam < 0.1) { $ham_stats++; $total_messages++; } } } if ($spam_messages) { $message_str = sqimap_message_list_squisher($spam_messages); if ($GLOBALS['bayesspam_delete']) { sqimap_run_command($imap_stream, 'STORE ' . $message_str . ' +FLAGS (\\Deleted)', true, $response, $message, $GLOBALS['uid_support']); } elseif (sqimap_mailbox_exists($imap_stream, $GLOBALS['bayesspam_folder'])) { sqimap_run_command($imap_stream, 'COPY ' . $message_str . ' "' . $GLOBALS['bayesspam_folder'] . '"', true, $response, $message, $GLOBALS['uid_support']); sqimap_run_command($imap_stream, 'STORE ' . $message_str . ' +FLAGS (\\Deleted)', true, $response, $message, $GLOBALS['uid_support']); } sqimap_mailbox_expunge($imap_stream, $box); } if ($uncertain_messages && $GLOBALS['bayesspam_do_uncertain_filtering']) { $message_str = sqimap_message_list_squisher($uncertain_messages); if (sqimap_mailbox_exists($imap_stream, $GLOBALS['bayesspam_uncertain_folder'])) { sqimap_run_command($imap_stream, 'COPY ' . $message_str . ' "' . $GLOBALS['bayesspam_uncertain_folder'] . '"', true, $response, $message, $GLOBALS['uid_support']); sqimap_run_command($imap_stream, 'STORE ' . $message_str . ' +FLAGS (\\Deleted)', true, $response, $message, $GLOBALS['uid_support']); } sqimap_mailbox_expunge($imap_stream, $box); } } if ($GLOBALS['bayesspam_do_stats'] && $GLOBALS['bayesspam_do_user_stats'] && $total_messages) { $res = $GLOBALS['bayesdbhandle']->query('SELECT UserName FROM ' . $GLOBALS['bayesdbprefix'] . 'stats WHERE UserName=\'' . $GLOBALS['bayes_username'] . '\''); if (!DB::isError($res) && !($row = $res->fetchRow())) { $GLOBALS['bayesdbhandle']->query('INSERT INTO ' . $GLOBALS['bayesdbprefix'] . 'stats SET StatsStart=NOW(),UserName=\'' . $GLOBALS['bayes_username'] . '\',TotalMessages=' . $total_messages . ',HamMessages=' . $ham_stats . ',SpamMessages=' . $spam_stats . ',UnsureMessages=' . $unsure_stats . ($GLOBALS['bayesspam_do_timing'] ? ',TimedMessages=' . $GLOBALS['bayes_parsed_messages'] . ',TotalParseTime=' . $GLOBALS['bayes_parse_time'] : '')); } else { $GLOBALS['bayesdbhandle']->query('UPDATE ' . $GLOBALS['bayesdbprefix'] . 'stats SET TotalMessages=TotalMessages+' . $total_messages . ',HamMessages=HamMessages+' . $ham_stats . ',SpamMessages=SpamMessages+' . $spam_stats . ', UnsureMessages=UnsureMessages+' . $unsure_stats . ($GLOBALS['bayesspam_do_timing'] ? ',TimedMessages=TimedMessages+' . $GLOBALS['bayes_parsed_messages'] . ',TotalParseTime=TotalParseTime+' . $GLOBALS['bayes_parse_time'] : '') . ' WHERE UserName=\'' . $GLOBALS['bayes_username'] . '\''); } } }
$temp = array(&$Result, &$composeMessage, &$mail_sent); do_hook('compose_send_after', $temp); if (!$Result) { showInputForm($session); exit; } /* if it is resumed draft, delete draft message */ if (isset($delete_draft)) { $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, false, $imap_stream_options); sqimap_mailbox_select($imap_stream, $draft_folder); // bypass_trash=true because message should be saved when deliverMessage() returns true. // in current implementation of sqimap_msgs_list_flag() single message id can // be submitted as string. docs state that it should be array. sqimap_msgs_list_delete($imap_stream, $draft_folder, $delete_draft, true); if ($auto_expunge) { sqimap_mailbox_expunge($imap_stream, $draft_folder, true); } sqimap_logout($imap_stream); } /* * Store the error array in the session because they will be lost on a redirect */ $oErrorHandler->saveDelayedErrors(); session_write_close(); if ($compose_new_win == '1') { if (!isset($pageheader_sent) || !$pageheader_sent) { header("Location: {$location}/compose.php?mail_sent={$mail_sent}"); } else { //FIXME: DON'T ECHO HTML FROM CORE! echo ' <br><br><div style="text-align: center;"><a href="' . $location . '/compose.php?mail_sent=$mail_sent">' . _("Return") . '</a></div>'; }
/** * FIXME: Undocumented function * @access private */ function spam_filters($imap_stream) { global $data_dir, $username, $uid_support; global $SpamFilters_YourHop; global $SpamFilters_DNScache; global $SpamFilters_SharedCache; global $SpamFilters_BulkQuery; $filters_spam_scan = getPref($data_dir, $username, 'filters_spam_scan'); $filters_spam_folder = getPref($data_dir, $username, 'filters_spam_folder'); $filters = load_spam_filters(); if ($SpamFilters_SharedCache) { filters_LoadCache(); } $run = 0; foreach ($filters as $Key => $Value) { if ($Value['enabled']) { $run++; } } // short-circuit if ($run == 0) { return; } sqimap_mailbox_select($imap_stream, 'INBOX'); // Ask for a big list of all "Received" headers in the inbox with // flags for each message. Kinda big. if ($filters_spam_scan != 'new') { $read = sqimap_run_command($imap_stream, 'FETCH 1:* (FLAGS BODY.PEEK[HEADER.FIELDS ' . '(RECEIVED)])', true, $response, $message, $uid_support); } else { $read = sqimap_run_command($imap_stream, 'SEARCH UNSEEN', true, $response, $message, $uid_support); if ($response != 'OK' || trim($read[0]) == '* SEARCH') { $read = sqimap_run_command($imap_stream, 'FETCH 1:* (FLAGS BODY.PEEK[HEADER.FIELDS ' . '(RECEIVED)])', true, $response, $message, $uid_support); } else { if (isset($read[0])) { if (preg_match("/^\\* SEARCH (.+)\$/", $read[0], $regs)) { $search_array = preg_split("/ /", trim($regs[1])); } } $msgs_str = sqimap_message_list_squisher($search_array); $imap_query = 'FETCH ' . $msgs_str; $imap_query .= ' (FLAGS BODY.PEEK[HEADER.FIELDS '; $imap_query .= '(RECEIVED)])'; $read = sqimap_run_command($imap_stream, $imap_query, true, $response, $message, $uid_support); } } if (isset($response) && $response != 'OK') { return; } if (strlen($SpamFilters_BulkQuery) > 0) { filters_bulkquery($filters_spam_scan, $filters, $read); } $i = 0; while ($i < count($read)) { // EIMS will give funky results $Chunks = explode(' ', $read[$i]); if ($Chunks[0] != '*') { $i++; continue; } $MsgNum = $Chunks[1]; $IPs = array(); $i++; $IsSpam = 0; // Look through all of the Received headers for IP addresses // Stop when I get ")" on a line // Stop if I get "*" on a line (don't advance) // and above all, stop if $i is bigger than the total # of lines while ($i < count($read) && ($read[$i][0] != ')' && $read[$i][0] != '*' && $read[$i][0] != "\n") && !$IsSpam) { // Check to see if this line is the right "Received from" line // to check if (is_int(strpos($read[$i], $SpamFilters_YourHop))) { // short-circuit and skip work if we don't scan this one $read[$i] = ereg_replace('[^0-9\\.]', ' ', $read[$i]); $elements = explode(' ', $read[$i]); foreach ($elements as $value) { if ($value != '' && ereg('[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}', $value, $regs)) { $Chunks = explode('.', $value); if (filters_spam_check_site($Chunks[0], $Chunks[1], $Chunks[2], $Chunks[3], $filters)) { $IsSpam++; break; // no sense in checking more IPs } // If we've checked one IP and YourHop is // just a space if ($SpamFilters_YourHop == ' ') { break; // don't check any more } } } } $i++; } // Lookie! It's spam! Yum! if ($IsSpam) { if (sqimap_mailbox_exists($imap_stream, $filters_spam_folder)) { // check if message copy was successful if (sqimap_messages_copy($imap_stream, $MsgNum, $MsgNum, $filters_spam_folder, false)) { sqimap_messages_flag($imap_stream, $MsgNum, $MsgNum, 'Deleted', false); } } } else { } } sqimap_mailbox_expunge($imap_stream, 'INBOX'); if ($SpamFilters_SharedCache) { filters_SaveCache(); } else { sqsession_register($SpamFilters_DNScache, 'SpamFilters_DNScache'); } }
function spamcop_while_sending() { global $mailbox, $spamcop_delete, $auto_expunge, $username, $key, $imapServerAddress, $imapPort; // load sqgetGlobalVar() include_once SM_PATH . 'functions/global.php'; // check if compose.php is called by spamcop plugin if (sqgetGlobalVar('spamcop_is_composing', $spamcop_is_composing)) { if ($spamcop_delete) { $imapConnection = sqimap_login($username, $key, $imapServerAddress, $imapPort, 0); sqimap_mailbox_select($imapConnection, $mailbox); sqimap_msgs_list_delete($imapConnection, $mailbox, $spamcop_is_composing); if ($auto_expunge) { sqimap_mailbox_expunge($imapConnection, $mailbox, true); } } // change default email composition setting. Plugin always operates in right frame. // make sure that compose.php redirects to right page. Temporally override. global $compose_new_win; $compose_new_win = false; } }
/** * Loops through all the Received Headers to find IP Addresses * @param stream imap_stream the stream to read from * @access private */ function spam_filters($imap_stream) { global $data_dir, $username; global $SpamFilters_YourHop; global $SpamFilters_DNScache; global $SpamFilters_SharedCache; global $SpamFilters_BulkQuery; global $SpamFilters_CacheTTL; $filters_spam_scan = getPref($data_dir, $username, 'filters_spam_scan'); $filters_spam_folder = getPref($data_dir, $username, 'filters_spam_folder'); $filters = load_spam_filters(); if ($SpamFilters_SharedCache) { filters_LoadCache(); } $run = false; foreach ($filters as $Value) { if ($Value['enabled']) { $run = true; break; } } // short-circuit if (!$run) { return; } // Ask for a big list of all "Received" headers in the inbox with // flags for each message. Kinda big. if ($filters_spam_scan == 'new') { $search_array = array(); $read = sqimap_run_command($imap_stream, 'SEARCH UNSEEN', true, $response, $message, TRUE); if (isset($read[0])) { for ($i = 0, $iCnt = count($read); $i < $iCnt; ++$i) { if (preg_match("/^\\* SEARCH (.+)\$/", $read[$i], $regs)) { $search_array = explode(' ', trim($regs[1])); break; } } } } if ($filters_spam_scan == 'new' && count($search_array)) { $headers = sqimap_get_small_header_list($imap_stream, $search_array, array('Received'), array()); } else { if ($filters_spam_scan != 'new') { $headers = sqimap_get_small_header_list($imap_stream, null, array('Received'), array()); } else { return; } } if (!count($headers)) { return; } $bulkquery = strlen($SpamFilters_BulkQuery) > 0 ? true : false; $IPs = array(); $aSpamIds = array(); foreach ($headers as $id => $aValue) { if (isset($aValue['UID'])) { $MsgNum = $aValue['UID']; } else { $MsgNum = $id; } // Look through all of the Received headers for IP addresses if (isset($aValue['RECEIVED'])) { foreach ($aValue['RECEIVED'] as $received) { // Check to see if this line is the right "Received from" line // to check // $aValue['Received'] is an array with all the received lines. // We should check them from bottom to top and only check the first 2. // Currently we check only the header where $SpamFilters_YourHop in occures if (is_int(strpos($received, $SpamFilters_YourHop))) { if (preg_match('/([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})/', $received, $aMatch)) { $isspam = false; if (filters_spam_check_site($aMatch[1], $aMatch[2], $aMatch[3], $aMatch[4], $filters)) { $aSpamIds[] = $MsgNum; $isspam = true; } if ($bulkquery) { array_shift($aMatch); $IP = explode('.', $aMatch); foreach ($filters as $key => $value) { if ($filters[$key]['enabled'] && $filters[$key]['dns']) { if (strlen($SpamFilters_DNScache[$IP . '.' . $filters[$key]['dns']]) == 0) { $IPs[$IP] = true; break; } } } } // If we've checked one IP and YourHop is // just a space if ($SpamFilters_YourHop == ' ' || $isspam) { break; // don't check any more } } } } } } // Lookie! It's spam! Yum! if (count($aSpamIds) && sqimap_mailbox_exists($imap_stream, $filters_spam_folder)) { if (!sqimap_msgs_list_move($imap_stream, $aSpamIds, $filters_spam_folder)) { // if errors occurred, don't try to filter again during this session sqsession_register(TRUE, 'filters_error'); global $color; error_box(_("A problem occurred filtering messages. Check filter settings and account quota if applicable. Filtering is disabled for the remainder of this login session."), $color); } // expunge even in the case of errors, in case some // messages were filtered before the error happened sqimap_mailbox_expunge($imap_stream, 'INBOX'); } if ($bulkquery && count($IPs)) { filters_bulkquery($filters, $IPs); } if ($SpamFilters_SharedCache) { filters_SaveCache(); } else { sqsession_register($SpamFilters_DNScache, 'SpamFilters_DNScache'); } }