diff options
-rw-r--r-- | CHANGELOG | 2 | ||||
-rw-r--r-- | program/js/editor.js | 2 | ||||
-rw-r--r-- | program/lib/Roundcube/rcube_spellchecker.php | 3 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 42 | ||||
-rw-r--r-- | program/steps/mail/sendmail.inc | 33 | ||||
-rw-r--r-- | tests/MailFunc.php | 48 |
6 files changed, 104 insertions, 26 deletions
@@ -1,6 +1,8 @@ CHANGELOG Roundcube Webmail =========================== +- Improve identity selection based on From: header (#1489378) +- Fix issue where mails with inline images of the same name contained only the first image multiple times (#1489406) - Use left/right arrow keys to collapse/expand thread and spacebar to select a row, change Ctrl key behavior (#1489392) - Fix an issue where using arrow keys to go up a list can result in selected message being under headers (#1489403) - Fix an issue where Home/End keys don't focus list row properly, don't scrollTo properly (#1489396) diff --git a/program/js/editor.js b/program/js/editor.js index b349c9c35..020971d6e 100644 --- a/program/js/editor.js +++ b/program/js/editor.js @@ -162,7 +162,7 @@ function rcmail_editor_images() for (i in files) { att = files[i]; if (att.complete && att.mimetype.startsWith('image/')) { - list.push([att.name, rcmail.env.comm_path+'&_action=display-attachment&_file='+i+'&_id='+rcmail.env.compose_id]); + list.push([att.name, rcmail.env.comm_path+'&_id='+rcmail.env.compose_id+'&_action=display-attachment&_file='+i]); } } diff --git a/program/lib/Roundcube/rcube_spellchecker.php b/program/lib/Roundcube/rcube_spellchecker.php index d087d2584..3182ff378 100644 --- a/program/lib/Roundcube/rcube_spellchecker.php +++ b/program/lib/Roundcube/rcube_spellchecker.php @@ -104,6 +104,9 @@ class rcube_spellchecker } } + // remove possible duplicates (#1489395) + $languages = array_unique($languages); + asort($languages); return $languages; diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 43651ecaa..b5a8de408 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -1781,28 +1781,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']) { @@ -1812,9 +1818,10 @@ 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 @@ -1845,7 +1852,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 diff --git a/tests/MailFunc.php b/tests/MailFunc.php index 08cbd4ed0..ab0074ef2 100644 --- a/tests/MailFunc.php +++ b/tests/MailFunc.php @@ -217,4 +217,52 @@ class MailFunc extends PHPUnit_Framework_TestCase $this->assertSame($identities[1], $res); } + + /** + * Test identities selection (#1489378) + */ + function test_rcmail_identity_select2() + { + $identities = array( + array( + 'name' => 'Test 1', + 'email_ascii' => 'addr1@domain.tld', + 'ident' => 'Test 1 <addr1@domain.tld>', + ), + array( + 'name' => 'Test 2', + 'email_ascii' => 'addr2@domain.tld', + 'ident' => 'Test 2 <addr2@domain.tld>', + ), + array( + 'name' => 'Test 3', + 'email_ascii' => 'addr3@domain.tld', + 'ident' => 'Test 3 <addr3@domain.tld>', + ), + array( + 'name' => 'Test 4', + 'email_ascii' => 'addr2@domain.tld', + 'ident' => 'Test 4 <addr2@domain.tld>', + ), + ); + + $message = new stdClass; + $message->headers = new rcube_message_header; + + $message->headers->set('From', '<addr2@domain.tld>'); + $res = rcmail_identity_select($message, $identities); + $this->assertSame($identities[1], $res); + + $message->headers->set('From', 'Test 2 <addr2@domain.tld>'); + $res = rcmail_identity_select($message, $identities); + $this->assertSame($identities[1], $res); + + $message->headers->set('From', 'Other <addr2@domain.tld>'); + $res = rcmail_identity_select($message, $identities); + $this->assertSame($identities[1], $res); + + $message->headers->set('From', 'Test 4 <addr2@domain.tld>'); + $res = rcmail_identity_select($message, $identities); + $this->assertSame($identities[3], $res); + } } |