diff --git a/CHANGELOG b/CHANGELOG index 1281f0ed8..d4465f382 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Support both comma and semicolon as recipient separator, drop recipients_separator option (#5092) - Plugin API: Added 'show_bytes' hook (#5001) - subscriptions_option: show \\Noselect folders greyed out (#5621) - Add option to not indent quoted text on top-posting reply (#5105) diff --git a/config/defaults.inc.php b/config/defaults.inc.php index fbbb2d895..b5e1c1f92 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -761,9 +761,6 @@ $config['spellcheck_ignore_nums'] = false; // Makes that words with symbols will be ignored (e.g. g@@gle) $config['spellcheck_ignore_syms'] = false; -// Use this char/string to separate recipients when composing a new message -$config['recipients_separator'] = ','; - // Number of lines at the end of a message considered to contain the signature. // Increase this value if signatures are not properly detected and colored $config['sig_max_lines'] = 15; diff --git a/program/js/app.js b/program/js/app.js index 2fafb8085..9d0cb6bbd 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -58,8 +58,8 @@ function rcube_webmail() request_timeout: 180, // seconds draft_autosave: 0, // seconds comm_path: './', - recipients_separator: ',', - recipients_delimiter: ', ', + recipients_separator: ',', // @deprecated + recipients_delimiter: ', ', // @deprecated popup_width: 1150, popup_width_small: 900 }; @@ -4299,8 +4299,6 @@ function rcube_webmail() this.init_address_input_events = function(obj, props) { - this.env.recipients_delimiter = this.env.recipients_separator + ' '; - obj.keydown(function(e) { return ref.ksearch_keydown(e, this, props); }) .attr({ 'autocomplete': 'off', 'aria-autocomplete': 'list', 'aria-expanded': 'false', 'role': 'combobox' }); @@ -4377,7 +4375,7 @@ function rcube_webmail() field = field.length ? field.attr('id').replace('_', '') : 'to'; } - var recipients = [], input = $('#_'+field), delim = this.env.recipients_delimiter; + var recipients = [], input = $('#_' + field); if (this.contact_list && this.contact_list.selection.length) { for (var id, n=0; n < this.contact_list.selection.length; n++) { @@ -4396,10 +4394,10 @@ function rcube_webmail() } if (recipients.length && input.length) { - var oldval = input.val(), rx = new RegExp(RegExp.escape(delim) + '\\s*$'); - if (oldval && !rx.test(oldval)) - oldval += delim + ' '; - input.val(oldval + recipients.join(delim + ' ') + delim + ' ').change(); + var oldval = input.val(); + if (oldval && !/[,;]\s*$/.test(oldval)) + oldval += ', '; + input.val(oldval + recipients.join(', ') + ', ').change(); this.triggerEvent('add-recipient', { field:field, recipients:recipients }); } @@ -4885,9 +4883,7 @@ function rcube_webmail() show_sig = this.env.show_sig; var id = obj.options[obj.selectedIndex].value, - sig = this.env.identity, - delim = this.env.recipients_separator, - rx_delim = RegExp.escape(delim); + sig = this.env.identity; // enable manual signature insert if (this.env.signatures && this.env.signatures[id]) { @@ -4920,19 +4916,15 @@ function rcube_webmail() } // cleanup - rx = new RegExp(rx_delim + '\\s*' + rx_delim, 'g'); - input_val = String(input_val).replace(rx, delim); - rx = new RegExp('^[\\s' + rx_delim + ']+'); - input_val = input_val.replace(rx, ''); + input_val = String(input_val).replace(/[,;]\s*[,;]/g, ',').replace(/^[\s,;]+/, ''); // add new address(es) if (new_val && input_val.indexOf(new_val) == -1 && input_val.indexOf(new_val.replace(/"/g, '')) == -1) { if (input_val) { - rx = new RegExp('[' + rx_delim + '\\s]+$') - input_val = input_val.replace(rx, '') + delim + ' '; + input_val = input_val.replace(/[,;\s]+$/, '') + ', '; } - input_val += new_val + delim + ' '; + input_val += new_val + ', '; } if (old_val || new_val) @@ -5469,6 +5461,7 @@ function rcube_webmail() p = inp_value.lastIndexOf(this.ksearch_value, cpos), trigger = false, insert = '', + delim = ', ', // replace search string with full address pre = inp_value.substring(0, p), end = inp_value.substring(p+this.ksearch_value.length, inp_value.length); @@ -5477,16 +5470,16 @@ function rcube_webmail() // insert all members of a group if (typeof this.env.contacts[id] === 'object' && this.env.contacts[id].type == 'group' && !this.env.contacts[id].email) { - insert += this.env.contacts[id].name + this.env.recipients_delimiter; + insert += this.env.contacts[id].name + delim; this.group2expand[this.env.contacts[id].id] = $.extend({ input: this.ksearch_input }, this.env.contacts[id]); this.http_request('mail/group-expand', {_source: this.env.contacts[id].source, _gid: this.env.contacts[id].id}, false); } else if (typeof this.env.contacts[id] === 'object' && this.env.contacts[id].name) { - insert = this.env.contacts[id].name + this.env.recipients_delimiter; + insert = this.env.contacts[id].name + delim; trigger = true; } else if (typeof this.env.contacts[id] === 'string') { - insert = this.env.contacts[id] + this.env.recipients_delimiter; + insert = this.env.contacts[id] + delim; trigger = true; } @@ -5524,10 +5517,9 @@ function rcube_webmail() if (this.ksearch_pane && this.ksearch_pane.is(":visible")) this.ksearch_pane.hide(); - // get string from current cursor pos to last comma + // get string from cursor position back to the last comma or semicolon var cpos = this.get_caret_pos(this.ksearch_input), - p = inp_value.lastIndexOf(this.env.recipients_separator, cpos-1), - q = inp_value.substring(p+1, cpos), + q = inp_value.substr(0, cpos).split(/[,;]/).pop(), min = this.env.autocomplete_min_length, data = this.ksearch_data; diff --git a/program/steps/mail/autocomplete.inc b/program/steps/mail/autocomplete.inc index 8bee48552..380b3b21d 100644 --- a/program/steps/mail/autocomplete.inc +++ b/program/steps/mail/autocomplete.inc @@ -26,9 +26,8 @@ if ($RCMAIL->action == 'group-expand') { $abook->set_group($gid); $abook->set_pagesize(9999); // TODO: limit number of group members by config? - $separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' '; - $result = $abook->list_records($RCMAIL->config->get('contactlist_fields')); - $members = array(); + $result = $abook->list_records($RCMAIL->config->get('contactlist_fields')); + $members = array(); while ($result && ($record = $result->iterate())) { $emails = (array) $abook->get_col_values('email', $record, true); @@ -37,7 +36,7 @@ if ($RCMAIL->action == 'group-expand') { } } - $OUTPUT->command('replace_group_recipients', $gid, join($separator, array_unique($members))); + $OUTPUT->command('replace_group_recipients', $gid, join(', ', array_unique($members))); } $OUTPUT->send(); diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index ca09324ec..156e86b20 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -98,7 +98,6 @@ $OUTPUT->set_env('session_id', session_id()); $OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); $OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0); $OUTPUT->set_env('sig_below', $RCMAIL->config->get('sig_below')); -$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ','))); $OUTPUT->set_env('save_localstorage', (bool)$RCMAIL->config->get('compose_save_localstorage')); $OUTPUT->set_env('max_disclosed_recipients', (int) $RCMAIL->config->get('max_disclosed_recipients', 5)); $OUTPUT->set_env('is_sent', false); @@ -566,7 +565,7 @@ function rcmail_compose_header_value($header) $fvalue = ''; $decode_header = true; $charset = $MESSAGE->headers->charset; - $separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' '; + $separator = ', '; // we have a set of recipients stored is session if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto']) diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 93483cd66..9c337ccb9 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -864,13 +864,13 @@ function rcmail_email_input_format($mailto, $count=false, $check=true) // simplified email regexp, supporting quoted local part $email_regexp = '(\S+|("[^"]+"))@\S+'; - $delim = trim($RCMAIL->config->get('recipients_separator', ',')); - $regexp = array("/[,;$delim]\s*[\r\n]+/", '/[\r\n]+/', "/[,;$delim]\s*\$/m", '/;/', '/(\S{1})(<'.$email_regexp.'>)/U'); - $replace = array($delim.' ', ', ', '', $delim, '\\1 \\2'); + $delim = ',;'; + $regexp = array("/[$delim]\s*[\r\n]+/", '/[\r\n]+/', "/[$delim]\s*\$/m", '/;/', '/(\S{1})(<'.$email_regexp.'>)/U'); + $replace = array(', ', ', ', '', ',', '\\1 \\2'); // replace new lines and strip ending ', ', make address input more valid $mailto = trim(preg_replace($regexp, $replace, $mailto)); - $items = rcube_utils::explode_quoted_string($delim, $mailto); + $items = rcube_utils::explode_quoted_string("[$delim]", $mailto); $result = array(); foreach ($items as $item) {