Example #1
0
 /**
  * Function to be executed in script shutdown
  * Registered with register_shutdown_function()
  */
 public function shutdown()
 {
     if (is_object($this->imap)) {
         $this->imap->close();
     }
     if (is_object($this->smtp)) {
         $this->smtp->disconnect();
     }
     foreach ($this->books as $book) {
         if (is_object($book)) {
             $book->close();
         }
     }
     // before closing the database connection, write session data
     if ($_SERVER['REMOTE_ADDR']) {
         session_write_close();
     }
     // write performance stats to logs/console
     if ($this->config->get('devel_mode')) {
         if (function_exists('memory_get_usage')) {
             $mem = show_bytes(memory_get_usage());
         }
         if (function_exists('memory_get_peak_usage')) {
             $mem .= '/' . show_bytes(memory_get_peak_usage());
         }
         $log = $this->task . ($this->action ? '/' . $this->action : '') . ($mem ? " [{$mem}]" : '');
         if (defined('RCMAIL_START')) {
             rcube_print_time(RCMAIL_START, $log);
         } else {
             console($log);
         }
     }
 }
Example #2
0
 /**
  * Parse message body for UUencoded attachments bodies
  *
  * @param rcube_message_part $part Message part to decode
  * @return array
  */
 function uu_decode(&$part)
 {
     // @TODO: messages may be huge, hadle body via file
     if (!isset($part->body)) {
         $part->body = $this->imap->get_message_part($this->uid, $part->mime_id, $part);
     }
     $parts = array();
     // FIXME: line length is max.65?
     $uu_regexp = '/begin [0-7]{3,4} ([^\\n]+)\\n(([\\x21-\\x7E]{0,65}\\n)+)`\\nend/s';
     if (preg_match_all($uu_regexp, $part->body, $matches, PREG_SET_ORDER)) {
         // remove attachments bodies from the message body
         $part->body = preg_replace($uu_regexp, '', $part->body);
         // update message content-type
         $part->ctype_primary = 'multipart';
         $part->ctype_secondary = 'mixed';
         $part->mimetype = $part->ctype_primary . '/' . $part->ctype_secondary;
         // add attachments to the structure
         foreach ($matches as $pid => $att) {
             $uupart = new rcube_message_part();
             $uupart->filename = trim($att[1]);
             $uupart->encoding = 'stream';
             $uupart->body = convert_uudecode($att[2]);
             $uupart->size = strlen($uupart->body);
             $uupart->mime_id = 'uu.' . $part->mime_id . '.' . $pid;
             $ctype = rc_mime_content_type($uupart->body, $uupart->filename, 'application/octet-stream', true);
             $uupart->mimetype = $ctype;
             list($uupart->ctype_primary, $uupart->ctype_secondary) = explode('/', $ctype);
             $parts[] = $uupart;
             unset($matches[$pid]);
         }
     }
     return $parts;
 }
 /**
  * Fetches thread data from IMAP server
  */
 private function get_thread_data($mailbox, $mbox_data = array())
 {
     if (empty($mbox_data)) {
         $mbox_data = $this->imap->folder_data($mailbox);
     }
     if ($mbox_data['EXISTS']) {
         // get all threads (default sort order)
         return $this->imap->threads_direct($mailbox);
     }
     return new rcube_result_thread($mailbox, '* THREAD');
 }
 /**
  * Fetches index data from IMAP server
  */
 private function get_index_data($mailbox, $sort_field, $sort_order, $mbox_data = array())
 {
     if (empty($mbox_data)) {
         $mbox_data = $this->imap->folder_data($mailbox);
     }
     if ($mbox_data['EXISTS']) {
         // fetch sorted sequence numbers
         $index = $this->imap->index_direct($mailbox, $sort_field, $sort_order);
     } else {
         $index = new rcube_result_index($mailbox, '* SORT');
     }
     return $index;
 }
 /**
  * __construct
  *
  * Provide a uid, and parse message structure.
  *
  * @param string $uid The message UID.
  *
  * @uses rcmail::get_instance()
  * @uses rcube_imap::decode_mime_string()
  * @uses self::set_safe()
  *
  * @see self::$app, self::$imap, self::$opt, self::$structure
  */
 function __construct($uid)
 {
     $this->app = rcmail::get_instance();
     $this->imap = $this->app->imap;
     $this->uid = $uid;
     $this->headers = $this->imap->get_headers($uid, NULL, true, true);
     $this->subject = rcube_imap::decode_mime_string($this->headers->subject, $this->headers->charset);
     list(, $this->sender) = each($this->imap->decode_address_list($this->headers->from));
     $this->set_safe(intval($_GET['_safe']) || $_SESSION['safe_messages'][$uid]);
     $this->opt = array('safe' => $this->is_safe, 'prefer_html' => $this->app->config->get('prefer_html'), 'get_url' => rcmail_url('get', array('_mbox' => $this->imap->get_mailbox_name(), '_uid' => $uid)));
     if ($this->structure = $this->imap->get_structure($uid, $this->headers->body_structure)) {
         $this->get_mime_numbers($this->structure);
         $this->parse_structure($this->structure);
     } else {
         $this->body = $this->imap->get_body($uid);
     }
 }
 /**
  * Collect the email address of a just-sent email recipients into
  * the automatic addressbook (if it's not already in another
  * addressbook). 
  */
 public function register_recipients($p)
 {
     $rcmail = rcmail::get_instance();
     if (!$rcmail->config->get('use_auto_abook', true)) {
         return;
     }
     $headers = $p['headers'];
     if (!class_exists('rcube_mime')) {
         // RC < 0.8 compatibility code
         $IMAP = new rcube_imap(null);
         $all_recipients = array_merge($IMAP->decode_address_list($headers['To'], null, true, $headers['charset']), $IMAP->decode_address_list($headers['Cc'], null, true, $headers['charset']), $IMAP->decode_address_list($headers['Bcc'], null, true, $headers['charset']));
     } else {
         $all_recipients = array_merge(rcube_mime::decode_address_list($headers['To'], null, true, $headers['charset']), rcube_mime::decode_address_list($headers['Cc'], null, true, $headers['charset']), rcube_mime::decode_address_list($headers['Bcc'], null, true, $headers['charset']));
     }
     require_once dirname(__FILE__) . '/automatic_addressbook_backend.php';
     $CONTACTS = new automatic_addressbook_backend($rcmail->db, $rcmail->user->ID);
     foreach ($all_recipients as $recipient) {
         // Bcc and Cc can be empty
         if ($recipient['mailto'] != '') {
             $contact = array('email' => $recipient['mailto'], 'name' => $recipient['name']);
             // use email address part for name
             if (empty($contact['name']) || $contact['name'] == $contact['email']) {
                 $contact['name'] = ucfirst(preg_replace('/[\\.\\-]/', ' ', substr($contact['email'], 0, strpos($contact['email'], '@'))));
             }
             /* We only want to add the contact to the collected contacts
              * address book if it is not already in an addressbook, so we
              * first lookup in every address source.
              */
             $book_types = (array) $rcmail->config->get('autocomplete_addressbooks', 'sql');
             foreach ($book_types as $id) {
                 $abook = $rcmail->get_address_book($id);
                 $previous_entries = $abook->search('email', $contact['email'], false, false);
                 if ($previous_entries->count) {
                     break;
                 }
             }
             if (!$previous_entries->count) {
                 $plugin = $rcmail->plugins->exec_hook('contact_create', array('record' => $contact, 'source' => $this->abook_id));
                 if (!$plugin['abort']) {
                     $CONTACTS->insert($contact, false);
                 }
             }
         }
     }
 }
Example #7
0
 /**
  * Fetches index data from IMAP server
  */
 private function get_index_data($mailbox, $sort_field, $sort_order, $mbox_data = array())
 {
     $data = array();
     if (empty($mbox_data)) {
         $mbox_data = $this->imap->mailbox_data($mailbox);
     }
     // Prevent infinite loop.
     // It happens when rcube_imap::message_index_direct() is called.
     // There id2uid() is called which will again call get_index() and so on.
     if (!$sort_field && !$this->skip_deleted) {
         $this->icache['pending_index_update'] = true;
     }
     if ($mbox_data['EXISTS']) {
         // fetch sorted sequence numbers
         $data_seq = $this->imap->message_index_direct($mailbox, $sort_field, $sort_order);
         // fetch UIDs
         if (!empty($data_seq)) {
             // Seek in internal cache
             if (array_key_exists('index', (array) $this->icache[$mailbox]) && array_key_exists('result', (array) $this->icache[$mailbox]['index'])) {
                 $data_uid = $this->icache[$mailbox]['index']['result'];
             } else {
                 $data_uid = $this->imap->conn->fetchUIDs($mailbox, $data_seq);
             }
             // build index
             if (!empty($data_uid)) {
                 foreach ($data_seq as $seq) {
                     if ($uid = $data_uid[$seq]) {
                         $data[$seq] = $uid;
                     }
                 }
             }
         }
     }
     // Reset internal flags
     $this->icache['pending_index_update'] = false;
     return $data;
 }
Example #8
0
 /**
  * Decode a mime-encoded string to internal charset
  *
  * @param string $input    Header value
  * @param string $fallback Fallback charset if none specified
  *
  * @return string Decoded string
  * @static
  */
 public static function decode_mime_string($input, $fallback = null)
 {
     // Initialize variable
     $out = '';
     // Iterate instead of recursing, this way if there are too many values we don't have stack overflows
     // rfc: all line breaks or other characters not found
     // in the Base64 Alphabet must be ignored by decoding software
     // delete all blanks between MIME-lines, differently we can
     // receive unnecessary blanks and broken utf-8 symbols
     $input = preg_replace("/\\?=\\s+=\\?/", '?==?', $input);
     // Check if there is stuff to decode
     if (strpos($input, '=?') !== false) {
         // Loop through the string to decode all occurences of =? ?= into the variable $out
         while (($pos = strpos($input, '=?')) !== false) {
             // Append everything that is before the text to be decoded
             $out .= substr($input, 0, $pos);
             // Get the location of the text to decode
             $end_cs_pos = strpos($input, "?", $pos + 2);
             $end_en_pos = strpos($input, "?", $end_cs_pos + 1);
             $end_pos = strpos($input, "?=", $end_en_pos + 1);
             // Extract the encoded string
             $encstr = substr($input, $pos + 2, $end_pos - $pos - 2);
             // Extract the remaining string
             $input = substr($input, $end_pos + 2);
             // Decode the string fragement
             $out .= rcube_imap::_decode_mime_string_part($encstr);
         }
         // Deocde the rest (if any)
         if (strlen($input) != 0) {
             $out .= rcube_imap::decode_mime_string($input, $fallback);
         }
         // return the results
         return $out;
     }
     // no encoding information, use fallback
     return rcube_charset_convert($input, !empty($fallback) ? $fallback : rcmail::get_instance()->config->get('default_charset', 'ISO-8859-1'));
 }
 /**
  * Checks wether recipients exist in any of the addressbooks.
  *
  * @param array $args Default hook parameters.
  *
  * @return void
  */
 public function check_recipients($args)
 {
     $rcmail = rcmail::get_instance();
     // don't process the sent message, if it's a 'Read Receipt' response
     if (isset($args['headers']['Content-Type']) && strpos($args['headers']['Content-Type'], 'report-type=disposition-notification') !== false) {
         return $args;
     }
     $rcube_imap = new rcube_imap(null);
     // build recipients array
     $recipients = $rcube_imap->decode_address_list($args['headers']['To']);
     if (isset($args['headers']['Cc'])) {
         $recipients = array_merge($recipients, $rcube_imap->decode_address_list($args['headers']['Cc']));
     }
     if (isset($args['headers']['Bcc'])) {
         $recipients = array_merge($recipients, $rcube_imap->decode_address_list($args['headers']['Bcc']));
     }
     // stores contacts that don't exist in current address books
     $new_contacts = array();
     // iterate over recipients and search for them in address books
     foreach ($recipients as $recipient) {
         // flag to denote if the current recipient doesn't exist in any of the address books
         $is_new_contact = true;
         // if we dont want to list users in same domain as us for some reason
         // example: globaladdressbook plugin with all domain users inside
         if (!$this->rcmail->config->get('recipient_to_contact_addressbooks')) {
             // get current recipient domain
             $recipient_domain = preg_replace('/^[^@]*@(.*)$/', '$1', $recipient['mailto']);
             // get identity used to send email
             $identity = $rcmail->user->get_identity();
             // get current identity domain
             $identity_domain = preg_replace('/^[^@]*@(.*)$/', '$1', $identity['email']);
             // check if recipient domain match with this identify domain
             // if match, continue loop and ignore recipient
             if ($recipient_domain == $identity_domain) {
                 unset($recipient_domain);
                 unset($identity);
                 unset($identity_domain);
                 $is_new_contact = false;
                 continue;
             }
         }
         // interate over over address books and search for a contact with the same email address
         foreach ($this->addressbooks as $abook_id => $address_source) {
             $address_book = $this->rcmail->get_address_book($abook_id);
             $search_result = $address_book->search('email', $recipient['mailto']);
             // the contact already exist. skip the rest address books and move to next recipient
             if ($search_result->count > 0) {
                 $is_new_contact = false;
                 break;
             }
         }
         // store the non-existing recipient
         if ($is_new_contact) {
             $new_contacts[] = $recipient;
         }
     }
     if (!empty($new_contacts)) {
         $_SESSION['recipient_to_contact'] = $new_contacts;
     }
 }
Example #10
0
    $imap_port = $RCI->getprop('default_port');
    $a_host = parse_url($imap_host);
    if ($a_host['host']) {
        $imap_host = $a_host['host'];
        $imap_ssl = isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl', 'imaps', 'tls')) ? $a_host['scheme'] : null;
        if (isset($a_host['port'])) {
            $imap_port = $a_host['port'];
        } else {
            if ($imap_ssl && $imap_ssl != 'tls' && (!$imap_port || $imap_port == 143)) {
                $imap_port = 993;
            }
        }
    }
    $imap_host = idn_to_ascii($imap_host);
    $imap_user = idn_to_ascii($_POST['_user']);
    $imap = new rcube_imap(null);
    $imap->set_options(array('auth_type' => $RCI->getprop('imap_auth_type'), 'debug' => $RCI->getprop('imap_debug'), 'socket_options' => $RCI->getprop('imap_conn_options')));
    if ($imap->connect($imap_host, $imap_user, $_POST['_pass'], $imap_port, $imap_ssl)) {
        $RCI->pass('IMAP connect', 'SORT capability: ' . ($imap->get_capability('SORT') ? 'yes' : 'no'));
        $imap->close();
    } else {
        $RCI->fail('IMAP connect', $RCI->get_error());
    }
}
?>

<p><input type="submit" name="imaptest" value="Check login" /></p>

</form>

<hr />
 /**
  * Copy of rcube_imap::search_index()
  */
 protected function search_index()
 {
     $criteria = $this->search;
     $charset = $this->charset;
     $imap = $this->worker->get_imap();
     if (!$imap->connected()) {
         trigger_error("No IMAP connection for {$this->folder}", E_USER_WARNING);
         if ($this->threading) {
             return new rcube_result_thread($this->folder);
         } else {
             return new rcube_result_index($this->folder);
         }
     }
     if ($this->worker->options['skip_deleted'] && !preg_match('/UNDELETED/', $criteria)) {
         $criteria = 'UNDELETED ' . $criteria;
     }
     // unset CHARSET if criteria string is ASCII, this way
     // SEARCH won't be re-sent after "unsupported charset" response
     if ($charset && $charset != 'US-ASCII' && is_ascii($criteria)) {
         $charset = 'US-ASCII';
     }
     if ($this->threading) {
         $threads = $imap->thread($this->folder, $this->threading, $criteria, true, $charset);
         // Error, try with US-ASCII (RFC5256: SORT/THREAD must support US-ASCII and UTF-8,
         // but I've seen that Courier doesn't support UTF-8)
         if ($threads->is_error() && $charset && $charset != 'US-ASCII') {
             $threads = $imap->thread($this->folder, $this->threading, rcube_imap::convert_criteria($criteria, $charset), true, 'US-ASCII');
         }
         return $threads;
     }
     if ($this->sort_field) {
         $messages = $imap->sort($this->folder, $this->sort_field, $criteria, true, $charset);
         // Error, try with US-ASCII (RFC5256: SORT/THREAD must support US-ASCII and UTF-8,
         // but I've seen Courier with disabled UTF-8 support)
         if ($messages->is_error() && $charset && $charset != 'US-ASCII') {
             $messages = $imap->sort($this->folder, $this->sort_field, rcube_imap::convert_criteria($criteria, $charset), true, 'US-ASCII');
         }
     }
     if (!$messages || $messages->is_error()) {
         $messages = $imap->search($this->folder, ($charset && $charset != 'US-ASCII' ? "CHARSET {$charset} " : '') . $criteria, true);
         // Error, try with US-ASCII (some servers may support only US-ASCII)
         if ($messages->is_error() && $charset && $charset != 'US-ASCII') {
             $messages = $imap->search($this->folder, rcube_imap::convert_criteria($criteria, $charset), true);
         }
     }
     return $messages;
 }
 /**
  * Checks wether recipients exist in any of the addressbooks.
  *
  * @param array $args Default hook parameters.
  *
  * @return void
  */
 public function check_recipients($args)
 {
     // don't process the sent message, if it's a 'Read Receipt' response
     if (isset($args['headers']['Content-Type']) && strpos($args['headers']['Content-Type'], 'report-type=disposition-notification') !== false) {
         return $args;
     }
     $rcube_imap = new rcube_imap(null);
     // build recipients array
     $recipients = $rcube_imap->decode_address_list($args['headers']['To']);
     if (isset($args['headers']['Cc'])) {
         $recipients = array_merge($recipients, $rcube_imap->decode_address_list($args['headers']['Cc']));
     }
     if (isset($args['headers']['Bcc'])) {
         $recipients = array_merge($recipients, $rcube_imap->decode_address_list($args['headers']['Bcc']));
     }
     // stores contacts that don't exist in current address books
     $new_contacts = array();
     // iterate over recipients and search for them in address books
     foreach ($recipients as $recipient) {
         // flag to denote if the current recipient doesn't exist in any of the address books
         $is_new_contact = true;
         // interate over over address books and search for a contact with the same email address
         foreach ($this->addressbooks as $abook_id => $address_source) {
             $address_book = $this->rcmail->get_address_book($abook_id);
             $search_result = $address_book->search('email', $recipient['mailto']);
             // the contact already exist. skip the rest address books and move to next recipient
             if ($search_result->count > 0) {
                 $is_new_contact = false;
                 break;
             }
         }
         // store the non-existing recipient
         if ($is_new_contact) {
             $new_contacts[] = $recipient;
         }
     }
     if (!empty($new_contacts)) {
         $_SESSION['recipient_to_contact'] = $new_contacts;
     }
 }
Example #13
0
    $imap_port = $RCI->getprop('default_port');
    $a_host = parse_url($imap_host);
    if ($a_host['host']) {
        $imap_host = $a_host['host'];
        $imap_ssl = isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl', 'imaps', 'tls')) ? $a_host['scheme'] : null;
        if (isset($a_host['port'])) {
            $imap_port = $a_host['port'];
        } else {
            if ($imap_ssl && $imap_ssl != 'tls' && (!$imap_port || $imap_port == 143)) {
                $imap_port = 993;
            }
        }
    }
    $imap_host = idn_to_ascii($imap_host);
    $imap_user = idn_to_ascii($_POST['_user']);
    $imap = new rcube_imap(null);
    if ($imap->connect($imap_host, $imap_user, $_POST['_pass'], $imap_port, $imap_ssl)) {
        $RCI->pass('IMAP connect', 'SORT capability: ' . ($imap->get_capability('SORT') ? 'yes' : 'no'));
        $imap->close();
    } else {
        $RCI->fail('IMAP connect', $RCI->get_error());
    }
}
?>

<p><input type="submit" name="imaptest" value="Check login" /></p>

</form>

<hr />
Example #14
0
 /**
  * Fixes some user preferences according to namespace handling change.
  * Old Roundcube versions were using folder names with removed namespace prefix.
  * Now we need to add the prefix on servers where personal namespace has prefix.
  *
  * @param rcube_user $user User object
  */
 private function fix_namespace_settings($user)
 {
     $prefix = $this->imap->get_namespace('prefix');
     $prefix_len = strlen($prefix);
     if (!$prefix_len) {
         return;
     }
     $prefs = $this->config->all();
     if (!empty($prefs['namespace_fixed'])) {
         return;
     }
     // Build namespace prefix regexp
     $ns = $this->imap->get_namespace();
     $regexp = array();
     foreach ($ns as $entry) {
         if (!empty($entry)) {
             foreach ($entry as $item) {
                 if (strlen($item[0])) {
                     $regexp[] = preg_quote($item[0], '/');
                 }
             }
         }
     }
     $regexp = '/^(' . implode('|', $regexp) . ')/';
     // Fix preferences
     $opts = array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox', 'archive_mbox');
     foreach ($opts as $opt) {
         if ($value = $prefs[$opt]) {
             if ($value != 'INBOX' && !preg_match($regexp, $value)) {
                 $prefs[$opt] = $prefix . $value;
             }
         }
     }
     if (!empty($prefs['default_imap_folders'])) {
         foreach ($prefs['default_imap_folders'] as $idx => $name) {
             if ($name != 'INBOX' && !preg_match($regexp, $name)) {
                 $prefs['default_imap_folders'][$idx] = $prefix . $name;
             }
         }
     }
     if (!empty($prefs['search_mods'])) {
         $folders = array();
         foreach ($prefs['search_mods'] as $idx => $value) {
             if ($idx != 'INBOX' && $idx != '*' && !preg_match($regexp, $idx)) {
                 $idx = $prefix . $idx;
             }
             $folders[$idx] = $value;
         }
         $prefs['search_mods'] = $folders;
     }
     if (!empty($prefs['message_threading'])) {
         $folders = array();
         foreach ($prefs['message_threading'] as $idx => $value) {
             if ($idx != 'INBOX' && !preg_match($regexp, $idx)) {
                 $idx = $prefix . $idx;
             }
             $folders[$prefix . $idx] = $value;
         }
         $prefs['message_threading'] = $folders;
     }
     if (!empty($prefs['collapsed_folders'])) {
         $folders = explode('&&', $prefs['collapsed_folders']);
         $count = count($folders);
         $folders_str = '';
         if ($count) {
             $folders[0] = substr($folders[0], 1);
             $folders[$count - 1] = substr($folders[$count - 1], 0, -1);
         }
         foreach ($folders as $value) {
             if ($value != 'INBOX' && !preg_match($regexp, $value)) {
                 $value = $prefix . $value;
             }
             $folders_str .= '&' . $value . '&';
         }
         $prefs['collapsed_folders'] = $folders_str;
     }
     $prefs['namespace_fixed'] = true;
     // save updated preferences and reset imap settings (default folders)
     $user->save_prefs($prefs);
     $this->set_imap_prop();
 }
Example #15
0
 /**
  * Decode a message header value
  *
  * @param string  $input         Header value
  * @param boolean $remove_quotas Remove quotes if necessary
  * @return string Decoded string
  */
 function decode_header($input, $remove_quotes = false)
 {
     $str = rcube_imap::decode_mime_string((string) $input, $this->default_charset);
     if ($str[0] == '"' && $remove_quotes) {
         $str = str_replace('"', '', $str);
     }
     return $str;
 }