| | |
| | | if ($use_ssl && extension_loaded('openssl')) |
| | | $ICL_SSL = $use_ssl == 'imaps' ? 'ssl' : $use_ssl; |
| | | else if ($use_ssl) { |
| | | raise_error(array('code' => 403, 'type' => 'imap', 'file' => __FILE__, |
| | | 'message' => 'Open SSL not available;'), TRUE, FALSE); |
| | | raise_error(array('code' => 403, 'type' => 'imap', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "Open SSL not available"), TRUE, FALSE); |
| | | $port = 143; |
| | | } |
| | | |
| | | $ICL_PORT = $port; |
| | | $IMAP_USE_INTERNAL_DATE = false; |
| | | |
| | | |
| | | $attempt = 0; |
| | | do { |
| | | $data = rcmail::get_instance()->plugins->exec_hook('imap_connect', array('host' => $host, 'user' => $user, 'attempt' => ++$attempt)); |
| | |
| | | else if (!$this->conn && $GLOBALS['iil_error']) |
| | | { |
| | | $this->error_code = $GLOBALS['iil_errornum']; |
| | | raise_error(array('code' => 403, |
| | | 'type' => 'imap', |
| | | 'message' => $GLOBALS['iil_error']), TRUE, FALSE); |
| | | raise_error(array('code' => 403, 'type' => 'imap', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => $GLOBALS['iil_error']), TRUE, FALSE); |
| | | } |
| | | |
| | | // get server properties |
| | | if ($this->conn) |
| | | { |
| | | if (!empty($this->conn->delimiter)) |
| | | $this->delimiter = $this->conn->delimiter; |
| | | if (!empty($this->conn->rootdir)) |
| | | { |
| | | $this->set_rootdir($this->conn->rootdir); |
| | | $this->root_ns = preg_replace('/[.\/]$/', '', $this->conn->rootdir); |
| | | } |
| | | if (empty($this->delimiter)) |
| | | $this->get_hierarchy_delimiter(); |
| | | } |
| | | |
| | | return $this->conn ? TRUE : FALSE; |
| | |
| | | { |
| | | if ($this->skip_deleted) { |
| | | // @TODO: this could be cached |
| | | $msg_index = $this->_search_index($mailbox, 'ALL UNDELETED'); |
| | | $max = max($msg_index); |
| | | list($begin, $end) = $this->_get_message_range(count($msg_index), $page); |
| | | $msg_index = array_slice($msg_index, $begin, $end-$begin); |
| | | if ($msg_index = $this->_search_index($mailbox, 'ALL UNDELETED')) { |
| | | $max = max($msg_index); |
| | | list($begin, $end) = $this->_get_message_range(count($msg_index), $page); |
| | | $msg_index = array_slice($msg_index, $begin, $end-$begin); |
| | | } |
| | | } else if ($max = iil_C_CountMessages($this->conn, $mailbox)) { |
| | | list($begin, $end) = $this->_get_message_range($max, $page); |
| | | $msg_index = range($begin+1, $end); |
| | | } else |
| | | return array(); |
| | | $msg_index = array(); |
| | | |
| | | if ($slice) |
| | | $msg_index = array_slice($msg_index, ($this->sort_order == 'DESC' ? 0 : -$slice), $slice); |
| | | |
| | | // fetch reqested headers from server |
| | | $this->_fetch_headers($mailbox, join(",", $msg_index), $a_msg_headers, $cache_key); |
| | | if ($msg_index) |
| | | $this->_fetch_headers($mailbox, join(",", $msg_index), $a_msg_headers, $cache_key); |
| | | } |
| | | // use SORT command |
| | | else if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field, $this->skip_deleted ? 'UNDELETED' : ''))) |
| | |
| | | $this->_fetch_headers($mailbox, join(',', $msg_index), $a_msg_headers, $cache_key); |
| | | } |
| | | // fetch specified header for all messages and sort |
| | | else |
| | | else if ($a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:*", $this->sort_field, $this->skip_deleted)) |
| | | { |
| | | $a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:*", $this->sort_field, $this->skip_deleted); |
| | | |
| | | if (empty($a_index)) |
| | | return array(); |
| | | |
| | | asort($a_index); // ASC |
| | | $msg_index = array_keys($a_index); |
| | | $max = max($msg_index); |
| | |
| | | * |
| | | * @access private |
| | | */ |
| | | function &_structure_part($part, $count=0, $parent='', $raw_headers=null) |
| | | function &_structure_part($part, $count=0, $parent='', $mime_headers=null, $raw_headers=null) |
| | | { |
| | | $struct = new rcube_message_part; |
| | | $struct->mime_id = empty($parent) ? (string)$count : "$parent.$count"; |
| | |
| | | |
| | | // build parts list for headers pre-fetching |
| | | for ($i=0, $count=0; $i<count($part); $i++) |
| | | if (is_array($part[$i]) && count($part[$i]) > 3) |
| | | // fetch message headers if message/rfc822 or named part (could contain Content-Location header) |
| | | if (strtolower($part[$i][0]) == 'message' || |
| | | (in_array('name', (array)$part[$i][2]) && (empty($part[$i][3]) || $part[$i][3]=='NIL'))) { |
| | | $part_headers[] = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1; |
| | | } |
| | | |
| | | if (is_array($part[$i]) && count($part[$i]) > 3) { |
| | | // fetch message headers if message/rfc822 or named part (could contain Content-Location header) |
| | | if (!is_array($part[$i][0])) { |
| | | $tmp_part_id = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1; |
| | | if (strtolower($part[$i][0]) == 'message' && strtolower($part[$i][1]) == 'rfc822') { |
| | | $raw_part_headers[] = $tmp_part_id; |
| | | $mime_part_headers[] = $tmp_part_id; |
| | | } |
| | | else if (in_array('name', (array)$part[$i][2]) && (empty($part[$i][3]) || $part[$i][3]=='NIL')) { |
| | | $mime_part_headers[] = $tmp_part_id; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // pre-fetch headers of all parts (in one command for better performance) |
| | | if ($part_headers) |
| | | $part_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox, $this->_msg_id, $part_headers); |
| | | // @TODO: we could do this before _structure_part() call, to fetch |
| | | // headers for parts on all levels |
| | | if ($mime_part_headers) |
| | | $mime_part_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox, |
| | | $this->_msg_id, $mime_part_headers); |
| | | // we'll need a real content-type of message/rfc822 part |
| | | if ($raw_part_headers) |
| | | $raw_part_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox, |
| | | $this->_msg_id, $raw_part_headers, false); |
| | | |
| | | $struct->parts = array(); |
| | | for ($i=0, $count=0; $i<count($part); $i++) |
| | | if (is_array($part[$i]) && count($part[$i]) > 3) { |
| | | $tmp_part_id = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1; |
| | | $struct->parts[] = $this->_structure_part($part[$i], ++$count, $struct->mime_id, |
| | | $part_headers[$struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1]); |
| | | $mime_part_headers[$tmp_part_id], $raw_part_headers[$tmp_part_id]); |
| | | } |
| | | |
| | | return $struct; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | // regular part |
| | | $struct->ctype_primary = strtolower($part[0]); |
| | | $struct->ctype_secondary = strtolower($part[1]); |
| | |
| | | |
| | | // fetch message headers if message/rfc822 or named part (could contain Content-Location header) |
| | | if ($struct->ctype_primary == 'message' || ($struct->ctype_parameters['name'] && !$struct->content_id)) { |
| | | if (empty($raw_headers)) |
| | | $raw_headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, false, $struct->mime_id); |
| | | $struct->headers = $this->_parse_headers($raw_headers) + $struct->headers; |
| | | } |
| | | if (empty($mime_headers)) |
| | | $mime_headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, false, $struct->mime_id); |
| | | $struct->headers = $this->_parse_headers($mime_headers) + $struct->headers; |
| | | |
| | | // get real headers for message of type 'message/rfc822' |
| | | if ($struct->mimetype == 'message/rfc822') { |
| | | if (empty($raw_headers)) |
| | | $raw_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox, $this->_msg_id, (array)$struct->mime_id, false); |
| | | $struct->real_headers = $this->_parse_headers($raw_headers); |
| | | |
| | | // get real content-type of message/rfc822 |
| | | if (preg_match('/^([a-z0-9_\/-]+)/i', $struct->real_headers['content-type'], $matches)) { |
| | | $struct->real_mimetype = strtolower($matches[1]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if ($struct->ctype_primary=='message') { |
| | | if (is_array($part[8]) && empty($struct->parts)) |
| | | if (is_array($part[8]) && $di != 8 && empty($struct->parts)) |
| | | $struct->parts[] = $this->_structure_part($part[8], ++$count, $struct->mime_id); |
| | | } |
| | | } |
| | | |
| | | // normalize filename property |
| | | $this->_set_part_filename($struct, $raw_headers); |
| | | $this->_set_part_filename($struct, $mime_headers); |
| | | |
| | | return $struct; |
| | | } |
| | |
| | | /** |
| | | * Append a mail message (source) to a specific mailbox |
| | | * |
| | | * @param string Target mailbox |
| | | * @param string Message source |
| | | * @param string Target mailbox |
| | | * @param string The message source string or filename |
| | | * @param string Headers string if $message contains only the body |
| | | * @param boolean True if $message is a filename |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | function save_message($mbox_name, &$message) |
| | | function save_message($mbox_name, &$message, $headers='', $is_file=false) |
| | | { |
| | | $mailbox = $this->mod_mailbox($mbox_name); |
| | | |
| | | // make sure mailbox exists |
| | | if (($mailbox == 'INBOX') || in_array($mailbox, $this->_list_mailboxes())) |
| | | $saved = iil_C_Append($this->conn, $mailbox, $message); |
| | | if (($mailbox == 'INBOX') || in_array($mailbox, $this->_list_mailboxes())) { |
| | | if ($is_file) { |
| | | $separator = rcmail::get_instance()->config->header_delimiter(); |
| | | $saved = iil_C_AppendFromFile($this->conn, $mailbox, $message, |
| | | $headers, $separator.$separator); |
| | | } |
| | | else |
| | | $saved = iil_C_Append($this->conn, $mailbox, $message); |
| | | } |
| | | |
| | | if ($saved) |
| | | { |
| | |
| | | // make sure mailbox exists |
| | | if ($to_mbox != 'INBOX' && !in_array($to_mbox, $this->_list_mailboxes())) |
| | | { |
| | | if (in_array($to_mbox_in, $this->default_folders)) |
| | | $this->create_mailbox($to_mbox_in, TRUE); |
| | | if (in_array($tbox, $this->default_folders)) |
| | | $this->create_mailbox($tbox, TRUE); |
| | | else |
| | | return FALSE; |
| | | } |
| | |
| | | foreach ($this->default_folders as $folder) |
| | | { |
| | | $abs_name = $this->mod_mailbox($folder); |
| | | if (!in_array_nocase($abs_name, $a_folders)) |
| | | if (!in_array($abs_name, $a_folders)) |
| | | $this->create_mailbox($folder, TRUE); |
| | | else if (!in_array_nocase($abs_name, $a_subscribed)) |
| | | else if (!in_array($abs_name, $a_subscribed)) |
| | | $this->subscribe($folder); |
| | | } |
| | | } |
| | |
| | | if ((!empty($this->root_ns) && $this->root_ns == $mbox_name) || $mbox_name == 'INBOX') |
| | | return $mbox_name; |
| | | |
| | | if (!empty($this->root_dir) && $mode=='in') |
| | | $mbox_name = $this->root_dir.$this->delimiter.$mbox_name; |
| | | else if (strlen($this->root_dir) && $mode=='out') |
| | | $mbox_name = substr($mbox_name, strlen($this->root_dir)+1); |
| | | |
| | | if (!empty($this->root_dir)) { |
| | | if ($mode=='in') |
| | | $mbox_name = $this->root_dir.$this->delimiter.$mbox_name; |
| | | else if (!empty($mbox_name)) // $mode=='out' |
| | | $mbox_name = substr($mbox_name, strlen($this->root_dir)+1); |
| | | } |
| | | |
| | | return $mbox_name; |
| | | } |
| | | |
| | |
| | | { |
| | | if (!$mbox_name) |
| | | $mbox_name = $this->mailbox; |
| | | |
| | | $index = array_flip((array)$this->uid_id_map[$mbox_name]); |
| | | if (isset($index[$id])) |
| | | $uid = $index[$id]; |
| | | else |
| | | { |
| | | $uid = iil_C_ID2UID($this->conn, $mbox_name, $id); |
| | | $this->uid_id_map[$mbox_name][$uid] = $id; |
| | | } |
| | | |
| | | if ($uid = array_search($id, (array)$this->uid_id_map[$mbox_name])) |
| | | return $uid; |
| | | |
| | | $uid = iil_C_ID2UID($this->conn, $mbox_name, $id); |
| | | $this->uid_id_map[$mbox_name][$uid] = $id; |
| | | |
| | | return $uid; |
| | | } |
| | |
| | | private function _parse_headers($headers) |
| | | { |
| | | $a_headers = array(); |
| | | $headers = preg_replace('/\r?\n(\t| )+/', ' ', $headers); |
| | | $lines = explode("\n", $headers); |
| | | $c = count($lines); |
| | | for ($i=0; $i<$c; $i++) |