diff options
author | alecpl <alec@alec.pl> | 2010-09-29 12:36:28 +0000 |
---|---|---|
committer | alecpl <alec@alec.pl> | 2010-09-29 12:36:28 +0000 |
commit | e99991996dbb9e7b0b0ff6cfa94dc0fb2522eb66 (patch) | |
tree | 8031feaef48d8d30de1253318993f8c0a2223674 /program/steps/mail | |
parent | d7f9eb573b82ca55c521b68f7cf3ad8de55ab8ba (diff) |
- Add Internationalized Domain Name (IDNA) support (#1483894)
Diffstat (limited to 'program/steps/mail')
-rw-r--r-- | program/steps/mail/addcontact.inc | 4 | ||||
-rw-r--r-- | program/steps/mail/compose.inc | 77 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 53 | ||||
-rw-r--r-- | program/steps/mail/sendmail.inc | 39 |
4 files changed, 99 insertions, 74 deletions
diff --git a/program/steps/mail/addcontact.inc b/program/steps/mail/addcontact.inc index 128cb4ea3..7a2b69e3d 100644 --- a/program/steps/mail/addcontact.inc +++ b/program/steps/mail/addcontact.inc @@ -36,7 +36,9 @@ if (!empty($_POST['_address']) && is_object($CONTACTS)) 'email' => $contact_arr[1]['mailto'], 'name' => $contact_arr[1]['name'] ); - + + $contact['email'] = idn_to_utf8($contact['email']); + // 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'], '@')))); diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 521a0f7b4..d01ca36ca 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -227,14 +227,12 @@ function rcmail_compose_headers($attrib) $fvalue = urldecode($_SESSION['mailto'][$mailto_id]); case 'cc': - if (!$fname) - { + if (!$fname) { $fname = '_cc'; $header = $param = 'cc'; } case 'bcc': - if (!$fname) - { + if (!$fname) { $fname = '_bcc'; $header = $param = 'bcc'; } @@ -251,7 +249,7 @@ function rcmail_compose_headers($attrib) $field_type = 'html_inputfield'; break; } - + if ($fname && !empty($_POST[$fname])) { $fvalue = get_input_value($fname, RCUBE_INPUT_POST, TRUE); } @@ -262,13 +260,10 @@ function rcmail_compose_headers($attrib) // get recipent address(es) out of the message headers if ($header=='to' && !empty($MESSAGE->headers->replyto)) $fvalue = $MESSAGE->headers->replyto; - else if ($header=='to' && !empty($MESSAGE->headers->from)) $fvalue = $MESSAGE->headers->from; - // add recipent of original message if reply to all - else if ($header=='cc' && !empty($MESSAGE->reply_all)) - { + else if ($header=='cc' && !empty($MESSAGE->reply_all)) { if ($v = $MESSAGE->headers->to) $fvalue .= $v; @@ -277,39 +272,58 @@ function rcmail_compose_headers($attrib) } // split recipients and put them back together in a unique way - if (!empty($fvalue)) - { + if (!empty($fvalue)) { $to_addresses = $IMAP->decode_address_list($fvalue); $fvalue = ''; - foreach ($to_addresses as $addr_part) - { - if (!empty($addr_part['mailto']) - && !in_array($addr_part['mailto'], $sa_recipients) + foreach ($to_addresses as $addr_part) { + if (empty($addr_part['mailto'])) + continue; + + $mailto = idn_to_utf8($addr_part['mailto']); + + if (!in_array($mailto, $sa_recipients) && (!$MESSAGE->compose_from - || !in_array_nocase($addr_part['mailto'], $MESSAGE->compose_from) - || (count($to_addresses)==1 && $header=='to'))) // allow reply to yourself - { - $fvalue .= (strlen($fvalue) ? ', ':'').$addr_part['string']; + || !in_array_nocase($mailto, $MESSAGE->compose_from) + || (count($to_addresses)==1 && $header=='to')) // allow reply to yourself + ) { + if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name']) + $string = format_email_recipient($mailto, $addr_part['name']); + else + $string = $mailto; + $fvalue .= (strlen($fvalue) ? ', ':'') . $string; $sa_recipients[] = $addr_part['mailto']; } } } } - else if ($header && in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) - { + else if ($header && in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) { // get drafted headers if ($header=='to' && !empty($MESSAGE->headers->to)) $fvalue = $MESSAGE->get_header('to'); - - if ($header=='cc' && !empty($MESSAGE->headers->cc)) + else if ($header=='cc' && !empty($MESSAGE->headers->cc)) $fvalue = $MESSAGE->get_header('cc'); - - if ($header=='bcc' && !empty($MESSAGE->headers->bcc)) + else if ($header=='bcc' && !empty($MESSAGE->headers->bcc)) $fvalue = $MESSAGE->get_header('bcc'); + + $addresses = $IMAP->decode_address_list($fvalue); + $fvalue = ''; + + foreach ($addresses as $addr_part) { + if (empty($addr_part['mailto'])) + continue; + + $mailto = idn_to_utf8($addr_part['mailto']); + + if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name']) + $string = format_email_recipient($mailto, $addr_part['name']); + else + $string = $mailto; + $fvalue .= (strlen($fvalue) ? ', ':'') . $string; + } } - + if ($fname && $field_type) { // pass the following attributes to the form class @@ -326,7 +340,7 @@ function rcmail_compose_headers($attrib) if ($form_start) $out = $form_start.$out; - return $out; + return $out; } @@ -350,7 +364,7 @@ function rcmail_compose_header_from($attrib) foreach ($a_to as $addr) { if (!empty($addr['mailto'])) - $a_recipients[] = mb_strtolower($addr['mailto']); + $a_recipients[] = mb_strtolower(idn_to_utf8($addr['mailto'])); } if (!empty($MESSAGE->headers->cc)) @@ -359,7 +373,7 @@ function rcmail_compose_header_from($attrib) foreach ($a_cc as $addr) { if (!empty($addr['mailto'])) - $a_recipients[] = mb_strtolower($addr['mailto']); + $a_recipients[] = mb_strtolower(idn_to_utf8($addr['mailto'])); } } } @@ -377,6 +391,7 @@ function rcmail_compose_header_from($attrib) foreach ($user_identities as $sql_arr) { + $sql_arr['email'] = mb_strtolower(idn_to_utf8($sql_arr['email'])); $identity_id = $sql_arr['identity_id']; $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id); @@ -401,7 +416,7 @@ function rcmail_compose_header_from($attrib) if ($compose_mode == RCUBE_COMPOSE_DRAFT && strstr($MESSAGE->headers->from, $sql_arr['email'])) $from_id = $sql_arr['identity_id']; // set identity if it's one of the reply-message recipients (with prio for default identity) - else if (in_array(mb_strtolower($sql_arr['email']), $a_recipients) && (empty($from_id) || $sql_arr['standard'])) + else if (in_array($sql_arr['email'], $a_recipients) && (empty($from_id) || $sql_arr['standard'])) $from_id = $sql_arr['identity_id']; } } @@ -925,7 +940,7 @@ function rcmail_compose_subject($attrib) $out = $form_start ? "$form_start\n" : ''; $out .= $textfield->show($subject); $out .= $form_end ? "\n$form_end" : ''; - + return $out; } diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 119a5da31..95bae0b10 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -24,7 +24,9 @@ $SENT_MBOX = $RCMAIL->config->get('sent_mbox'); $DRAFTS_MBOX = $RCMAIL->config->get('drafts_mbox'); $SEARCH_MODS_DEFAULT = array('*' => array('subject'=>1, 'from'=>1), $SENT_MBOX => array('subject'=>1, 'to'=>1), $DRAFTS_MBOX => array('subject'=>1, 'to'=>1)); -$EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9][a-z0-9\-\.]*\\.[a-z]{2,5})'; +// Simplified for IDN in Unicode +//$EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9][a-z0-9\-\.]*\\.[a-z]{2,5})'; +$EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[^.].*\\.[a-z]{2,5})'; // actions that do not require imap connection here $NOIMAP_ACTIONS = array('addcontact', 'autocomplete', 'upload', 'display-attachment', 'remove-attachment', 'get'); @@ -1241,7 +1243,7 @@ function rcmail_alter_html_link($matches) */ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null) { - global $IMAP, $RCMAIL, $PRINT_MODE, $CONFIG, $OUTPUT, $EMAIL_ADDRESS_PATTERN; + global $IMAP, $RCMAIL, $PRINT_MODE, $CONFIG; static $got_writable_abook = null; $a_parts = $IMAP->decode_address_list($input); @@ -1259,27 +1261,40 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null) foreach ($a_parts as $part) { $j++; + + $name = $part['name']; + $mailto = $part['mailto']; + $string = $part['string']; + + // IDNA ASCII to Unicode + if ($name == $mailto) + $name = idn_to_utf8($name); + if ($string == $mailto) + $string = idn_to_utf8($string); + $mailto = idn_to_utf8($mailto); + if ($PRINT_MODE) { - $out .= sprintf('%s <%s>', Q($part['name']), $part['mailto']); + $out .= sprintf('%s <%s>', Q($name), $mailto); } else if (check_email($part['mailto'], false)) { if ($linked) { $out .= html::a(array( - 'href' => 'mailto:'.$part['mailto'], - 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($part['mailto'])), - 'title' => $part['mailto'], + 'href' => 'mailto:'.$mailto, + 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)), + 'title' => $mailto, 'class' => "rcmContactAddress", ), - Q($part['name'])); + Q($name ? $name : $mailto)); } else { - $out .= html::span(array('title' => $part['mailto'], 'class' => "rcmContactAddress"), Q($part['name'])); + $out .= html::span(array('title' => $mailto, 'class' => "rcmContactAddress"), + Q($name ? $name : $mailto)); } if ($addicon && $got_writable_abook) { $out .= ' ' . html::a(array( 'href' => "#add", - 'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($part['string'])), + 'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($string)), 'title' => rcube_label('addtoaddressbook'), ), html::img(array( @@ -1289,10 +1304,10 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null) } } else { - if ($part['name']) - $out .= Q($part['name']); - if ($part['mailto']) - $out .= (strlen($out) ? ' ' : '') . sprintf('<%s>', Q($part['mailto'])); + if ($name) + $out .= Q($name); + if ($mailto) + $out .= (strlen($out) ? ' ' : '') . sprintf('<%s>', Q($mailto)); } if ($c>$j) @@ -1375,7 +1390,7 @@ function rcmail_draftinfo_decode($str) function rcmail_message_part_controls() - { +{ global $MESSAGE; $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC)); @@ -1397,12 +1412,12 @@ function rcmail_message_part_controls() } return $table->show($attrib); - } +} function rcmail_message_part_frame($attrib) - { +{ global $MESSAGE; $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))]; @@ -1411,21 +1426,21 @@ function rcmail_message_part_frame($attrib) $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_show=' : '_preload='), $_SERVER['QUERY_STRING']); return html::iframe($attrib); - } +} /** * clear message composing settings */ function rcmail_compose_cleanup() - { +{ if (!isset($_SESSION['compose'])) return; $rcmail = rcmail::get_instance(); $rcmail->plugins->exec_hook('attachments_cleanup', array()); $rcmail->session->remove('compose'); - } +} /** diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 75d406b71..45afa046f 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -60,8 +60,7 @@ if (!$savedraft) { function rcmail_encrypt_header($what) { global $CONFIG, $RCMAIL; - if (!$CONFIG['http_received_header_encrypt']) - { + if (!$CONFIG['http_received_header_encrypt']) { return $what; } return $RCMAIL->encrypt($what); @@ -69,30 +68,21 @@ function rcmail_encrypt_header($what) // get identity record function rcmail_get_identity($id) - { +{ global $USER, $OUTPUT; - if ($sql_arr = $USER->get_identity($id)) - { + if ($sql_arr = $USER->get_identity($id)) { $out = $sql_arr; $out['mailto'] = $sql_arr['email']; - - // Special chars as defined by RFC 822 need to in quoted string (or escaped). - if (preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $sql_arr['name'])) - $name = '"' . addcslashes($sql_arr['name'], '"') . '"'; - else - $name = $sql_arr['name']; - - $out['string'] = rcube_charset_convert($name, RCMAIL_CHARSET, $OUTPUT->get_charset()); - if ($sql_arr['email']) - $out['string'] .= ' <' . $sql_arr['email'] . '>'; + $out['string'] = format_email_recipient($sql_arr['email'], + rcube_charset_convert($sql_arr['name'], RCMAIL_CHARSET, $OUTPUT->get_charset())); return $out; - } - - return FALSE; } + return FALSE; +} + /** * go from this: * <img src="http[s]://.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" /> @@ -146,7 +136,7 @@ function rcmail_fix_emoticon_paths(&$mime_message) } // parse email address input (and count addresses) -function rcmail_email_input_format($mailto, $count=false) +function rcmail_email_input_format($mailto, $count=false, $check=true) { global $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT; @@ -163,9 +153,11 @@ function rcmail_email_input_format($mailto, $count=false) $item = trim($item); // address in brackets without name (do nothing) if (preg_match('/^<\S+@\S+>$/', $item)) { + $item = idn_to_ascii($item); $result[] = $item; // address without brackets and without name (add brackets) } else if (preg_match('/^\S+@\S+$/', $item)) { + $item = idn_to_ascii($item); $result[] = '<'.$item.'>'; // address with name (handle name) } else if (preg_match('/\S+@\S+>*$/', $item, $matches)) { @@ -176,6 +168,7 @@ function rcmail_email_input_format($mailto, $count=false) && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) { $name = '"'.addcslashes($name, '"').'"'; } + $address = idn_to_ascii($address); if (!preg_match('/^<\S+@\S+>$/', $address)) $address = '<'.$address.'>'; @@ -187,7 +180,7 @@ function rcmail_email_input_format($mailto, $count=false) // check address format $item = trim($item, '<>'); - if ($item && !check_email($item)) { + if ($item && $check && !check_email($item)) { $EMAIL_FORMAT_ERROR = $item; return; } @@ -297,7 +290,7 @@ if (!empty($mailcc)) if (!empty($mailbcc)) $headers['Bcc'] = $mailbcc; - + if (!empty($identity_arr['bcc'])) { $headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc']; $RECIPIENT_COUNT ++; @@ -319,11 +312,11 @@ if (!empty($identity_arr['organization'])) if (!empty($_POST['_replyto'])) $headers['Reply-To'] = rcmail_email_input_format(get_input_value('_replyto', RCUBE_INPUT_POST, TRUE, $message_charset)); else if (!empty($identity_arr['reply-to'])) - $headers['Reply-To'] = $identity_arr['reply-to']; + $headers['Reply-To'] = rcmail_email_input_format($identity_arr['reply-to'], false, true); if (!empty($_SESSION['compose']['reply_msgid'])) $headers['In-Reply-To'] = $_SESSION['compose']['reply_msgid']; - + // remember reply/forward UIDs in special headers if (!empty($_SESSION['compose']['reply_uid']) && $savedraft) $headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $_SESSION['compose']['reply_uid']); |