function sqimap_get_small_header($imap_stream, $id, $sent) { $res = sqimap_get_small_header_list($imap_stream, $id, $sent); return $res[0]; }
function fetchMessageHeaders($imapConnection, &$aMailbox) { /** * Retrieve the UIDSET. * Setindex is used to be able to store multiple uid sets. That will make it * possible to display the mailbox multiple times in different sort order * or to store serach results separate from normal mailbox view. */ $iSetIndx = isset($aMailbox['SETINDEX']) ? $aMailbox['SETINDEX'] : 0; $iLimit = $aMailbox['SHOWALL'][$iSetIndx] ? $aMailbox['EXISTS'] : $aMailbox['LIMIT']; /** * Adjust the start_msg */ $start_msg = $aMailbox['PAGEOFFSET']; if ($aMailbox['PAGEOFFSET'] > $aMailbox['EXISTS']) { $start_msg -= $aMailbox['LIMIT']; if ($start_msg < 1) { $start_msg = 1; } } if (is_array($aMailbox['UIDSET'])) { $aUid =& $aMailbox['UIDSET'][$iSetIndx]; } else { $aUid = false; } // initialize the fields we want to retrieve: $aHeaderFields = array('Date', 'To', 'Cc', 'From', 'Subject', 'X-Priority', 'Content-Type'); $aFetchItems = array('FLAGS', 'RFC822.SIZE'); // Are we sorting on internaldate then retrieve the internaldate value as well if ($aMailbox['INTERNALDATE']) { $aFetchItems[] = 'INTERNALDATE'; } /** * A uidset with sorted uid's is available. We can use the cache */ if (($aMailbox['SORT'] != SQSORT_NONE || $aMailbox['SEARCH'][$iSetIndx] != 'ALL') && isset($aUid) && $aUid) { // limit the cache to SQM_MAX_PAGES_IN_CACHE if (!$aMailbox['SHOWALL'][$iSetIndx]) { $iMaxMsgs = $iLimit * SQM_MAX_PAGES_IN_CACHE; $iCacheSize = count($aMailbox['MSG_HEADERS']); if ($iCacheSize > $iMaxMsgs) { $iReduce = $iCacheSize - $iMaxMsgs; foreach ($aMailbox['MSG_HEADERS'] as $iUid => $value) { if ($iReduce) { unset($aMailbox['MSG_HEADERS'][$iUid]); } else { break; } --$iReduce; } } } $id_slice = array_slice($aUid, $start_msg - 1, $iLimit); /* do some funky cache checks */ $aUidCached = array_keys($aMailbox['MSG_HEADERS']); $aUidNotCached = array_values(array_diff($id_slice, $aUidCached)); /** * $aUidNotCached contains an array with UID's which need to be fetched to * complete the needed message headers. */ if (count($aUidNotCached)) { $aMsgs = sqimap_get_small_header_list($imapConnection, $aUidNotCached, $aHeaderFields, $aFetchItems); // append the msgs to the existend headers $aMailbox['MSG_HEADERS'] += $aMsgs; } } else { /** * Initialize the sorted UID list and fetch the visible message headers */ if ($aMailbox['SORT'] != SQSORT_NONE || $aMailbox['SEARCH'][$iSetIndx] != 'ALL') { // || $aMailbox['SORT_METHOD'] & SQSORT_THREAD 'THREAD') { $error = false; if ($aMailbox['SEARCH'][$iSetIndx] && $aMailbox['SORT'] == 0) { $aUid = sqimap_run_search($imapConnection, $aMailbox['SEARCH'][$iSetIndx], $aMailbox['CHARSET'][$iSetIndx]); } else { $error = get_sorted_msgs_list($imapConnection, $aMailbox, $error); $aUid = $aMailbox['UIDSET'][$iSetIndx]; } if ($error === false) { $id_slice = array_slice($aUid, $aMailbox['OFFSET'], $iLimit); if (count($id_slice)) { $aMailbox['MSG_HEADERS'] = sqimap_get_small_header_list($imapConnection, $id_slice, $aHeaderFields, $aFetchItems); } else { return false; } } else { // FIX ME, format message and fallback to squirrel sort if ($error) { echo $error; } } } else { // limit the cache to SQM_MAX_PAGES_IN_CACHE if (!$aMailbox['SHOWALL'][$iSetIndx] && isset($aMailbox['MSG_HEADERS']) && is_array($aMailbox['MSG_HEADERS'])) { $iMaxMsgs = $iLimit * SQM_MAX_PAGES_IN_CACHE; $iCacheSize = count($aMailbox['MSG_HEADERS']); if ($iCacheSize > $iMaxMsgs) { $iReduce = $iCacheSize - $iMaxMsgs; foreach ($aMailbox['MSG_HEADERS'] as $iUid => $value) { if ($iReduce) { $iId = $aMailbox['MSG_HEADERS'][$iUid]['ID']; unset($aMailbox['MSG_HEADERS'][$iUid]); unset($aMailbox['ID'][$iId]); } else { break; } --$iReduce; } } } /** * retrieve messages by sequence id's and fetch the UID to retrieve * the UID. for sorted lists this is not needed because a UID FETCH * automaticly add the UID value in fetch results **/ $aFetchItems[] = 'UID'; //create id range $iRangeStart = $aMailbox['EXISTS'] - $aMailbox['OFFSET']; $iRangeEnd = $iRangeStart > $iLimit ? $iRangeStart - $iLimit + 1 : 1; $id_slice = range($iRangeStart, $iRangeEnd); /** * Non sorted mailbox with cached message headers */ if (isset($aMailbox['ID']) && is_array($aMailbox['ID'])) { // the fetched id => uid relation $aId = $aMailbox['ID']; $aIdCached = array(); foreach ($aId as $iId => $iUid) { if (isset($aMailbox['MSG_HEADERS'][$iUid])) { if ($iId <= $iRangeStart && $iId >= $iRangeEnd) { $aIdCached[] = $iId; } } } $aIdNotCached = array_diff($id_slice, $aIdCached); } else { $aIdNotCached = $id_slice; } if (count($aIdNotCached)) { $aMsgs = sqimap_get_small_header_list($imapConnection, $aIdNotCached, $aHeaderFields, $aFetchItems); // append the msgs to the existend headers if (isset($aMailbox['MSG_HEADERS']) && is_array($aMailbox['MSG_HEADERS'])) { $aMailbox['MSG_HEADERS'] += $aMsgs; } else { $aMailbox['MSG_HEADERS'] = $aMsgs; } // update the ID array foreach ($aMsgs as $iUid => $aMsg) { if (isset($aMsg['ID'])) { $aMailbox['ID'][$aMsg['ID']] = $iUid; } } } /** * In unsorted state we show newest messages first which means * that the UIDSET which represents the order of the messages * should contain a high to low ordered UID list */ $aSortedUidList = array(); foreach ($id_slice as $iId) { if (isset($aMailbox['ID'][$iId])) { $aSortedUidList[] = $aMailbox['ID'][$iId]; } } $aMailbox['UIDSET'][$iSetIndx] = $aSortedUidList; $aMailbox['OFFSET'] = 0; } } return true; }
/** * Retrieves an array with a sorted uid list. Sorting is done by SquirrelMail * * @param resource $imap_stream IMAP socket connection * @param string $sSortField Field to sort on * @param bool $reverse Reverse order search * @param array $aUid limit the search to the provided array with uid's default sqimap_get_small_headers uses 1:* * @return array $aUid sorted uid list */ function get_squirrel_sort($imap_stream, $sSortField, $reverse = false, $aUid = NULL) { if ($sSortField != 'RFC822.SIZE' && $sSortField != 'INTERNALDATE') { $msgs = sqimap_get_small_header_list($imap_stream, $aUid, array($sSortField), array()); } else { $msgs = sqimap_get_small_header_list($imap_stream, $aUid, array(), array($sSortField)); } // sqimap_get_small_header (see above) returns fields in lower case, // but the code below uses all upper case foreach ($msgs as $k => $v) { if (isset($msgs[$k][strtolower($sSortField)])) { $msgs[$k][strtoupper($sSortField)] = $msgs[$k][strtolower($sSortField)]; } } $aUid = array(); $walk = false; switch ($sSortField) { // natcasesort section case 'FROM': case 'TO': case 'CC': if (!$walk) { array_walk($msgs, create_function('&$v,&$k,$f', '$v[$f] = (isset($v[$f])) ? $v[$f] : ""; $addr = reset(parseRFC822Address($v[$f],1)); $sPersonal = (isset($addr[SQM_ADDR_PERSONAL]) && $addr[SQM_ADDR_PERSONAL]) ? $addr[SQM_ADDR_PERSONAL] : ""; $sEmail = ($addr[SQM_ADDR_HOST]) ? $addr[SQM_ADDR_MAILBOX] . "@".$addr[SQM_ADDR_HOST] : $addr[SQM_ADDR_HOST]; $v[$f] = ($sPersonal) ? decodeHeader($sPersonal, true, false):$sEmail;'), $sSortField); $walk = true; } // nobreak // nobreak case 'SUBJECT': if (!$walk) { array_walk($msgs, create_function('&$v,&$k,$f', '$v[$f] = (isset($v[$f])) ? $v[$f] : ""; $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) { $aUid[$item['UID']] = $item[$sSortField]; } natcasesort($aUid); $aUid = array_keys($aUid); if ($reverse) { $aUid = array_reverse($aUid); } break; // \natcasesort section // sort_numeric section // \natcasesort section // sort_numeric section case 'DATE': case 'INTERNALDATE': if (!$walk) { array_walk($msgs, create_function('&$v,$k,$f', '$v[$f] = (isset($v[$f])) ? $v[$f] : ""; $v[$f] = getTimeStamp(explode(" ",$v[$f]));'), $sSortField); $walk = true; } // nobreak; // nobreak; case 'RFC822.SIZE': if (!$walk) { // redefine $sSortField to maintain the same namespace between // server-side sorting and SquirrelMail sorting $sSortField = 'SIZE'; } foreach ($msgs as $item) { $aUid[$item['UID']] = isset($item[$sSortField]) ? $item[$sSortField] : 0; } if ($reverse) { arsort($aUid, SORT_NUMERIC); } else { asort($aUid, SORT_NUMERIC); } $aUid = array_keys($aUid); break; // \sort_numeric section // \sort_numeric section case 'UID': $aUid = array_reverse($msgs); break; } return $aUid; }
function fillMessageArray($imapConnection, $id, $count, $show_num = false) { return sqimap_get_small_header_list($imapConnection, $id, $show_num); }
/** * Fetch the message headers for a mailbox. Settings are part of the aMailbox * array. Dependent of the mailbox settings it deals with sort, thread and search * If server sort is supported then SORT is also used for retrieving sorted search results * * @param resource $imapConnection imap socket handle * @param array $aMailbox (reference) mailbox retrieved from sqm_api_mailbox_select * @return error $error error number * @since 1.5.1 * @author Marc Groot Koerkamp */ function fetchMessageHeaders($imapConnection, &$aMailbox) { /* FIX ME, this function is kind of big, maybe we can split it up in a couple of functions. Make sure the functions are private and starts with _ Also make sure that the error codes are propagated */ /** * Retrieve the UIDSET. * Setindex is used to be able to store multiple uid sets. That will make it * possible to display the mailbox multiple times in different sort order * or to store serach results separate from normal mailbox view. */ $iSetIndx = isset($aMailbox['SETINDEX']) ? $aMailbox['SETINDEX'] : 0; $iLimit = $aMailbox['SHOWALL'][$iSetIndx] ? $aMailbox['EXISTS'] : $aMailbox['LIMIT']; /** * Adjust the start_msg */ $start_msg = $aMailbox['PAGEOFFSET']; if ($aMailbox['PAGEOFFSET'] > $aMailbox['EXISTS']) { $start_msg -= $aMailbox['LIMIT']; if ($start_msg < 1) { $start_msg = 1; } } if (is_array($aMailbox['UIDSET'])) { $aUid =& $aMailbox['UIDSET'][$iSetIndx]; } else { $aUid = false; } $aFetchHeaders = $aMailbox['FETCHHEADERS']; $iError = 0; $aFetchItems = $aHeaderItems = array(); // initialize the fields we want to retrieve: $aHeaderFields = array(); foreach ($aFetchHeaders as $v) { switch ($v) { case SQM_COL_DATE: $aHeaderFields[] = 'Date'; break; case SQM_COL_TO: $aHeaderFields[] = 'To'; break; case SQM_COL_CC: $aHeaderFields[] = 'Cc'; break; case SQM_COL_FROM: $aHeaderFields[] = 'From'; break; case SQM_COL_SUBJ: $aHeaderFields[] = 'Subject'; break; case SQM_COL_PRIO: $aHeaderFields[] = 'X-Priority'; break; case SQM_COL_ATTACHMENT: $aHeaderFields[] = 'Content-Type'; break; case SQM_COL_INT_DATE: $aFetchItems[] = 'INTERNALDATE'; break; case SQM_COL_FLAGS: $aFetchItems[] = 'FLAGS'; break; case SQM_COL_SIZE: $aFetchItems[] = 'RFC822.SIZE'; break; default: break; } } /** * A uidset with sorted uid's is available. We can use the cache */ if (isset($aUid) && $aUid) { // limit the cache to SQM_MAX_PAGES_IN_CACHE if (!$aMailbox['SHOWALL'][$iSetIndx] && isset($aMailbox['MSG_HEADERS'])) { $iMaxMsgs = $iLimit * SQM_MAX_PAGES_IN_CACHE; $iCacheSize = count($aMailbox['MSG_HEADERS']); if ($iCacheSize > $iMaxMsgs) { $iReduce = $iCacheSize - $iMaxMsgs; foreach ($aMailbox['MSG_HEADERS'] as $iUid => $value) { if ($iReduce) { unset($aMailbox['MSG_HEADERS'][$iUid]); } else { break; } --$iReduce; } } } $id_slice = array_slice($aUid, $start_msg - 1, $iLimit); /* do some funky cache checks */ if (isset($aMailbox['MSG_HEADERS']) && is_array($aMailbox['MSG_HEADERS'])) { // temp code, read_body del / next links fo not update fields. foreach ($aMailbox['MSG_HEADERS'] as $iUid => $aValue) { if (!isset($aValue['UID'])) { unset($aMailbox['MSG_HEADERS'][$iUid]); } } $aUidCached = array_keys($aMailbox['MSG_HEADERS']); } else { $aMailbox['MSG_HEADERS'] = array(); $aUidCached = array(); } $aUidNotCached = array_values(array_diff($id_slice, $aUidCached)); /** * $aUidNotCached contains an array with UID's which need to be fetched to * complete the needed message headers. */ if (count($aUidNotCached)) { $aMsgs = sqimap_get_small_header_list($imapConnection, $aUidNotCached, $aHeaderFields, $aFetchItems); // append the msgs to the existend headers $aMailbox['MSG_HEADERS'] += $aMsgs; } } else { /** * Initialize the sorted UID list or initiate a UID list with search * results and fetch the visible message headers */ if ($aMailbox['SEARCH'][$iSetIndx] != 'ALL') { // in case of a search request if ($aMailbox['SEARCH'][$iSetIndx] && $aMailbox['SORT'] == 0) { $aUid = sqimap_run_search($imapConnection, $aMailbox['SEARCH'][$iSetIndx], $aMailbox['CHARSET'][$iSetIndx]); } else { $iError = 0; $iError = _get_sorted_msgs_list($imapConnection, $aMailbox, $iError); $aUid = $aMailbox['UIDSET'][$iSetIndx]; } if (!$iError) { /** * Number of messages is the resultset */ $aMailbox['TOTAL'][$iSetIndx] = count($aUid); $id_slice = array_slice($aUid, $aMailbox['OFFSET'], $iLimit); if (count($id_slice)) { $aMailbox['MSG_HEADERS'] = sqimap_get_small_header_list($imapConnection, $id_slice, $aHeaderFields, $aFetchItems); } else { $iError = 1; // FIX ME, define an error code } } } else { // $iError = 0; $iError = _get_sorted_msgs_list($imapConnection, $aMailbox, $iError); $aUid = $aMailbox['UIDSET'][$iSetIndx]; if (!$iError) { /** * Number of messages is the resultset */ $aMailbox['TOTAL'][$iSetIndx] = count($aUid); $id_slice = array_slice($aUid, $aMailbox['OFFSET'], $iLimit); if (count($id_slice)) { $aMailbox['MSG_HEADERS'] = sqimap_get_small_header_list($imapConnection, $id_slice, $aHeaderFields, $aFetchItems); } else { $iError = 1; // FIX ME, define an error code } } } } return $iError; }
function bayesspam_get_tokens(&$imap_stream, $passed_id) { if ($GLOBALS['bayesdbhandle'] == null) { return; } $tokens = array(); $headers = sqimap_get_small_header_list($imap_stream, array($passed_id)); $version_array = split('\\.', $GLOBALS['version']); bayesspam_set_message_id($imap_stream, $passed_id); $lines1 = sqimap_run_command($imap_stream, 'FETCH ' . $passed_id . ':' . $passed_id . ' BODY[HEADER]<0.' . $GLOBALS['bayesspam_scan_size'] . '>', true, $response, $msg, $GLOBALS['uid_support']); $response = array_shift($lines1); preg_match('/\\{(\\d+)\\}/', $response, $matches); $lines2 = sqimap_run_command($imap_stream, 'FETCH ' . $passed_id . ':' . $passed_id . ' BODY[TEXT]<0.' . ($GLOBALS['bayesspam_scan_size'] - $matches[1]) . '>', true, $response, $msg, $GLOBALS['uid_support']); if ($version_array[0] == 1 && $version_array[1] <= 2) { if (!$headers[0]['FLAG_SEEN']) { sqimap_messages_remove_flag($imap_stream, $passed_id, $passed_id, 'Seen'); } } else { if ($version_array[0] == 1 && $version_array[1] == 5) { if (!isset($headers[$passed_id]['FLAGS']['\\seen'])) { sqimap_toggle_flag($imap_stream, $passed_id, '\\Seen', FALSE, TRUE); } } else { if (!$headers[0]['FLAG_SEEN']) { sqimap_messages_remove_flag($imap_stream, $passed_id, $passed_id, 'Seen', FALSE); } } } array_shift($lines2); $lines = array_merge($lines1, $lines2); $hdr_lines = count($lines1); unset($lines1); unset($lines2); $mime = ''; $encoding = ''; $decoded = ''; $content_type = ''; $in_html_tag = 0; for ($i = 0; $i < count($lines); $i++) { $line = $lines[$i]; if ($line == '') { continue; } if ($mime != '' && preg_match('/' . $mime . '/', $line)) { $encoding = ''; continue; } if (preg_match('/base64/i', $encoding)) { $decoded = ''; while (preg_match('/^([A-Za-z0-9+\\/]{4}){1,48}[\\n\\r]*/', $line) || preg_match('/^[A-Za-z0-9+\\/]+=+?[\\n\\r]*/', $line)) { $decoded .= base64_decode($line); if (preg_match('/[^a-zA-Z\\-\\.]$/', $decoded)) { $temp_tokens = bayesspam_parse_line($decoded, 'ENCODED'); foreach ($temp_tokens as $token) { $tokens[] = $token; } $decoded = ''; } $i++; if ($i < count($lines)) { $line = $lines[$i]; } else { break; } } $temp_tokens = bayesspam_parse_line($decoded, 'ENCODED'); foreach ($temp_tokens as $token) { $tokens[] = $token; } } if ($i == count($lines)) { break; } if (preg_match('/<html>/i', $line)) { $content_type = 'text/html'; } if (preg_match('/quoted\\-printable/', $encoding)) { $line = preg_replace('/=[\\r\\n]*$/', "=\n", $line); while (preg_match('/=\\n$/', $line)) { $tokens[] = 'CHEATER: Line Break'; $i++; $line = preg_replace('/=\\n$/', '', $line); $line = $line . $lines[$i]; } $line = quoted_printable_decode($line); } $oldline = $line; while ($oldline != ($line = preg_replace('/<!--.*?-->/', '', $line))) { $tokens[] = 'HTML: CHEATER'; $oldline = $line; } unset($oldline); if (preg_match('/html/', $content_type)) { if ($in_html_tag) { if (preg_match('/(.*?)>/', $line, $matches)) { $line = preg_replace('/(.*?)>/', ' ', $line); $html_arg .= $matches[1]; $in_html_tag = 0; if (preg_match('/quoted\\-printable/', $line)) { $html_tag = preg_replace('/=\\n ?/', '', $html_tag); $html_arg = preg_replace('/=\\n ?/', '', $html_arg); } $tokens[] = bayesspam_parse_html_tag($html_tag, $html_arg); $tokens[] = 'HTMLTAG: ' . $html_tag; $html_tag = ''; $html_arg = ''; } else { $html_arg .= ' ' . $line; $line = ''; continue; } } while (preg_match('/<[\\/]?([A-Za-z]+)([^>]*?)>/', $line, $matches)) { $line = preg_replace('/<[\\/]?([A-Za-z]+)([^>]*?)>/', '', $line, 1); $tokens[] = bayesspam_parse_html_tag($matches[1], $matches[2]); $tokens[] = 'HTMLTAG: ' . $matches[1]; } if (preg_match('/<([^ >]+)([^>]*)$/', $line, $matches)) { $line = preg_replace('/<([^ >]+)([^>]*)$/', '', $line); $html_tag = $matches[1]; $html_arg = $matches[2]; $in_html_tag = 1; } } if (preg_match('/^([A-Za-z-]+): ?([^\\n\\r]*)/', $line, $matches)) { $header = $matches[1]; $arguement = $matches[2]; $tokens[] = 'HEADERTYPE: ' . $header; if (preg_match('/(From|To|Cc)/i', $header)) { if (preg_match('/From/i', $header)) { $encoding = ''; $content_type = ''; } while (preg_match('/<([a-zA-Z0-9\\-_\\.]+?@([a-zA-Z0-9\\-_\\.]+?))>/', $arguement, $matches)) { $arguement = preg_replace('/<[a-zA-Z0-9\\-_\\.]+?@[a-zA-Z0-9\\-_\\.]+?>/', '', $arguement, 1); if ($matches[1]) { $tokens[] = 'EMAIL: ' . $matches[1]; } if ($matches[2]) { $tokens[] = 'DOMAIN: ' . $matches[2]; } } while (preg_match('/([a-zA-Z0-9\\-_\\.]+?@([a-zA-Z0-9\\-_\\.]+))/', $arguement, $matches)) { $arguement = preg_replace('/([a-zA-Z0-9\\-_\\.]+?@([a-zA-Z0-9\\-_\\.]+))/', '', $arguement); if ($matches[1]) { $tokens[] = 'EMAIL: ' . $matches[1]; } if ($matches[2]) { $tokens[] = 'DOMAIN: ' . $matches[2]; } } $temp_tokens = bayesspam_parse_line($arguement, 'HEADER'); foreach ($temp_tokens as $token) { $tokens[] = $token; } continue; } if (preg_match('/Subject/i', $header)) { $temp_tokens = bayesspam_parse_line($arguement, 'SUBJECT'); foreach ($temp_tokens as $token) { $tokens[] = $token; } continue; } if (preg_match('/Content-Type/i', $header)) { if (preg_match('/multipart\\//i', $arguement)) { $boundary = $arguement; if (preg_match('/boundary="(.*)"/', $arguement)) { $i++; $boundary = $lines[$i]; } if (preg_match('/boundary="(.*)"/', $boundary, $matches)) { $mime = $matches[1]; $mime = preg_replace('/(\\+|\\/|\\?|\\*|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\^|\\$|\\.)/', $matches[1], $mime); } } $content_type = $arguement; continue; } if (preg_match('/Content-Transfer-Encoding/i', $header)) { $encoding = $arguement; continue; } if (preg_match('/X-Text-Classification/', $header)) { $tokens[] = 'TEXTCLASS: ' . $arguement; continue; } if (preg_match('/(Thread-Index|X-UIDL|Message-ID|X-Text-Classification|X-Mime-Key)/i', $header)) { continue; } $temp_tokens = bayesspam_parse_line($arguement, 'HEADER'); foreach ($temp_tokens as $token) { $tokens[] = $token; } } else { if ($i < $hdr_lines) { $temp_tokens = bayesspam_parse_line($arguement, 'HEADER'); } else { $temp_tokens = bayesspam_parse_line($arguement, 'BODY'); } foreach ($temp_tokens as $token) { $tokens[] = $token; } } } return $tokens; }
function fillMessageArray($imapConnection, $id, $count) { return sqimap_get_small_header_list($imapConnection, $id); }
/** * 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'); } }