diff options
Diffstat (limited to 'program/steps/mail')
-rw-r--r-- | program/steps/mail/compose.inc | 63 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 53 | ||||
-rw-r--r-- | program/steps/mail/sendmail.inc | 33 |
3 files changed, 99 insertions, 50 deletions
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index dc2452506..646d2bcd1 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -109,7 +109,8 @@ if (!is_array($COMPOSE)) $OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning', 'cancel', 'nobodywarning', 'notsentwarning', 'notuploadedwarning', 'savingmessage', 'sendingmessage', 'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany', - 'fileuploaderror', 'sendmessage'); + 'fileuploaderror', 'sendmessage', 'savenewresponse', 'responsename', 'responsetext', 'save', + 'savingresponse'); $OUTPUT->set_env('compose_id', $COMPOSE['id']); $OUTPUT->set_pagetitle(rcube_label('compose')); @@ -852,29 +853,14 @@ function rcmail_compose_body($attrib) // Set language list if (!empty($CONFIG['enable_spellcheck'])) { - $engine = $RCMAIL->config->get('spellcheck_engine','googie'); + $engine = new rcube_spellchecker(); $dictionary = (bool) $RCMAIL->config->get('spellcheck_dictionary'); - $spellcheck_langs = (array) $RCMAIL->config->get('spellcheck_languages', - array('da'=>'Dansk', 'de'=>'Deutsch', 'en' => 'English', 'es'=>'Español', - 'fr'=>'Français', 'it'=>'Italiano', 'nl'=>'Nederlands', 'pl'=>'Polski', - 'pt'=>'Português', 'ru'=>'Русский', 'fi'=>'Suomi', 'sv'=>'Svenska')); - - // googie works only with two-letter codes - if ($engine == 'googie') { - $lang = strtolower(substr($_SESSION['language'], 0, 2)); - - $spellcheck_langs_googie = array(); - foreach ($spellcheck_langs as $key => $name) - $spellcheck_langs_googie[strtolower(substr($key,0,2))] = $name; - $spellcheck_langs = $spellcheck_langs_googie; - } - else { - $lang = $_SESSION['language']; + $spellcheck_langs = $engine->languages(); + $lang = $_SESSION['language']; - // if not found in the list, try with two-letter code - if (!$spellcheck_langs[$lang]) - $lang = strtolower(substr($lang, 0, 2)); - } + // if not found in the list, try with two-letter code + if (!$spellcheck_langs[$lang]) + $lang = strtolower(substr($lang, 0, 2)); if (!$spellcheck_langs[$lang]) $lang = 'en'; @@ -1757,6 +1743,38 @@ function compose_file_drop_area($attrib) } +/** + * + */ +function rcmail_compose_responses_list($attrib) +{ + global $RCMAIL, $OUTPUT; + + $attrib += array('id' => 'rcmresponseslist', 'tagname' => 'ul', 'cols' => 1); + + $jsenv = array(); + $list = new html_table($attrib); + foreach ($RCMAIL->get_compose_responses(true) as $response) { + $key = $response['key']; + $item = html::a(array( + 'href '=> '#'.urlencode($response['name']), + 'class' => rtrim('insertresponse ' . $attrib['itemclass']), + 'unselectable' => 'on', + 'rel' => $key, + ), Q($response['name'])); + + $jsenv[$key] = $response; + $list->add(array(), $item); + } + + // set client env + $OUTPUT->set_env('textresponses', $jsenv); + $OUTPUT->add_gui_object('responseslist', $attrib['id']); + + return $list->show(); +} + + // register UI objects $OUTPUT->add_handlers(array( 'composeheaders' => 'rcmail_compose_headers', @@ -1773,6 +1791,7 @@ $OUTPUT->add_handlers(array( 'storetarget' => 'rcmail_store_target_selection', 'addressbooks' => 'rcmail_addressbook_list', 'addresslist' => 'rcmail_contacts_list', + 'responseslist' => 'rcmail_compose_responses_list', )); $OUTPUT->send('compose'); diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 48afecb60..78a977b82 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -97,6 +97,7 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') { $OUTPUT->set_env('delimiter', $delimiter); $OUTPUT->set_env('threading', $threading); $OUTPUT->set_env('threads', $threading || $RCMAIL->storage->get_capability('THREAD')); + $OUTPUT->set_env('reply_all_mode', (int) $RCMAIL->config->get('reply_all_mode')); $OUTPUT->set_env('preview_pane_mark_read', $RCMAIL->config->get('preview_pane_mark_read', 0)); if ($RCMAIL->storage->get_capability('QUOTA')) { $OUTPUT->set_env('quota', true); @@ -1775,28 +1776,34 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r } } - $from_idx = null; - $found_idx = null; - $default_identity = 0; // default identity is always first on the list + // decode From: address + $from = rcube_mime::decode_address_list($MESSAGE->headers->from, null, true, $MESSAGE->headers->charset); + $from = array_shift($from); + $from['mailto'] = strtolower($from['mailto']); + + $from_idx = null; + $found_idx = array('to' => null, 'from' => null); + $check_from = in_array($compose_mode, array('draft', 'edit', 'reply')); // Select identity foreach ($identities as $idx => $ident) { - // use From header - if (in_array($compose_mode, array('draft', 'edit'))) { - if ($MESSAGE->headers->from == $ident['ident']) { + // use From: header when in edit/draft or reply-to-self + if ($check_from && $from['mailto'] == strtolower($ident['email_ascii'])) { + // remember first matching identity address + if ($found_idx['from'] === null) { + $found_idx['from'] = $idx; + } + // match identity name + if ($from['name'] && $ident['name'] && $from['name'] == $ident['name']) { $from_idx = $idx; break; } } - // reply to yourself - else if ($compose_mode == 'reply' && $MESSAGE->headers->from == $ident['ident']) { - $from_idx = $idx; - break; - } - // use replied message recipients + // use replied/forwarded message recipients else if (($found = array_search(strtolower($ident['email_ascii']), $a_recipients)) !== false) { - if ($found_idx === null) { - $found_idx = $idx; + // remember first matching identity address + if ($found_idx['to'] === null) { + $found_idx['to'] = $idx; } // match identity name if ($a_names[$found] && $ident['name'] && $a_names[$found] == $ident['name']) { @@ -1806,22 +1813,27 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r } } - // If matching by name+address doesn't found any matches, get first found address (identity) + // If matching by name+address didn't find any matches, + // get first found identity (address) if any if ($from_idx === null) { - $from_idx = $found_idx; + $from_idx = $found_idx['from'] !== null ? $found_idx['from'] : $found_idx['to']; } // Try Return-Path if ($from_idx === null && ($return_path = $MESSAGE->headers->others['return-path'])) { + $return_path = array_map('strtolower', (array) $return_path); + foreach ($identities as $idx => $ident) { // Return-Path header contains an email address, but on some mailing list // it can be e.g. <pear-dev-return-55250-local=domain.tld@lists.php.net> // where local@domain.tld is the address we're looking for (#1489241) - $ident1 = $ident['email_ascii']; + $ident1 = strtolower($ident['email_ascii']); $ident2 = str_replace('@', '=', $ident1); + $ident1 = '<' . $ident1 . '>'; + $ident2 = '-' . $ident2 . '@'; - foreach ((array)$return_path as $path) { - if (stripos($path, $ident1) !== false || stripos($path, $ident2)) { + foreach ($return_path as $path) { + if ($path == $ident1 || stripos($path, $ident2)) { $from_idx = $idx; break 2; } @@ -1835,7 +1847,8 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r $selected = $plugin['selected']; - return $identities[$selected !== null ? $selected : $default_identity]; + // default identity is always first on the list + return $identities[$selected !== null ? $selected : 0]; } // Fixes some content-type names diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index ccb8978be..52b02ecff 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -615,22 +615,39 @@ else { } // add stored attachments, if any -if (is_array($COMPOSE['attachments'])) -{ +if (is_array($COMPOSE['attachments'])) { foreach ($COMPOSE['attachments'] as $id => $attachment) { // This hook retrieves the attachment contents from the file storage backend $attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment); - $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]*/'; - $message_body = $MAIL_MIME->getHTMLBody(); - if ($isHtml && (preg_match($dispurl, $message_body) > 0)) { - $message_body = preg_replace($dispurl, ' src="'.$attachment['name'].'" ', $message_body); + if ($isHtml) { + $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]*/'; + $message_body = $MAIL_MIME->getHTMLBody(); + $is_inline = preg_match($dispurl, $message_body); + } + else { + $is_inline = false; + } + + // inline image + if ($is_inline) { + // Mail_Mime does not support many inline attachments with the same name (#1489406) + // we'll generate cid: urls here to workaround this + $cid = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true)); + if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $from, $matches)) { + $cid .= $matches[1]; + } else { + $cid .= '@localhost'; + } + + $message_body = preg_replace($dispurl, ' src="cid:' . $cid . '" ', $message_body); + $MAIL_MIME->setHTMLBody($message_body); if ($attachment['data']) - $MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false); + $MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false, $cid); else - $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true); + $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true, $cid); } else { $ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914 |