Пример #1
0
 /**
  * __construct
  *
  * Provide a uid, and parse message structure.
  *
  * @param string $uid    The message UID.
  * @param string $folder Folder name
  *
  * @see self::$app, self::$storage, self::$opt, self::$parts
  */
 function __construct($uid, $folder = null)
 {
     $this->uid = $uid;
     $this->app = rcube::get_instance();
     $this->storage = $this->app->get_storage();
     $this->folder = strlen($folder) ? $folder : $this->storage->get_folder();
     $this->storage->set_options(array('all_headers' => true));
     // Set current folder
     $this->storage->set_folder($this->folder);
     $this->headers = $this->storage->get_message($uid);
     if (!$this->headers) {
         return;
     }
     $this->mime = new rcube_mime($this->headers->charset);
     $this->subject = $this->mime->decode_mime_string($this->headers->subject);
     list(, $this->sender) = each($this->mime->decode_address_list($this->headers->from, 1));
     $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' => $this->app->url(array('action' => 'get', 'mbox' => $this->storage->get_folder(), 'uid' => $uid)));
     if (!empty($this->headers->structure)) {
         $this->get_mime_numbers($this->headers->structure);
         $this->parse_structure($this->headers->structure);
     } else {
         $this->body = $this->storage->get_body($uid);
     }
     // notify plugins and let them analyze this structured message object
     $this->app->plugins->exec_hook('message_load', array('object' => $this));
 }
Пример #2
0
 /**
  * Get recipients' e-mail addresses
  *
  * @return array Recipients' addresses
  */
 public function getRecipients()
 {
     // get sender address
     $headers = $this->message->headers();
     $to = rcube_mime::decode_address_list($headers['To'], null, false, null, true);
     $cc = rcube_mime::decode_address_list($headers['Cc'], null, false, null, true);
     $bcc = rcube_mime::decode_address_list($headers['Bcc'], null, false, null, true);
     $recipients = array_unique(array_merge($to, $cc, $bcc));
     $recipients = array_diff($recipients, array('undisclosed-recipients:'));
     return $recipients;
 }
Пример #3
0
 /**
  * Test decoding of single e-mail address strings
  * Uses rcube_mime::decode_address_list()
  */
 function test_decode_single_address()
 {
     $headers = array(0 => '*****@*****.**', 1 => '<*****@*****.**>', 2 => 'Test <*****@*****.**>', 3 => 'Test Test <*****@*****.**>', 4 => 'Test Test<*****@*****.**>', 5 => '"Test Test" <*****@*****.**>', 6 => '"Test Test"<*****@*****.**>', 7 => '"Test \\" Test" <*****@*****.**>', 8 => '"Test<Test" <*****@*****.**>', 9 => '=?ISO-8859-1?B?VGVzdAo=?= <*****@*****.**>', 10 => '=?ISO-8859-1?B?VGVzdAo=?=<*****@*****.**>', 11 => 'Test (comment) <*****@*****.**>', 12 => '"Test" (comment) <*****@*****.**>', 13 => '"Test (comment)" (comment) <*****@*****.**>', 14 => '(comment) <*****@*****.**>', 15 => 'Test <test@(comment)domain.tld>', 16 => 'Test Test ((comment)) <*****@*****.**>', 17 => 'test@domain.tld (comment)', 18 => '"Test,Test" <*****@*****.**>', 19 => 'Test <"test test"@domain.tld>', 20 => '<"test test"@domain.tld>', 21 => '"test test"@domain.tld', 22 => '"John Doe @ SomeBusinessName" <MAILER-DAEMON>', 23 => '=?UTF-8?B?IlRlc3QsVGVzdCI=?= <*****@*****.**>', 24 => '"*****@*****.**" <>');
     $results = array(0 => array(1, '', '*****@*****.**'), 1 => array(1, '', '*****@*****.**'), 2 => array(1, 'Test', '*****@*****.**'), 3 => array(1, 'Test Test', '*****@*****.**'), 4 => array(1, 'Test Test', '*****@*****.**'), 5 => array(1, 'Test Test', '*****@*****.**'), 6 => array(1, 'Test Test', '*****@*****.**'), 7 => array(1, 'Test " Test', '*****@*****.**'), 8 => array(1, 'Test<Test', '*****@*****.**'), 9 => array(1, 'Test', '*****@*****.**'), 10 => array(1, 'Test', '*****@*****.**'), 11 => array(1, 'Test', '*****@*****.**'), 12 => array(1, 'Test', '*****@*****.**'), 13 => array(1, 'Test (comment)', '*****@*****.**'), 14 => array(1, '', '*****@*****.**'), 15 => array(1, 'Test', '*****@*****.**'), 16 => array(1, 'Test Test', '*****@*****.**'), 17 => array(1, '', '*****@*****.**'), 18 => array(1, 'Test,Test', '*****@*****.**'), 19 => array(1, 'Test', '"test test"@domain.tld'), 20 => array(1, '', '"test test"@domain.tld'), 21 => array(1, '', '"test test"@domain.tld'), 22 => array(1, 'John Doe @ SomeBusinessName', 'MAILER-DAEMON'), 23 => array(1, 'Test,Test', '*****@*****.**'), 24 => array(1, '', '*****@*****.**'));
     foreach ($headers as $idx => $header) {
         $res = rcube_mime::decode_address_list($header);
         $this->assertEquals($results[$idx][0], count($res), "Rows number in result for header: " . $header);
         $this->assertEquals($results[$idx][1], $res[1]['name'], "Name part decoding for header: " . $header);
         $this->assertEquals($results[$idx][2], $res[1]['mailto'], "Email part decoding for header: " . $header);
     }
 }
Пример #4
0
 /**
  * __construct
  *
  * Provide a uid, and parse message structure.
  *
  * @param string $uid     The message UID.
  * @param string $folder  Folder name
  * @param bool   $is_safe Security flag
  *
  * @see self::$app, self::$storage, self::$opt, self::$parts
  */
 function __construct($uid, $folder = null, $is_safe = false)
 {
     // decode combined UID-folder identifier
     if (preg_match('/^[0-9.]+-.+/', $uid)) {
         list($uid, $folder) = explode('-', $uid, 2);
     }
     if (preg_match('/^([0-9]+)\\.([0-9.]+)$/', $uid, $matches)) {
         $uid = $matches[1];
         $context = $matches[2];
     }
     $this->uid = $uid;
     $this->context = $context;
     $this->app = rcube::get_instance();
     $this->storage = $this->app->get_storage();
     $this->folder = strlen($folder) ? $folder : $this->storage->get_folder();
     // Set current folder
     $this->storage->set_folder($this->folder);
     $this->storage->set_options(array('all_headers' => true));
     $this->headers = $this->storage->get_message($uid);
     if (!$this->headers) {
         return;
     }
     $this->set_safe($is_safe || $_SESSION['safe_messages'][$this->folder . ':' . $uid]);
     $this->opt = array('safe' => $this->is_safe, 'prefer_html' => $this->app->config->get('prefer_html'), 'get_url' => $this->app->url(array('action' => 'get', 'mbox' => $this->folder, 'uid' => $uid), false, false, true));
     if (!empty($this->headers->structure)) {
         $this->get_mime_numbers($this->headers->structure);
         $this->parse_structure($this->headers->structure);
     } else {
         if ($this->context === null) {
             $this->body = $this->storage->get_body($uid);
         }
     }
     $this->mime = new rcube_mime($this->headers->charset);
     $this->subject = $this->headers->get('subject');
     list(, $this->sender) = each($this->mime->decode_address_list($this->headers->from, 1));
     // notify plugins and let them analyze this structured message object
     $this->app->plugins->exec_hook('message_load', array('object' => $this));
 }
Пример #5
0
 /**
  * Add mobile_text in messages list
  *
  * @param array $args
  * @return array
  */
 public function messages_list($args)
 {
     if (isset($args['messages'])) {
         foreach ($args['messages'] as $message) {
             $address = rcube_mime::decode_address_list($message->from, null, true);
             $from = "NNN";
             if (isset($address[1])) {
                 if (isset($address[1]['name'])) {
                     $from = $address[1]['name'];
                 } elseif (isset($address[1]['mailto'])) {
                     $from = $address[1]['mailto'];
                 }
             }
             // Remove specials chars
             $from = str_replace(array(' ', '~', '"', "'", '!', '>'), '', $from);
             $from = strtoupper($from);
             $message->mobile_text = substr($from, 0, 3);
             $message->mobile_class = $this->get_mobile_class($message->mobile_text);
         }
     }
     return $args;
 }
Пример #6
0
 /**
  * Send the given message using the configured method.
  *
  * @param object $message    Reference to Mail_MIME object
  * @param string $from       Sender address string
  * @param array  $mailto     Array of recipient address strings
  * @param array  $error      SMTP error array (reference)
  * @param string $body_file  Location of file with saved message body (reference),
  *                           used when delay_file_io is enabled
  * @param array  $options    SMTP options (e.g. DSN request)
  *
  * @return boolean Send status.
  */
 public function deliver_message(&$message, $from, $mailto, &$error, &$body_file = null, $options = null)
 {
     $plugin = $this->plugins->exec_hook('message_before_send', array('message' => $message, 'from' => $from, 'mailto' => $mailto, 'options' => $options));
     if ($plugin['abort']) {
         if (!empty($plugin['error'])) {
             $error = $plugin['error'];
         }
         if (!empty($plugin['body_file'])) {
             $body_file = $plugin['body_file'];
         }
         return isset($plugin['result']) ? $plugin['result'] : false;
     }
     $from = $plugin['from'];
     $mailto = $plugin['mailto'];
     $options = $plugin['options'];
     $message = $plugin['message'];
     $headers = $message->headers();
     // send thru SMTP server using custom SMTP library
     if ($this->config->get('smtp_server')) {
         // generate list of recipients
         $a_recipients = (array) $mailto;
         if (strlen($headers['Cc'])) {
             $a_recipients[] = $headers['Cc'];
         }
         if (strlen($headers['Bcc'])) {
             $a_recipients[] = $headers['Bcc'];
         }
         // clean Bcc from header for recipients
         $send_headers = $headers;
         unset($send_headers['Bcc']);
         // here too, it because txtHeaders() below use $message->_headers not only $send_headers
         unset($message->_headers['Bcc']);
         $smtp_headers = $message->txtHeaders($send_headers, true);
         if ($message->getParam('delay_file_io')) {
             // use common temp dir
             $temp_dir = $this->config->get('temp_dir');
             $body_file = tempnam($temp_dir, 'rcmMsg');
             if (PEAR::isError($mime_result = $message->saveMessageBody($body_file))) {
                 self::raise_error(array('code' => 650, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Could not create message: " . $mime_result->getMessage()), TRUE, FALSE);
                 return false;
             }
             $msg_body = fopen($body_file, 'r');
         } else {
             $msg_body = $message->get();
         }
         // send message
         if (!is_object($this->smtp)) {
             $this->smtp_init(true);
         }
         $sent = $this->smtp->send_mail($from, $a_recipients, $smtp_headers, $msg_body, $options);
         $response = $this->smtp->get_response();
         $error = $this->smtp->get_error();
         // log error
         if (!$sent) {
             self::raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__, 'message' => join("\n", $response)), true, false);
         }
     } else {
         // unset some headers because they will be added by the mail() function
         $headers_enc = $message->headers($headers);
         $headers_php = $message->_headers;
         unset($headers_php['To'], $headers_php['Subject']);
         // reset stored headers and overwrite
         $message->_headers = array();
         $header_str = $message->txtHeaders($headers_php);
         // #1485779
         if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
             if (preg_match_all('/<([^@]+@[^>]+)>/', $headers_enc['To'], $m)) {
                 $headers_enc['To'] = implode(', ', $m[1]);
             }
         }
         $msg_body = $message->get();
         if (PEAR::isError($msg_body)) {
             self::raise_error(array('code' => 650, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Could not create message: " . $msg_body->getMessage()), TRUE, FALSE);
         } else {
             $delim = $this->config->header_delimiter();
             $to = $headers_enc['To'];
             $subject = $headers_enc['Subject'];
             $header_str = rtrim($header_str);
             if ($delim != "\r\n") {
                 $header_str = str_replace("\r\n", $delim, $header_str);
                 $msg_body = str_replace("\r\n", $delim, $msg_body);
                 $to = str_replace("\r\n", $delim, $to);
                 $subject = str_replace("\r\n", $delim, $subject);
             }
             if (filter_var(ini_get('safe_mode'), FILTER_VALIDATE_BOOLEAN)) {
                 $sent = mail($to, $subject, $msg_body, $header_str);
             } else {
                 $sent = mail($to, $subject, $msg_body, $header_str, "-f{$from}");
             }
         }
     }
     if ($sent) {
         $this->plugins->exec_hook('message_sent', array('headers' => $headers, 'body' => $msg_body));
         // remove MDN headers after sending
         unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']);
         if ($this->config->get('smtp_log')) {
             // get all recipient addresses
             if (is_array($mailto)) {
                 $mailto = implode(',', $mailto);
             }
             if ($headers['Cc']) {
                 $mailto .= ',' . $headers['Cc'];
             }
             if ($headers['Bcc']) {
                 $mailto .= ',' . $headers['Bcc'];
             }
             $mailto = rcube_mime::decode_address_list($mailto, null, false, null, true);
             self::write_log('sendmail', sprintf("User %s [%s]; Message for %s; %s", $this->user->get_username(), rcube_utils::remote_addr(), implode(', ', $mailto), !empty($response) ? join('; ', $response) : ''));
         }
     } else {
         // allow plugins to catch sending errors with the same parameters as in 'message_before_send'
         $this->plugins->exec_hook('message_send_error', $plugin + array('error' => $error));
     }
     if (is_resource($msg_body)) {
         fclose($msg_body);
     }
     $message->_headers = array();
     $message->headers($headers);
     return $sent;
 }
 /**
  * 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);
                 }
             }
         }
     }
 }
Пример #8
0
 /**
  * Extract mail headers for new filter form
  */
 private function parse_headers($headers)
 {
     $result = array();
     if ($headers->subject) {
         $result[] = array('Subject', rcube_mime::decode_header($headers->subject));
     }
     // @TODO: List-Id, others?
     foreach (array('From', 'To') as $h) {
         $hl = strtolower($h);
         if ($headers->{$hl}) {
             $list = rcube_mime::decode_address_list($headers->{$hl});
             foreach ($list as $item) {
                 if ($item['mailto']) {
                     $result[] = array($h, $item['mailto']);
                 }
             }
         }
     }
     return $result;
 }
Пример #9
0
 /**
  * Server-side key pair generation handler
  */
 private function key_generate()
 {
     $user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST, true);
     $pass = rcube_utils::get_input_value('_password', rcube_utils::INPUT_POST, true);
     $size = (int) rcube_utils::get_input_value('_size', rcube_utils::INPUT_POST);
     if ($size > 4096) {
         $size = 4096;
     }
     $ident = rcube_mime::decode_address_list($user, 1, false);
     if (empty($ident)) {
         $this->rc->output->show_message('enigma.keygenerateerror', 'error');
         $this->rc->output->send();
     }
     $this->enigma->load_engine();
     $result = $this->enigma->engine->generate_key(array('user' => $ident[1]['name'], 'email' => $ident[1]['mailto'], 'password' => $pass, 'size' => $size));
     if ($result instanceof enigma_key) {
         $this->rc->output->command('enigma_key_create_success');
         $this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation');
     } else {
         $this->rc->output->show_message('enigma.keygenerateerror', 'error');
     }
     $this->rc->output->send();
 }
 /**
  * Handler for POST request to import an event attached to a mail message
  */
 public function mail_import_itip()
 {
     $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST);
     $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST);
     $mime_id = rcube_utils::get_input_value('_part', rcube_utils::INPUT_POST);
     $status = rcube_utils::get_input_value('_status', rcube_utils::INPUT_POST);
     $delete = intval(rcube_utils::get_input_value('_del', rcube_utils::INPUT_POST));
     $noreply = intval(rcube_utils::get_input_value('_noreply', rcube_utils::INPUT_POST)) || $status == 'needs-action';
     $error_msg = $this->gettext('errorimportingtask');
     $success = false;
     $delegate = null;
     if ($status == 'delegated') {
         $delegates = rcube_mime::decode_address_list(rcube_utils::get_input_value('_to', rcube_utils::INPUT_POST, true), 1, false);
         $delegate = reset($delegates);
         if (empty($delegate) || empty($delegate['mailto'])) {
             $this->rc->output->command('display_message', $this->gettext('libcalendaring.delegateinvalidaddress'), 'error');
             return;
         }
     }
     // successfully parsed tasks?
     if ($task = $this->lib->mail_get_itip_object($mbox, $uid, $mime_id, 'task')) {
         $task = $this->from_ical($task);
         // forward iTip request to delegatee
         if ($delegate) {
             $rsvpme = intval(rcube_utils::get_input_value('_rsvp', rcube_utils::INPUT_POST));
             $itip = $this->load_itip();
             if ($itip->delegate_to($task, $delegate, $rsvpme ? true : false)) {
                 $this->rc->output->show_message('tasklist.itipsendsuccess', 'confirmation');
             } else {
                 $this->rc->output->command('display_message', $this->gettext('itipresponseerror'), 'error');
             }
         }
         // find writeable list to store the task
         $list_id = !empty($_REQUEST['_folder']) ? rcube_utils::get_input_value('_folder', rcube_utils::INPUT_POST) : null;
         $lists = $this->driver->get_lists();
         $list = $lists[$list_id];
         $dontsave = $_REQUEST['_folder'] === '' && $task['_method'] == 'REQUEST';
         // select default list except user explicitly selected 'none'
         if (!$list && !$dontsave) {
             $list = $this->get_default_tasklist($task['sensitivity']);
         }
         $metadata = array('uid' => $task['uid'], 'changed' => is_object($task['changed']) ? $task['changed']->format('U') : 0, 'sequence' => intval($task['sequence']), 'fallback' => strtoupper($status), 'method' => $task['_method'], 'task' => 'tasks');
         // update my attendee status according to submitted method
         if (!empty($status)) {
             $organizer = $task['organizer'];
             $emails = $this->lib->get_user_emails();
             foreach ($task['attendees'] as $i => $attendee) {
                 if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) {
                     $metadata['attendee'] = $attendee['email'];
                     $metadata['rsvp'] = $attendee['role'] != 'NON-PARTICIPANT';
                     $reply_sender = $attendee['email'];
                     $task['attendees'][$i]['status'] = strtoupper($status);
                     if (!in_array($task['attendees'][$i]['status'], array('NEEDS-ACTION', 'DELEGATED'))) {
                         $task['attendees'][$i]['rsvp'] = false;
                         // unset RSVP attribute
                     }
                 }
             }
             // add attendee with this user's default identity if not listed
             if (!$reply_sender) {
                 $sender_identity = $this->rc->user->list_emails(true);
                 $task['attendees'][] = array('name' => $sender_identity['name'], 'email' => $sender_identity['email'], 'role' => 'OPT-PARTICIPANT', 'status' => strtoupper($status));
                 $metadata['attendee'] = $sender_identity['email'];
             }
         }
         // save to tasklist
         if ($list && $list['editable']) {
             $task['list'] = $list['id'];
             // check for existing task with the same UID
             $existing = $this->driver->get_task($task['uid']);
             if ($existing) {
                 // only update attendee status
                 if ($task['_method'] == 'REPLY') {
                     // try to identify the attendee using the email sender address
                     $existing_attendee = -1;
                     $existing_attendee_emails = array();
                     foreach ($existing['attendees'] as $i => $attendee) {
                         $existing_attendee_emails[] = $attendee['email'];
                         if ($task['_sender'] && ($attendee['email'] == $task['_sender'] || $attendee['email'] == $task['_sender_utf'])) {
                             $existing_attendee = $i;
                         }
                     }
                     $task_attendee = null;
                     foreach ($task['attendees'] as $attendee) {
                         if ($task['_sender'] && ($attendee['email'] == $task['_sender'] || $attendee['email'] == $task['_sender_utf'])) {
                             $task_attendee = $attendee;
                             $metadata['fallback'] = $attendee['status'];
                             $metadata['attendee'] = $attendee['email'];
                             $metadata['rsvp'] = $attendee['rsvp'] || $attendee['role'] != 'NON-PARTICIPANT';
                             if ($attendee['status'] != 'DELEGATED') {
                                 break;
                             }
                         } else {
                             if (!empty($attendee['delegated-from']) && (stripos($attendee['delegated-from'], $task['_sender']) !== false || stripos($attendee['delegated-from'], $task['_sender_utf']) !== false) && !in_array($attendee['email'], $existing_attendee_emails)) {
                                 $existing['attendees'][] = $attendee;
                             }
                         }
                     }
                     // if delegatee has declined, set delegator's RSVP=True
                     if ($task_attendee && $task_attendee['status'] == 'DECLINED' && $task_attendee['delegated-from']) {
                         foreach ($existing['attendees'] as $i => $attendee) {
                             if ($attendee['email'] == $task_attendee['delegated-from']) {
                                 $existing['attendees'][$i]['rsvp'] = true;
                                 break;
                             }
                         }
                     }
                     // found matching attendee entry in both existing and new events
                     if ($existing_attendee >= 0 && $task_attendee) {
                         $existing['attendees'][$existing_attendee] = $task_attendee;
                         $success = $this->driver->edit_task($existing);
                     } else {
                         if (($task['sequence'] >= $existing['sequence'] || $task['changed'] >= $existing['changed']) && $task_attendee) {
                             $existing['attendees'][] = $task_attendee;
                             $success = $this->driver->edit_task($existing);
                         } else {
                             $error_msg = $this->gettext('newerversionexists');
                         }
                     }
                 } else {
                     if ($status == 'declined' && $delete) {
                         $deleted = $this->driver->delete_task($existing, true);
                         $success = true;
                     } else {
                         if ($task['sequence'] >= $existing['sequence'] || $task['changed'] >= $existing['changed']) {
                             $task['id'] = $existing['id'];
                             $task['list'] = $existing['list'];
                             // preserve my participant status for regular updates
                             if (empty($status)) {
                                 $emails = $this->lib->get_user_emails();
                                 foreach ($task['attendees'] as $i => $attendee) {
                                     if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) {
                                         foreach ($existing['attendees'] as $j => $_attendee) {
                                             if ($attendee['email'] == $_attendee['email']) {
                                                 $task['attendees'][$i] = $existing['attendees'][$j];
                                                 break;
                                             }
                                         }
                                     }
                                 }
                             }
                             // set status=CANCELLED on CANCEL messages
                             if ($task['_method'] == 'CANCEL') {
                                 $task['status'] = 'CANCELLED';
                             }
                             // show me as free when declined (#1670)
                             if ($status == 'declined' || $task['status'] == 'CANCELLED') {
                                 $task['free_busy'] = 'free';
                             }
                             $success = $this->driver->edit_task($task);
                         } else {
                             if (!empty($status)) {
                                 $existing['attendees'] = $task['attendees'];
                                 if ($status == 'declined') {
                                     // show me as free when declined (#1670)
                                     $existing['free_busy'] = 'free';
                                 }
                                 $success = $this->driver->edit_event($existing);
                             } else {
                                 $error_msg = $this->gettext('newerversionexists');
                             }
                         }
                     }
                 }
             } else {
                 if (!$existing && ($status != 'declined' || $this->rc->config->get('kolab_invitation_tasklists'))) {
                     $success = $this->driver->create_task($task);
                 } else {
                     if ($status == 'declined') {
                         $error_msg = null;
                     }
                 }
             }
         } else {
             if ($status == 'declined' || $dontsave) {
                 $error_msg = null;
             } else {
                 $error_msg = $this->gettext('nowritetasklistfound');
             }
         }
     }
     if ($success || $dontsave) {
         if ($success) {
             $message = $task['_method'] == 'REPLY' ? 'attendeupdateesuccess' : ($deleted ? 'successremoval' : ($existing ? 'updatedsuccessfully' : 'importedsuccessfully'));
             $this->rc->output->command('display_message', $this->gettext(array('name' => $message, 'vars' => array('list' => $list['name']))), 'confirmation');
         }
         $metadata['rsvp'] = intval($metadata['rsvp']);
         $metadata['after_action'] = $this->rc->config->get('calendar_itip_after_action', 0);
         $this->rc->output->command('plugin.itip_message_processed', $metadata);
         $error_msg = null;
     } else {
         if ($error_msg) {
             $this->rc->output->command('display_message', $error_msg, 'error');
         }
     }
     // send iTip reply
     if ($task['_method'] == 'REQUEST' && $organizer && !$noreply && !in_array(strtolower($organizer['email']), $emails) && !$error_msg) {
         $task['comment'] = rcube_utils::get_input_value('_comment', rcube_utils::INPUT_POST);
         $itip = $this->load_itip();
         $itip->set_sender_email($reply_sender);
         if ($itip->send_itip_message($this->to_libcal($task), 'REPLY', $organizer, 'itipsubject' . $status, 'itipmailbody' . $status)) {
             $this->rc->output->command('display_message', $this->gettext(array('name' => 'sentresponseto', 'vars' => array('mailto' => $organizer['name'] ?: $organizer['email']))), 'confirmation');
         } else {
             $this->rc->output->command('display_message', $this->gettext('itipresponseerror'), 'error');
         }
     }
     $this->rc->output->send();
 }
 function create_rule($args)
 {
     $rcmail = rcube::get_instance();
     if ($rcmail->action == 'plugin.sieverules.add' || $rcmail->action == 'plugin.sieverules.edit') {
         $messageset = unserialize($_SESSION['plugin.sieverules.messageset']);
         $headers = $args['defaults']['headers'];
         $rcmail->storage_init();
         $use_address = preg_match('/^address::/', $this->headers[1]['value']) ? true : false;
         foreach ($messageset as $mbox => $uids) {
             $rcmail->get_storage()->set_folder($mbox);
             foreach ($uids as $uid) {
                 $message = new rcube_message($uid);
                 $this->_add_to_array($args['script']['tests'], array('type' => $use_address ? 'address' : 'header', 'operator' => 'is', 'header' => 'From', 'target' => $message->sender['mailto']));
                 $recipients = array();
                 $recipients_array = rcube_mime::decode_address_list($message->headers->to);
                 foreach ($recipients_array as $recipient) {
                     $recipients[] = $recipient['mailto'];
                 }
                 $identity = $rcmail->user->get_identity();
                 $recipient_str = join(', ', $recipients);
                 if ($recipient_str != $identity['email']) {
                     $this->_add_to_array($args['script']['tests'], array('type' => $use_address ? 'address' : 'header', 'operator' => 'is', 'header' => 'To', 'target' => $recipient_str));
                 }
                 if (strlen($message->subject) > 0) {
                     $this->_add_to_array($args['script']['tests'], array('type' => 'header', 'operator' => 'contains', 'header' => 'Subject', 'target' => $message->subject));
                 }
                 foreach ($this->additional_headers as $header) {
                     if (strlen($message->headers->others[strtolower($header)]) > 0) {
                         $this->_add_to_array($args['script']['tests'], array('type' => 'header', 'operator' => 'is', 'header' => $header, 'target' => $message->headers->others[strtolower($header)]));
                     }
                 }
                 $this->_add_to_array($args['script']['actions'], array('type' => 'fileinto', 'target' => $mbox));
                 foreach ($message->headers->flags as $flag => $value) {
                     if ($flag == 'FLAGGED') {
                         $this->_add_to_array($args['script']['actions'], array('type' => 'imapflags', 'target' => '\\\\Flagged'));
                     }
                 }
             }
         }
         $_SESSION['plugin.sieverules.rule'] = false;
         $_SESSION['plugin.sieverules.messageset'] = null;
     }
     return $args;
 }
 /**
  * Forward the given iTip event as delegation to another person
  *
  * @param array Event object to delegate
  * @param mixed Delegatee as string or hash array with keys 'name' and 'mailto'
  * @param boolean The delegator's RSVP flag
  * @param array List with indexes of new/updated attendees
  * @return boolean True on success, False on failure
  */
 public function delegate_to(&$event, $delegate, $rsvp = false, &$attendees = array())
 {
     if (is_string($delegate)) {
         $delegates = rcube_mime::decode_address_list($delegate, 1, false);
         if (count($delegates) > 0) {
             $delegate = reset($delegates);
         }
     }
     $emails = $this->lib->get_user_emails();
     $me = $this->rc->user->list_emails(true);
     // find/create the delegate attendee
     $delegate_attendee = array('email' => $delegate['mailto'], 'name' => $delegate['name'], 'role' => 'REQ-PARTICIPANT');
     $delegate_index = count($event['attendees']);
     foreach ($event['attendees'] as $i => $attendee) {
         // set myself the DELEGATED-TO parameter
         if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) {
             $event['attendees'][$i]['delegated-to'] = $delegate['mailto'];
             $event['attendees'][$i]['status'] = 'DELEGATED';
             $event['attendees'][$i]['role'] = 'NON-PARTICIPANT';
             $event['attendees'][$i]['rsvp'] = $rsvp;
             $me['email'] = $attendee['email'];
             $delegate_attendee['role'] = $attendee['role'];
         } else {
             if (stripos($delegate['mailto'], $attendee['email']) !== false && $attendee['role'] != 'ORGANIZER') {
                 $delegate_attendee = $attendee;
                 $delegate_index = $i;
                 break;
             }
         }
         // TODO: remove previous delegatee (i.e. attendee that has DELEGATED-FROM == $me)
     }
     // set/add delegate attendee with RSVP=TRUE and DELEGATED-FROM parameter
     $delegate_attendee['rsvp'] = true;
     $delegate_attendee['status'] = 'NEEDS-ACTION';
     $delegate_attendee['delegated-from'] = $me['email'];
     $event['attendees'][$delegate_index] = $delegate_attendee;
     $attendees[] = $delegate_index;
     $this->set_sender_email($me['email']);
     return $this->send_itip_message($event, 'REQUEST', $delegate_attendee, 'itipsubjectdelegatedto', 'itipmailbodydelegatedto');
 }
Пример #13
0
 /**
  * Send the given message using the configured method.
  *
  * @param object $message   Reference to Mail_MIME object
  * @param string $from      Sender address string
  * @param array  $mailto    Array of recipient address strings
  * @param array  $error     SMTP error array (reference)
  * @param string $body_file Location of file with saved message body (reference),
  *                          used when delay_file_io is enabled
  * @param array  $options   SMTP options (e.g. DSN request)
  * @param bool   $disconnect Close SMTP connection ASAP
  *
  * @return boolean Send status.
  */
 public function deliver_message(&$message, $from, $mailto, &$error, &$body_file = null, $options = null, $disconnect = false)
 {
     $plugin = $this->plugins->exec_hook('message_before_send', array('message' => $message, 'from' => $from, 'mailto' => $mailto, 'options' => $options));
     if ($plugin['abort']) {
         if (!empty($plugin['error'])) {
             $error = $plugin['error'];
         }
         if (!empty($plugin['body_file'])) {
             $body_file = $plugin['body_file'];
         }
         return isset($plugin['result']) ? $plugin['result'] : false;
     }
     $from = $plugin['from'];
     $mailto = $plugin['mailto'];
     $options = $plugin['options'];
     $message = $plugin['message'];
     $headers = $message->headers();
     // generate list of recipients
     $a_recipients = (array) $mailto;
     if (strlen($headers['Cc'])) {
         $a_recipients[] = $headers['Cc'];
     }
     if (strlen($headers['Bcc'])) {
         $a_recipients[] = $headers['Bcc'];
     }
     // remove Bcc header and get the whole head of the message as string
     $smtp_headers = $message->txtHeaders(array('Bcc' => null), true);
     if ($message->getParam('delay_file_io')) {
         // use common temp dir
         $temp_dir = $this->config->get('temp_dir');
         $body_file = tempnam($temp_dir, 'rcmMsg');
         $mime_result = $message->saveMessageBody($body_file);
         if (is_a($mime_result, 'PEAR_Error')) {
             self::raise_error(array('code' => 650, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Could not create message: " . $mime_result->getMessage()), true, false);
             return false;
         }
         $msg_body = fopen($body_file, 'r');
     } else {
         $msg_body = $message->get();
     }
     // initialize SMTP connection
     if (!is_object($this->smtp)) {
         $this->smtp_init(true);
     }
     // send message
     $sent = $this->smtp->send_mail($from, $a_recipients, $smtp_headers, $msg_body, $options);
     $response = $this->smtp->get_response();
     $error = $this->smtp->get_error();
     if (!$sent) {
         self::raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__, 'message' => join("\n", $response)), true, false);
         // allow plugins to catch sending errors with the same parameters as in 'message_before_send'
         $this->plugins->exec_hook('message_send_error', $plugin + array('error' => $error));
     } else {
         $this->plugins->exec_hook('message_sent', array('headers' => $headers, 'body' => $msg_body));
         // remove MDN headers after sending
         unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']);
         if ($this->config->get('smtp_log')) {
             // get all recipient addresses
             $mailto = implode(',', $a_recipients);
             $mailto = rcube_mime::decode_address_list($mailto, null, false, null, true);
             self::write_log('sendmail', sprintf("User %s [%s]; Message for %s; %s", $this->user->get_username(), rcube_utils::remote_addr(), implode(', ', $mailto), !empty($response) ? join('; ', $response) : ''));
         }
     }
     if (is_resource($msg_body)) {
         fclose($msg_body);
     }
     if ($disconnect) {
         $this->smtp->disconnect();
     }
     $message->headers($headers, true);
     return $sent;
 }
Пример #14
0
 /**
  * Handler for attaching public key to a message
  *
  * @param Mail_mime Original message
  *
  * @return bool True on success, False on failure
  */
 function attach_public_key(&$message)
 {
     $headers = $message->headers();
     $from = rcube_mime::decode_address_list($headers['From'], 1, false, null, true);
     $from = $from[1];
     // find my key
     if ($from && ($key = $this->find_key($from))) {
         $pubkey_armor = $this->export_key($key->id);
         if (!$pubkey_armor instanceof enigma_error) {
             $pubkey_name = '0x' . enigma_key::format_id($key->id) . '.asc';
             $message->addAttachment($pubkey_armor, 'application/pgp-keys', $pubkey_name, false, '7bit');
             return true;
         }
     }
     return false;
 }
Пример #15
0
 public function message_compose($params)
 {
     global $IMAP;
     global $USER;
     $this->load_config();
     $address = null;
     $rcmail = rcmail::get_instance();
     if (isset($params['param']['reply_uid'])) {
         $message = $params['param']['reply_uid'];
     } else {
         if (isset($params['param']['forward_uid'])) {
             $message = $params['param']['forward_uid'];
         } else {
             if (isset($params['param']['uid'])) {
                 $message = $params['param']['uid'];
             } else {
                 $message = null;
             }
         }
     }
     if ($rcmail->config->get('custom_from_compose_auto', true) && $message !== null) {
         // Newer versions of roundcube don't provide a global $IMAP or $USER variable
         if (!isset($IMAP) && isset($rcmail->storage)) {
             $IMAP = $rcmail->storage;
         }
         if (!isset($USER) && isset($rcmail->user)) {
             $USER = $rcmail->user;
         }
         $IMAP->get_all_headers = true;
         $headers = $IMAP->get_message($message);
         if ($headers !== null) {
             // Browse headers where addresses will be fetched from
             $recipients = array();
             $rules = $this->parse_headers($rcmail->config->get('custom_from_header_rules', self::HEADER_RULES));
             foreach ($rules as $header => $rule) {
                 // RC < 0.8 compatibility code
                 if (!class_exists('rcube_mime')) {
                     if (in_array($header, self::$default_headers)) {
                         $addresses = isset($headers->{$header}) ? $IMAP->decode_address_list($headers->{$header}) : array();
                     } else {
                         $addresses = isset($headers->others[$header]) ? $IMAP->decode_address_list($headers->others[$header]) : array();
                     }
                 } else {
                     if (in_array($header, self::$default_headers)) {
                         $addresses = isset($headers->{$header}) ? rcube_mime::decode_address_list($headers->{$header}) : array();
                     } else {
                         $addresses = isset($headers->others[$header]) ? rcube_mime::decode_address_list($headers->others[$header]) : array();
                     }
                 }
                 // Decode recipients and matching rules from retrieved addresses
                 foreach ($addresses as $address) {
                     if (isset($address['mailto'])) {
                         $email = $address['mailto'];
                         $recipients[] = array('domain' => preg_replace('/^[^@]*@(.*)$/', '$1', $email), 'email' => $email, 'match_domain' => strpos($rule, 'd') !== false, 'match_exact' => strpos($rule, 'e') !== false, 'match_other' => strpos($rule, 'o') !== false, 'name' => $address['name']);
                     }
                 }
             }
             // Get user identities list
             $identities = array();
             foreach ($USER->list_identities() as $identity) {
                 $identities[$identity['email']] = array('domain' => preg_replace('/^[^@]*@(.*)$/', '$1', $identity['email']), 'name' => $identity['name']);
             }
             // Find best possible match from recipients and identities
             $address = null;
             $score = 0;
             foreach ($recipients as $recipient) {
                 $email = $recipient['email'];
                 // Relevance score 3: exact match found in identities
                 if ($score < 3 && $recipient['match_exact'] && isset($identities[$email])) {
                     $address = null;
                     $score = 3;
                 }
                 // Relevance score 2: domain match found in identities
                 if ($score < 2 && $recipient['match_domain']) {
                     foreach ($identities as $identity) {
                         if (strcasecmp($identity['domain'], $recipient['domain']) == 0) {
                             $address = $identity['name'] ? $identity['name'] . ' <' . $email . '>' : $email;
                             $score = 2;
                         }
                     }
                 }
                 // Relevance score 1: no match found
                 if ($score < 1 && $recipient['match_other']) {
                     $address = $recipient['name'] ? $recipient['name'] . ' <' . $email . '>' : $email;
                     $score = 1;
                 }
             }
         }
     }
     $_SESSION['custom_from'] = $address;
 }
Пример #16
0
 /**
  * Helper method to packs all the given messages into a zip archive
  *
  * @param array List of message UIDs to download
  */
 private function _download_messages($messageset)
 {
     $rcmail = rcmail::get_instance();
     $imap = $rcmail->get_storage();
     $mode = rcube_utils::get_input_value('_mode', rcube_utils::INPUT_POST);
     $temp_dir = $rcmail->config->get('temp_dir');
     $tmpfname = tempnam($temp_dir, 'zipdownload');
     $tempfiles = array($tmpfname);
     $folders = count($messageset) > 1;
     // @TODO: file size limit
     // open zip file
     $zip = new ZipArchive();
     $zip->open($tmpfname, ZIPARCHIVE::OVERWRITE);
     if ($mode == 'mbox') {
         $tmpfp = fopen($tmpfname . '.mbox', 'w');
     }
     $start = time();
     if (!is_array($_SESSION['zipdownload_uids'])) {
         $_SESSION['zipdownload_uids'] = array();
     }
     $count = 0;
     foreach ($messageset as $mbox => $uids) {
         $imap->set_folder($mbox);
         $path = $folders ? str_replace($imap->get_hierarchy_delimiter(), '/', $mbox) . '/' : '';
         if ($uids === '*') {
             $index = $imap->index($mbox, null, null, true);
             $uids = $index->get();
         }
         foreach ($uids as $uid) {
             if (isset($_SESSION['zipdownload_uids'][$mbox . '|' . $uid])) {
                 continue;
             }
             $count++;
             $headers = $imap->get_message_headers($uid);
             if ($mode == 'mbox') {
                 $from = rcube_mime::decode_address_list($headers->from, null, true, $headers->charset, true);
                 $from = array_shift($from);
                 // Mbox format header
                 // @FIXME: \r\n or \n
                 // @FIXME: date format
                 $header = sprintf("From %s %s\r\n", $from ? preg_replace('/\\s/', '-', $from) : 'MAILER-DAEMON', $headers->internaldate);
                 fwrite($tmpfp, $header);
                 // Use stream filter to quote "From " in the message body
                 stream_filter_register('mbox_filter', '_zipdownload_mbox_filter');
                 $filter = stream_filter_append($tmpfp, 'mbox_filter');
                 $imap->get_raw_body($uid, $tmpfp);
                 stream_filter_remove($filter);
                 fwrite($tmpfp, "\r\n");
             } else {
                 // maildir
                 $subject = rcube_mime::decode_mime_string((string) $headers->subject);
                 $subject = $this->_convert_filename($subject);
                 $subject = substr($subject, 0, 16);
                 $disp_name = ($subject ? $subject : 'message_rfc822') . ".eml";
                 $disp_name = $path . $uid . "_" . $disp_name;
                 $tmpfn = tempnam($temp_dir, 'zipmessage');
                 $tmpfp = fopen($tmpfn, 'w');
                 $imap->get_raw_body($uid, $tmpfp);
                 $tempfiles[] = $tmpfn;
                 fclose($tmpfp);
                 $zip->addFile($tmpfn, $disp_name);
             }
             $_SESSION['zipdownload_uids'][$mbox . '|' . $uid] = 1;
             if ($to = $rcmail->config->get('zipdownload_resume', 25)) {
                 if (time() > $start + $to) {
                     if (isset($_SESSION['zipdownload_count'])) {
                         $_SESSION['zipdownload']++;
                     } else {
                         $_SESSION['zipdownload'] = 0;
                     }
                     break;
                 }
             }
         }
     }
     $filename = $folders ? 'messages' : $imap->get_folder();
     if ($mode == 'mbox') {
         $tempfiles[] = $tmpfname . '.mbox';
         fclose($tmpfp);
         $zip->addFile($tmpfname . '.mbox', $filename . '.mbox');
     }
     $zip->close();
     if ($count > 0) {
         $this->_deliver_zipfile($tmpfname, $filename . ($_SESSION['zipdownload_count'] > 0 ? '(' . $_SESSION['zipdownload_count'] . ')' : '') . '.zip');
         // delete temporary files from disk
         foreach ($tempfiles as $tmpfn) {
             unlink($tmpfn);
         }
     } else {
         echo html::tag('script', array('type' => 'text/javascript'), 'parent.rcmail.http_post("plugin.zipdownload.abort", "_mbox' . $mbox . '");' . "\r\n" . 'parent.rcmail.set_busy(false, "loading", parent.lock);');
     }
     exit;
 }
Пример #17
0
 /**
  * Helper method to packs all the given messages into a zip archive
  *
  * @param array List of message UIDs to download
  */
 private function _download_messages($messageset)
 {
     $rcmail = rcmail::get_instance();
     $imap = $rcmail->get_storage();
     $mode = rcube_utils::get_input_value('_mode', rcube_utils::INPUT_POST);
     $temp_dir = $rcmail->config->get('temp_dir');
     $tmpfname = tempnam($temp_dir, 'zipdownload');
     $tempfiles = array($tmpfname);
     $folders = count($messageset) > 1;
     // @TODO: file size limit
     // open zip file
     $zip = new ZipArchive();
     $zip->open($tmpfname, ZIPARCHIVE::OVERWRITE);
     if ($mode == 'mbox') {
         $tmpfp = fopen($tmpfname . '.mbox', 'w');
     }
     foreach ($messageset as $mbox => $uids) {
         $imap->set_folder($mbox);
         $path = $folders ? str_replace($imap->get_hierarchy_delimiter(), '/', $mbox) . '/' : '';
         foreach ($uids as $uid) {
             $headers = $imap->get_message_headers($uid);
             if ($mode == 'mbox') {
                 $from = rcube_mime::decode_address_list($headers->from, null, true, $headers->charset, true);
                 $from = array_shift($from);
                 // Mbox format header
                 // @FIXME: \r\n or \n
                 // @FIXME: date format
                 $header = sprintf("From %s %s\r\n", $from ? preg_replace('/\\s/', '-', $from) : 'MAILER-DAEMON', $headers->internaldate);
                 fwrite($tmpfp, $header);
                 // Use stream filter to quote "From " in the message body
                 stream_filter_register('mbox_filter', 'zipdownload_mbox_filter');
                 $filter = stream_filter_append($tmpfp, 'mbox_filter');
                 $imap->get_raw_body($uid, $tmpfp);
                 stream_filter_remove($filter);
                 fwrite($tmpfp, "\r\n");
             } else {
                 // maildir
                 $subject = rcube_mime::decode_mime_string((string) $headers->subject);
                 $subject = $this->_convert_filename($subject);
                 $subject = substr($subject, 0, 16);
                 $disp_name = ($subject ? $subject : 'message_rfc822') . ".eml";
                 $disp_name = $path . $uid . "_" . $disp_name;
                 $tmpfn = tempnam($temp_dir, 'zipmessage');
                 $tmpfp = fopen($tmpfn, 'w');
                 $imap->get_raw_body($uid, $tmpfp);
                 $tempfiles[] = $tmpfn;
                 fclose($tmpfp);
                 $zip->addFile($tmpfn, $disp_name);
             }
         }
     }
     $filename = $folders ? 'messages' : $imap->get_folder();
     if ($mode == 'mbox') {
         $tempfiles[] = $tmpfname . '.mbox';
         fclose($tmpfp);
         $zip->addFile($tmpfname . '.mbox', $filename . '.mbox');
     }
     $zip->close();
     $this->_deliver_zipfile($tmpfname, $filename . '.zip');
     // delete temporary files from disk
     foreach ($tempfiles as $tmpfn) {
         unlink($tmpfn);
     }
     exit;
 }
Пример #18
0
 /**
  * Get message headers for popup window
  */
 function mail_headers($args)
 {
     $headers = $args['headers'];
     $ret = array();
     if ($headers->subject) {
         $ret[] = array('Subject', rcube_mime::decode_header($headers->subject));
     }
     // @TODO: List-Id, others?
     foreach (array('From', 'To') as $h) {
         $hl = strtolower($h);
         if ($headers->{$hl}) {
             $list = rcube_mime::decode_address_list($headers->{$hl});
             foreach ($list as $item) {
                 if ($item['mailto']) {
                     $ret[] = array($h, $item['mailto']);
                 }
             }
         }
     }
     if ($this->rc->action == 'preview') {
         $this->rc->output->command('parent.set_env', array('sieve_headers' => $ret));
     } else {
         $this->rc->output->set_env('sieve_headers', $ret);
     }
     return $args;
 }
Пример #19
0
 /**
  * Handler for POST request to import an event attached to a mail message
  */
 public function mail_import_itip()
 {
     $itip_sending = $this->rc->config->get('calendar_itip_send_option', $this->defaults['calendar_itip_send_option']);
     $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST);
     $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST);
     $mime_id = rcube_utils::get_input_value('_part', rcube_utils::INPUT_POST);
     $status = rcube_utils::get_input_value('_status', rcube_utils::INPUT_POST);
     $delete = intval(rcube_utils::get_input_value('_del', rcube_utils::INPUT_POST));
     $noreply = intval(rcube_utils::get_input_value('_noreply', rcube_utils::INPUT_POST));
     $noreply = $noreply || $status == 'needs-action' || $itip_sending === 0;
     $instance = rcube_utils::get_input_value('_instance', rcube_utils::INPUT_POST);
     $savemode = rcube_utils::get_input_value('_savemode', rcube_utils::INPUT_POST);
     $error_msg = $this->gettext('errorimportingevent');
     $success = false;
     $delegate = null;
     if ($status == 'delegated') {
         $delegates = rcube_mime::decode_address_list(rcube_utils::get_input_value('_to', rcube_utils::INPUT_POST, true), 1, false);
         $delegate = reset($delegates);
         if (empty($delegate) || empty($delegate['mailto'])) {
             $this->rc->output->command('display_message', $this->gettext('libcalendaring.delegateinvalidaddress'), 'error');
             return;
         }
     }
     // successfully parsed events?
     if ($event = $this->lib->mail_get_itip_object($mbox, $uid, $mime_id, 'event')) {
         // forward iTip request to delegatee
         if ($delegate) {
             $rsvpme = intval(rcube_utils::get_input_value('_rsvp', rcube_utils::INPUT_POST));
             $itip = $this->load_itip();
             if ($itip->delegate_to($event, $delegate, $rsvpme ? true : false)) {
                 $this->rc->output->show_message('calendar.itipsendsuccess', 'confirmation');
             } else {
                 $this->rc->output->command('display_message', $this->gettext('itipresponseerror'), 'error');
             }
             // the delegator is set to non-participant, thus save as non-blocking
             $event['free_busy'] = 'free';
         }
         // find writeable calendar to store event
         $cal_id = !empty($_REQUEST['_folder']) ? rcube_utils::get_input_value('_folder', rcube_utils::INPUT_POST) : null;
         $dontsave = $_REQUEST['_folder'] === '' && $event['_method'] == 'REQUEST';
         $calendars = $this->driver->list_calendars(calendar_driver::FILTER_PERSONAL);
         $calendar = $calendars[$cal_id];
         // select default calendar except user explicitly selected 'none'
         if (!$calendar && !$dontsave) {
             $calendar = $this->get_default_calendar($event['sensitivity']);
         }
         $metadata = array('uid' => $event['uid'], '_instance' => $event['_instance'], 'changed' => is_object($event['changed']) ? $event['changed']->format('U') : 0, 'sequence' => intval($event['sequence']), 'fallback' => strtoupper($status), 'method' => $event['_method'], 'task' => 'calendar');
         // update my attendee status according to submitted method
         if (!empty($status)) {
             $organizer = null;
             $emails = $this->get_user_emails();
             foreach ($event['attendees'] as $i => $attendee) {
                 if ($attendee['role'] == 'ORGANIZER') {
                     $organizer = $attendee;
                 } else {
                     if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) {
                         $event['attendees'][$i]['status'] = strtoupper($status);
                         if (!in_array($event['attendees'][$i]['status'], array('NEEDS-ACTION', 'DELEGATED'))) {
                             $event['attendees'][$i]['rsvp'] = false;
                         }
                         // unset RSVP attribute
                         $metadata['attendee'] = $attendee['email'];
                         $metadata['rsvp'] = $attendee['role'] != 'NON-PARTICIPANT';
                         $reply_sender = $attendee['email'];
                         $event_attendee = $attendee;
                     }
                 }
             }
             // add attendee with this user's default identity if not listed
             if (!$reply_sender) {
                 $sender_identity = $this->rc->user->list_emails(true);
                 $event['attendees'][] = array('name' => $sender_identity['name'], 'email' => $sender_identity['email'], 'role' => 'OPT-PARTICIPANT', 'status' => strtoupper($status));
                 $metadata['attendee'] = $sender_identity['email'];
             }
         }
         // save to calendar
         if ($calendar && $calendar['editable']) {
             // check for existing event with the same UID
             $existing = $this->driver->get_event($event, calendar_driver::FILTER_WRITEABLE | calendar_driver::FILTER_PERSONAL);
             if ($existing) {
                 // forward savemode for correct updates of recurring events
                 $existing['_savemode'] = $savemode ?: $event['_savemode'];
                 // only update attendee status
                 if ($event['_method'] == 'REPLY') {
                     // try to identify the attendee using the email sender address
                     $existing_attendee = -1;
                     $existing_attendee_emails = array();
                     foreach ($existing['attendees'] as $i => $attendee) {
                         $existing_attendee_emails[] = $attendee['email'];
                         if ($event['_sender'] && ($attendee['email'] == $event['_sender'] || $attendee['email'] == $event['_sender_utf'])) {
                             $existing_attendee = $i;
                         }
                     }
                     $event_attendee = null;
                     $update_attendees = array();
                     foreach ($event['attendees'] as $attendee) {
                         if ($event['_sender'] && ($attendee['email'] == $event['_sender'] || $attendee['email'] == $event['_sender_utf'])) {
                             $event_attendee = $attendee;
                             $update_attendees[] = $attendee;
                             $metadata['fallback'] = $attendee['status'];
                             $metadata['attendee'] = $attendee['email'];
                             $metadata['rsvp'] = $attendee['rsvp'] || $attendee['role'] != 'NON-PARTICIPANT';
                             if ($attendee['status'] != 'DELEGATED') {
                                 break;
                             }
                         } else {
                             if (!empty($attendee['delegated-from']) && (stripos($attendee['delegated-from'], $event['_sender']) !== false || stripos($attendee['delegated-from'], $event['_sender_utf']) !== false)) {
                                 $update_attendees[] = $attendee;
                                 if (!in_array($attendee['email'], $existing_attendee_emails)) {
                                     $existing['attendees'][] = $attendee;
                                 }
                             }
                         }
                     }
                     // if delegatee has declined, set delegator's RSVP=True
                     if ($event_attendee && $event_attendee['status'] == 'DECLINED' && $event_attendee['delegated-from']) {
                         foreach ($existing['attendees'] as $i => $attendee) {
                             if ($attendee['email'] == $event_attendee['delegated-from']) {
                                 $existing['attendees'][$i]['rsvp'] = true;
                                 break;
                             }
                         }
                     }
                     // found matching attendee entry in both existing and new events
                     if ($existing_attendee >= 0 && $event_attendee) {
                         $existing['attendees'][$existing_attendee] = $event_attendee;
                         $success = $this->driver->update_attendees($existing, $update_attendees);
                     } else {
                         if (($event['sequence'] >= $existing['sequence'] || $event['changed'] >= $existing['changed']) && $event_attendee) {
                             $existing['attendees'][] = $event_attendee;
                             $success = $this->driver->update_attendees($existing, $update_attendees);
                         } else {
                             $error_msg = $this->gettext('newerversionexists');
                         }
                     }
                 } else {
                     if ($status == 'declined' && $delete) {
                         $deleted = $this->driver->remove_event($existing, true);
                         $success = true;
                     } else {
                         if ($event['sequence'] >= $existing['sequence'] || $event['changed'] >= $existing['changed']) {
                             $event['id'] = $existing['id'];
                             $event['calendar'] = $existing['calendar'];
                             // preserve my participant status for regular updates
                             if (empty($status)) {
                                 $emails = $this->get_user_emails();
                                 foreach ($event['attendees'] as $i => $attendee) {
                                     if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) {
                                         foreach ($existing['attendees'] as $j => $_attendee) {
                                             if ($attendee['email'] == $_attendee['email']) {
                                                 $event['attendees'][$i] = $existing['attendees'][$j];
                                                 break;
                                             }
                                         }
                                     }
                                 }
                             }
                             // set status=CANCELLED on CANCEL messages
                             if ($event['_method'] == 'CANCEL') {
                                 $event['status'] = 'CANCELLED';
                             }
                             // show me as free when declined (#1670)
                             if ($status == 'declined' || $event['status'] == 'CANCELLED' || $event_attendee['role'] == 'NON-PARTICIPANT') {
                                 $event['free_busy'] = 'free';
                             }
                             $success = $this->driver->edit_event($event);
                         } else {
                             if (!empty($status)) {
                                 $existing['attendees'] = $event['attendees'];
                                 if ($status == 'declined' || $event_attendee['role'] == 'NON-PARTICIPANT') {
                                     // show me as free when declined (#1670)
                                     $existing['free_busy'] = 'free';
                                 }
                                 $success = $this->driver->edit_event($existing);
                             } else {
                                 $error_msg = $this->gettext('newerversionexists');
                             }
                         }
                     }
                 }
             } else {
                 if (!$existing && ($status != 'declined' || $this->rc->config->get('kolab_invitation_calendars'))) {
                     if ($status == 'declined' || $event['status'] == 'CANCELLED' || $event_attendee['role'] == 'NON-PARTICIPANT') {
                         $event['free_busy'] = 'free';
                     }
                     // if the RSVP reply only refers to a single instance:
                     // store unmodified master event with current instance as exception
                     if (!empty($instance) && !empty($savemode) && $savemode != 'all') {
                         $master = $this->lib->mail_get_itip_object($mbox, $uid, $mime_id, 'event');
                         if ($master['recurrence'] && !$master['_instance']) {
                             // compute recurring events until this instance's date
                             if ($recurrence_date = rcube_utils::anytodatetime($instance, $master['start']->getTimezone())) {
                                 $recurrence_date->setTime(23, 59, 59);
                                 foreach ($this->driver->get_recurring_events($master, $master['start'], $recurrence_date) as $recurring) {
                                     if ($recurring['_instance'] == $instance) {
                                         // copy attendees block with my partstat to exception
                                         $recurring['attendees'] = $event['attendees'];
                                         $master['recurrence']['EXCEPTIONS'][] = $recurring;
                                         $event = $recurring;
                                         // set reference for iTip reply
                                         break;
                                     }
                                 }
                                 $master['calendar'] = $event['calendar'] = $calendar['id'];
                                 $success = $this->driver->new_event($master);
                             } else {
                                 $master = null;
                             }
                         } else {
                             $master = null;
                         }
                     }
                     // save to the selected/default calendar
                     if (!$master) {
                         $event['calendar'] = $calendar['id'];
                         $success = $this->driver->new_event($event);
                     }
                 } else {
                     if ($status == 'declined') {
                         $error_msg = null;
                     }
                 }
             }
         } else {
             if ($status == 'declined' || $dontsave) {
                 $error_msg = null;
             } else {
                 $error_msg = $this->gettext('nowritecalendarfound');
             }
         }
     }
     if ($success) {
         $message = $event['_method'] == 'REPLY' ? 'attendeupdateesuccess' : ($deleted ? 'successremoval' : ($existing ? 'updatedsuccessfully' : 'importedsuccessfully'));
         $this->rc->output->command('display_message', $this->gettext(array('name' => $message, 'vars' => array('calendar' => $calendar['name']))), 'confirmation');
     }
     if ($success || $dontsave) {
         $metadata['calendar'] = $event['calendar'];
         $metadata['nosave'] = $dontsave;
         $metadata['rsvp'] = intval($metadata['rsvp']);
         $metadata['after_action'] = $this->rc->config->get('calendar_itip_after_action', $this->defaults['calendar_itip_after_action']);
         $this->rc->output->command('plugin.itip_message_processed', $metadata);
         $error_msg = null;
     } else {
         if ($error_msg) {
             $this->rc->output->command('display_message', $error_msg, 'error');
         }
     }
     // send iTip reply
     if ($event['_method'] == 'REQUEST' && $organizer && !$noreply && !in_array(strtolower($organizer['email']), $emails) && !$error_msg) {
         $event['comment'] = rcube_utils::get_input_value('_comment', rcube_utils::INPUT_POST);
         $itip = $this->load_itip();
         $itip->set_sender_email($reply_sender);
         if ($itip->send_itip_message($event, 'REPLY', $organizer, 'itipsubject' . $status, 'itipmailbody' . $status)) {
             $this->rc->output->command('display_message', $this->gettext(array('name' => 'sentresponseto', 'vars' => array('mailto' => $organizer['name'] ? $organizer['name'] : $organizer['email']))), 'confirmation');
         } else {
             $this->rc->output->command('display_message', $this->gettext('itipresponseerror'), 'error');
         }
     }
     $this->rc->output->send();
 }
Пример #20
0
 /**
  * Server-side key pair generation handler
  */
 private function key_generate()
 {
     // Crypt_GPG does not support key generation for multiple identities
     // It is also very slow (which is problematic because it may exceed
     // request time limit) and requires entropy generator
     // That's why we use only OpenPGP.js method of key generation
     return;
     $user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST, true);
     $pass = rcube_utils::get_input_value('_password', rcube_utils::INPUT_POST, true);
     $size = (int) rcube_utils::get_input_value('_size', rcube_utils::INPUT_POST);
     if ($size > 4096) {
         $size = 4096;
     }
     $ident = rcube_mime::decode_address_list($user, 1, false);
     if (empty($ident)) {
         $this->rc->output->show_message('enigma.keygenerateerror', 'error');
         $this->rc->output->send();
     }
     $this->enigma->load_engine();
     $result = $this->enigma->engine->generate_key(array('user' => $ident[1]['name'], 'email' => $ident[1]['mailto'], 'password' => $pass, 'size' => $size));
     if ($result instanceof enigma_key) {
         $this->rc->output->command('enigma_key_create_success');
         $this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation');
     } else {
         $this->rc->output->show_message('enigma.keygenerateerror', 'error');
     }
     $this->rc->output->send();
 }
Пример #21
0
 /**
  * Deprecated methods (to be removed)
  */
 public function decode_address_list($input, $max = null, $decode = true, $fallback = null)
 {
     return rcube_mime::decode_address_list($input, $max, $decode, $fallback);
 }
Пример #22
0
 /**
  * Helper method to packs all the given messages into a zip archive
  *
  * @param array List of message UIDs to download
  */
 private function _download_messages($messageset)
 {
     $rcmail = rcmail::get_instance();
     $imap = $rcmail->get_storage();
     $mode = rcube_utils::get_input_value('_mode', rcube_utils::INPUT_POST);
     $temp_dir = $rcmail->config->get('temp_dir');
     $tmpfname = tempnam($temp_dir, 'zipdownload');
     $tempfiles = array($tmpfname);
     $folders = count($messageset) > 1;
     // @TODO: file size limit
     // open zip file
     $zip = new ZipArchive();
     $zip->open($tmpfname, ZIPARCHIVE::OVERWRITE);
     if ($mode == 'mbox') {
         $tmpfp = fopen($tmpfname . '.mbox', 'w');
     }
     foreach ($messageset as $mbox => $uids) {
         $imap->set_folder($mbox);
         $path = $folders ? str_replace($imap->get_hierarchy_delimiter(), '/', $mbox) . '/' : '';
         if ($uids === '*') {
             $index = $imap->index($mbox, null, null, true);
             $uids = $index->get();
         }
         foreach ($uids as $uid) {
             $headers = $imap->get_message_headers($uid);
             if ($mode == 'mbox') {
                 // Sender address
                 $from = rcube_mime::decode_address_list($headers->from, null, true, $headers->charset, true);
                 $from = array_shift($from);
                 $from = preg_replace('/\\s/', '-', $from);
                 // Received (internal) date
                 $date = rcube_utils::anytodatetime($headers->internaldate);
                 if ($date) {
                     $date->setTimezone(new DateTimeZone('UTC'));
                     $date = $date->format(self::MBOX_DATE_FORMAT);
                 }
                 // Mbox format header (RFC4155)
                 $header = sprintf("From %s %s\r\n", $from ?: 'MAILER-DAEMON', $date ?: '');
                 fwrite($tmpfp, $header);
                 // Use stream filter to quote "From " in the message body
                 stream_filter_register('mbox_filter', 'zipdownload_mbox_filter');
                 $filter = stream_filter_append($tmpfp, 'mbox_filter');
                 $imap->get_raw_body($uid, $tmpfp);
                 stream_filter_remove($filter);
                 fwrite($tmpfp, "\r\n");
             } else {
                 // maildir
                 $subject = rcube_mime::decode_header($headers->subject, $headers->charset);
                 $subject = $this->_filename_from_subject(mb_substr($subject, 0, 16));
                 $subject = $this->_convert_filename($subject);
                 $disp_name = $path . $uid . ($subject ? " {$subject}" : '') . '.eml';
                 $tmpfn = tempnam($temp_dir, 'zipmessage');
                 $tmpfp = fopen($tmpfn, 'w');
                 $imap->get_raw_body($uid, $tmpfp);
                 $tempfiles[] = $tmpfn;
                 fclose($tmpfp);
                 $zip->addFile($tmpfn, $disp_name);
             }
         }
     }
     $filename = $folders ? 'messages' : $imap->get_folder();
     if ($mode == 'mbox') {
         $tempfiles[] = $tmpfname . '.mbox';
         fclose($tmpfp);
         $zip->addFile($tmpfname . '.mbox', $filename . '.mbox');
     }
     $zip->close();
     $this->_deliver_zipfile($tmpfname, $filename . '.zip');
     // delete temporary files from disk
     foreach ($tempfiles as $tmpfn) {
         unlink($tmpfn);
     }
     exit;
 }