- Add Internationalized Domain Name (IDNA) support (#1483894)

release-0.6
alecpl 14 years ago
parent d7f9eb573b
commit e99991996d

@ -3,6 +3,7 @@ CHANGELOG Roundcube Webmail
- Messages caching: performance improvements, fixed syncing, fixes related with #1486748 - Messages caching: performance improvements, fixed syncing, fixes related with #1486748
- Add link to identities in compose window (#1486729) - Add link to identities in compose window (#1486729)
- Add Internationalized Domain Name (IDNA) support (#1483894)
RELEASE 0.4.1 RELEASE 0.4.1
------------- -------------

@ -15,6 +15,7 @@ $optional_php_exts = array(
'Multibyte' => 'mbstring', 'Multibyte' => 'mbstring',
'OpenSSL' => 'openssl', 'OpenSSL' => 'openssl',
'Mcrypt' => 'mcrypt', 'Mcrypt' => 'mcrypt',
'Intl' => 'intl',
); );
$required_libs = array( $required_libs = array(
@ -44,19 +45,20 @@ $optional_checks = array(
); );
$source_urls = array( $source_urls = array(
'Sockets' => 'http://www.php.net/manual/en/book.sockets.php', 'Sockets' => 'http://www.php.net/manual/en/book.sockets.php',
'Session' => 'http://www.php.net/manual/en/book.session.php', 'Session' => 'http://www.php.net/manual/en/book.session.php',
'PCRE' => 'http://www.php.net/manual/en/book.pcre.php', 'PCRE' => 'http://www.php.net/manual/en/book.pcre.php',
'FileInfo' => 'http://www.php.net/manual/en/book.fileinfo.php', 'FileInfo' => 'http://www.php.net/manual/en/book.fileinfo.php',
'Libiconv' => 'http://www.php.net/manual/en/book.iconv.php', 'Libiconv' => 'http://www.php.net/manual/en/book.iconv.php',
'Multibyte' => 'http://www.php.net/manual/en/book.mbstring.php', 'Multibyte' => 'http://www.php.net/manual/en/book.mbstring.php',
'Mcrypt' => 'http://www.php.net/manual/en/book.mcrypt.php', 'Mcrypt' => 'http://www.php.net/manual/en/book.mcrypt.php',
'OpenSSL' => 'http://www.php.net/manual/en/book.openssl.php', 'OpenSSL' => 'http://www.php.net/manual/en/book.openssl.php',
'JSON' => 'http://www.php.net/manual/en/book.json.php', 'JSON' => 'http://www.php.net/manual/en/book.json.php',
'DOM' => 'http://www.php.net/manual/en/book.dom.php', 'DOM' => 'http://www.php.net/manual/en/book.dom.php',
'PEAR' => 'http://pear.php.net', 'Intl' => 'http://www.php.net/manual/en/book.intl.php',
'MDB2' => 'http://pear.php.net/package/MDB2', 'PEAR' => 'http://pear.php.net',
'Net_SMTP' => 'http://pear.php.net/package/Net_SMTP', 'MDB2' => 'http://pear.php.net/package/MDB2',
'Net_SMTP' => 'http://pear.php.net/package/Net_SMTP',
'Mail_mime' => 'http://pear.php.net/package/Mail_mime', 'Mail_mime' => 'http://pear.php.net/package/Mail_mime',
); );

@ -249,18 +249,21 @@ if (isset($_POST['sendmail'])) {
echo '<p>Trying to send email...<br />'; echo '<p>Trying to send email...<br />';
if (preg_match('/^' . $RCI->email_pattern . '$/i', trim($_POST['_from'])) && $from = idn_to_ascii(trim($_POST['_from']));
preg_match('/^' . $RCI->email_pattern . '$/i', trim($_POST['_to']))) { $to = idn_to_ascii(trim($_POST['_to']));
if (preg_match('/^' . $RCI->email_pattern . '$/i', $from) &&
preg_match('/^' . $RCI->email_pattern . '$/i', $to)
) {
$headers = array( $headers = array(
'From' => trim($_POST['_from']), 'From' => $from,
'To' => trim($_POST['_to']), 'To' => $to,
'Subject' => 'Test message from Roundcube', 'Subject' => 'Test message from Roundcube',
); );
$body = 'This is a test to confirm that Roundcube can send email.'; $body = 'This is a test to confirm that Roundcube can send email.';
$smtp_response = array(); $smtp_response = array();
// send mail using configured SMTP server // send mail using configured SMTP server
if ($RCI->getprop('smtp_server')) { if ($RCI->getprop('smtp_server')) {
$CONFIG = $RCI->config; $CONFIG = $RCI->config;
@ -383,9 +386,12 @@ if (isset($_POST['imaptest']) && !empty($_POST['_host']) && !empty($_POST['_user
$imap_host = trim($_POST['_host']); $imap_host = trim($_POST['_host']);
$imap_port = $RCI->getprop('default_port'); $imap_port = $RCI->getprop('default_port');
} }
$imap_host = idn_to_ascii($imap_host);
$imap_user = idn_to_ascii($_POST['_user']);
$imap = new rcube_imap(null); $imap = new rcube_imap(null);
if ($imap->connect($imap_host, $_POST['_user'], $_POST['_pass'], $imap_port, $imap_ssl)) { if ($imap->connect($imap_host, $imap_user, $_POST['_pass'], $imap_port, $imap_ssl)) {
$RCI->pass('IMAP connect', 'SORT capability: ' . ($imap->get_capability('SORT') ? 'yes' : 'no')); $RCI->pass('IMAP connect', 'SORT capability: ' . ($imap->get_capability('SORT') ? 'yes' : 'no'));
$imap->close(); $imap->close();
} }

@ -1764,4 +1764,3 @@ function log_bug($arg_arr)
flush(); flush();
} }
} }

@ -587,7 +587,7 @@ class rcmail
if ($a_host['host']) { if ($a_host['host']) {
$host = $a_host['host']; $host = $a_host['host'];
$imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null; $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null;
if(!empty($a_host['port'])) if (!empty($a_host['port']))
$imap_port = $a_host['port']; $imap_port = $a_host['port'];
else if ($imap_ssl && $imap_ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143)) else if ($imap_ssl && $imap_ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143))
$imap_port = 993; $imap_port = 993;
@ -618,6 +618,12 @@ class rcmail
if (!$this->imap) if (!$this->imap)
$this->imap_init(); $this->imap_init();
// Here we need IDNA ASCII
// Only rcube_contacts class is using domain names in Unicode
$host = idn_to_ascii($host);
if (strpos($username, '@'))
$username = idn_to_ascii($username);
// try IMAP login // try IMAP login
if (!($imap_login = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl))) { if (!($imap_login = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl))) {
// lowercase username if it's an e-mail address (#1484473) // lowercase username if it's an e-mail address (#1484473)

@ -274,10 +274,11 @@ class rcube_config
/** /**
* Return the mail domain configured for the given host * Return the mail domain configured for the given host
* *
* @param string IMAP host * @param string IMAP host
* @param boolean If true, domain name will be converted to IDN ASCII
* @return string Resolved SMTP host * @return string Resolved SMTP host
*/ */
public function mail_domain($host) public function mail_domain($host, $encode=true)
{ {
$domain = $host; $domain = $host;
@ -288,6 +289,9 @@ class rcube_config
else if (!empty($this->prop['mail_domain'])) else if (!empty($this->prop['mail_domain']))
$domain = rcube_parse_host($this->prop['mail_domain']); $domain = rcube_parse_host($this->prop['mail_domain']);
if ($encode)
$domain = idn_to_ascii($domain);
return $domain; return $domain;
} }

@ -3505,7 +3505,7 @@ class rcube_imap
$address = trim($val['address']); $address = trim($val['address']);
$name = trim($val['name']); $name = trim($val['name']);
if (preg_match('/^[\'"]/', $name) && preg_match('/[\'"]$/', $name)) if ($name && preg_match('/^[\'"]/', $name) && preg_match('/[\'"]$/', $name))
$name = trim($name, '\'"'); $name = trim($name, '\'"');
if ($name && $address && $name != $address) if ($name && $address && $name != $address)
@ -3515,7 +3515,8 @@ class rcube_imap
else if ($name) else if ($name)
$string = $name; $string = $name;
$out[$j] = array('name' => $name, $out[$j] = array(
'name' => $name,
'mailto' => $address, 'mailto' => $address,
'string' => $string 'string' => $string
); );
@ -3912,9 +3913,9 @@ class rcube_imap
$result[$key]['name'] .= (empty($result[$key]['name'])?'':' ').str_replace("\"",'',stripslashes($v)); $result[$key]['name'] .= (empty($result[$key]['name'])?'':' ').str_replace("\"",'',stripslashes($v));
} }
if (empty($result[$key]['name'])) // if (empty($result[$key]['name']))
$result[$key]['name'] = $result[$key]['address']; // $result[$key]['name'] = $result[$key]['address'];
elseif (empty($result[$key]['address'])) if (empty($result[$key]['address']))
$result[$key]['address'] = $result[$key]['name']; $result[$key]['address'] = $result[$key]['name'];
} }

@ -99,7 +99,7 @@ class rcube_ldap extends rcube_addressbook
foreach ($this->prop['hosts'] as $host) foreach ($this->prop['hosts'] as $host)
{ {
$host = rcube_parse_host($host); $host = idn_to_ascii(rcube_parse_host($host));
$this->_debug("C: Connect [$host".($this->prop['port'] ? ':'.$this->prop['port'] : '')."]"); $this->_debug("C: Connect [$host".($this->prop['port'] ? ':'.$this->prop['port'] : '')."]");
if ($lc = @ldap_connect($host, $this->prop['port'])) if ($lc = @ldap_connect($host, $this->prop['port']))

@ -680,3 +680,51 @@ if (!extension_loaded('mbstring'))
} }
} }
/**
* intl replacement functions
*/
if (!function_exists('idn_to_utf8'))
{
function idn_to_utf8($domain, $flags=null)
{
static $idn, $loaded;
if (!$loaded) {
$idn = new Net_IDNA2();
$loaded = true;
}
if ($idn && $domain && preg_match('/(^|@|\.)xn--/i', $domain)) {
try {
$domain = $idn->decode($domain);
}
catch (Exception $e) {
}
}
return $domain;
}
}
if (!function_exists('idn_to_ascii'))
{
function idn_to_ascii($domain, $flags=null)
{
static $idn, $loaded;
if (!$loaded) {
$idn = new Net_IDNA2();
$loaded = true;
}
if ($idn && $domain && preg_match('/[^\x20-\x7E]/', $domain)) {
try {
$domain = $idn->encode($domain);
}
catch (Exception $e) {
}
}
return $domain;
}
}

@ -98,6 +98,9 @@ class rcube_smtp
else else
$helo_host = 'localhost'; $helo_host = 'localhost';
// IDNA Support
$smtp_host = idn_to_ascii($smtp_host);
$this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host); $this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host);
if($RCMAIL->config->get('smtp_debug')) if($RCMAIL->config->get('smtp_debug'))
@ -116,10 +119,14 @@ class rcube_smtp
$smtp_user = str_replace('%u', $_SESSION['username'], $CONFIG['smtp_user']); $smtp_user = str_replace('%u', $_SESSION['username'], $CONFIG['smtp_user']);
$smtp_pass = str_replace('%p', $RCMAIL->decrypt($_SESSION['password']), $CONFIG['smtp_pass']); $smtp_pass = str_replace('%p', $RCMAIL->decrypt($_SESSION['password']), $CONFIG['smtp_pass']);
$smtp_auth_type = empty($CONFIG['smtp_auth_type']) ? NULL : $CONFIG['smtp_auth_type']; $smtp_auth_type = empty($CONFIG['smtp_auth_type']) ? NULL : $CONFIG['smtp_auth_type'];
// attempt to authenticate to the SMTP server // attempt to authenticate to the SMTP server
if ($smtp_user && $smtp_pass) if ($smtp_user && $smtp_pass)
{ {
// IDNA Support
if (strpos($smtp_user, '@'))
$smtp_user = idn_to_ascii($smtp_user);
$result = $this->conn->auth($smtp_user, $smtp_pass, $smtp_auth_type, $use_tls); $result = $this->conn->auth($smtp_user, $smtp_pass, $smtp_auth_type, $use_tls);
if (PEAR::isError($result)) if (PEAR::isError($result))

@ -994,15 +994,19 @@ class rcube_template extends rcube_html_page
return $username; return $username;
} }
// Current username is an e-mail address
if (strpos($_SESSION['username'], '@')) {
$username = $_SESSION['username'];
}
// get e-mail address from default identity // get e-mail address from default identity
if ($sql_arr = $this->app->user->get_identity()) { else if ($sql_arr = $this->app->user->get_identity()) {
$username = $sql_arr['email']; $username = $sql_arr['email'];
} }
else { else {
$username = $this->app->user->get_username(); $username = $this->app->user->get_username();
} }
return $username; return idn_to_utf8($username);
} }

@ -44,7 +44,7 @@ class rcube_user
function __construct($id = null, $sql_arr = null) function __construct($id = null, $sql_arr = null)
{ {
$this->db = rcmail::get_instance()->get_dbh(); $this->db = rcmail::get_instance()->get_dbh();
if ($id && !$sql_arr) { if ($id && !$sql_arr) {
$sql_result = $this->db->query( $sql_result = $this->db->query(
"SELECT * FROM ".get_table_name('users')." WHERE user_id = ?", $id); "SELECT * FROM ".get_table_name('users')." WHERE user_id = ?", $id);
@ -121,14 +121,14 @@ class rcube_user
{ {
if (!$this->ID) if (!$this->ID)
return false; return false;
$config = rcmail::get_instance()->config; $config = rcmail::get_instance()->config;
$old_prefs = (array)$this->get_prefs(); $old_prefs = (array)$this->get_prefs();
// merge (partial) prefs array with existing settings // merge (partial) prefs array with existing settings
$save_prefs = $a_user_prefs + $old_prefs; $save_prefs = $a_user_prefs + $old_prefs;
unset($save_prefs['language']); unset($save_prefs['language']);
// don't save prefs with default values if they haven't been changed yet // don't save prefs with default values if they haven't been changed yet
foreach ($a_user_prefs as $key => $value) { foreach ($a_user_prefs as $key => $value) {
if (!isset($old_prefs[$key]) && ($value == $config->get($key))) if (!isset($old_prefs[$key]) && ($value == $config->get($key)))
@ -186,11 +186,11 @@ class rcube_user
($sql_add ? " ".$sql_add : ""). ($sql_add ? " ".$sql_add : "").
" ORDER BY ".$this->db->quoteIdentifier('standard')." DESC, name ASC, identity_id ASC", " ORDER BY ".$this->db->quoteIdentifier('standard')." DESC, name ASC, identity_id ASC",
$this->ID); $this->ID);
while ($sql_arr = $this->db->fetch_assoc($sql_result)) { while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
$result[] = $sql_arr; $result[] = $sql_arr;
} }
return $result; return $result;
} }
@ -208,7 +208,7 @@ class rcube_user
return false; return false;
$query_cols = $query_params = array(); $query_cols = $query_params = array();
foreach ((array)$data as $col => $value) { foreach ((array)$data as $col => $value) {
$query_cols[] = $this->db->quoteIdentifier($col) . ' = ?'; $query_cols[] = $this->db->quoteIdentifier($col) . ' = ?';
$query_params[] = $value; $query_params[] = $value;
@ -224,11 +224,11 @@ class rcube_user
call_user_func_array(array($this->db, 'query'), call_user_func_array(array($this->db, 'query'),
array_merge(array($sql), $query_params)); array_merge(array($sql), $query_params));
return $this->db->affected_rows(); return $this->db->affected_rows();
} }
/** /**
* Create a new identity record linked with this user * Create a new identity record linked with this user
* *
@ -259,8 +259,8 @@ class rcube_user
return $this->db->insert_id('identities'); return $this->db->insert_id('identities');
} }
/** /**
* Mark the given identity as deleted * Mark the given identity as deleted
* *
@ -282,7 +282,7 @@ class rcube_user
// we'll not delete last identity // we'll not delete last identity
if ($sql_arr['ident_count'] <= 1) if ($sql_arr['ident_count'] <= 1)
return false; return false;
$this->db->query( $this->db->query(
"UPDATE ".get_table_name('identities'). "UPDATE ".get_table_name('identities').
" SET del = 1, changed = ".$this->db->now(). " SET del = 1, changed = ".$this->db->now().
@ -293,8 +293,8 @@ class rcube_user
return $this->db->affected_rows(); return $this->db->affected_rows();
} }
/** /**
* Make this identity the default one for this user * Make this identity the default one for this user
* *
@ -313,8 +313,8 @@ class rcube_user
$iid); $iid);
} }
} }
/** /**
* Update user's last_login timestamp * Update user's last_login timestamp
*/ */
@ -328,8 +328,8 @@ class rcube_user
$this->ID); $this->ID);
} }
} }
/** /**
* Clear the saved object state * Clear the saved object state
*/ */
@ -338,8 +338,8 @@ class rcube_user
$this->ID = null; $this->ID = null;
$this->data = null; $this->data = null;
} }
/** /**
* Find a user record matching the given name and host * Find a user record matching the given name and host
* *
@ -350,25 +350,25 @@ class rcube_user
static function query($user, $host) static function query($user, $host)
{ {
$dbh = rcmail::get_instance()->get_dbh(); $dbh = rcmail::get_instance()->get_dbh();
// query for matching user name // query for matching user name
$query = "SELECT * FROM ".get_table_name('users')." WHERE mail_host = ? AND %s = ?"; $query = "SELECT * FROM ".get_table_name('users')." WHERE mail_host = ? AND %s = ?";
$sql_result = $dbh->query(sprintf($query, 'username'), $host, $user); $sql_result = $dbh->query(sprintf($query, 'username'), $host, $user);
// query for matching alias // query for matching alias
if (!($sql_arr = $dbh->fetch_assoc($sql_result))) { if (!($sql_arr = $dbh->fetch_assoc($sql_result))) {
$sql_result = $dbh->query(sprintf($query, 'alias'), $host, $user); $sql_result = $dbh->query(sprintf($query, 'alias'), $host, $user);
$sql_arr = $dbh->fetch_assoc($sql_result); $sql_arr = $dbh->fetch_assoc($sql_result);
} }
// user already registered -> overwrite username // user already registered -> overwrite username
if ($sql_arr) if ($sql_arr)
return new rcube_user($sql_arr['user_id'], $sql_arr); return new rcube_user($sql_arr['user_id'], $sql_arr);
else else
return false; return false;
} }
/** /**
* Create a new user record and return a rcube_user instance * Create a new user record and return a rcube_user instance
* *
@ -448,7 +448,7 @@ class rcube_user
$plugin = $rcmail->plugins->exec_hook('identity_create', $plugin = $rcmail->plugins->exec_hook('identity_create',
array('login' => true, 'record' => $record)); array('login' => true, 'record' => $record));
if (!$plugin['abort'] && $plugin['record']['email']) { if (!$plugin['abort'] && $plugin['record']['email']) {
$rcmail->user->insert_identity($plugin['record']); $rcmail->user->insert_identity($plugin['record']);
} }
@ -463,11 +463,11 @@ class rcube_user
'file' => __FILE__, 'file' => __FILE__,
'message' => "Failed to create new user"), true, false); 'message' => "Failed to create new user"), true, false);
} }
return $user_id ? $user_instance : false; return $user_id ? $user_instance : false;
} }
/** /**
* Resolve username using a virtuser plugins * Resolve username using a virtuser plugins
* *

@ -484,21 +484,26 @@ function rcube_layer(id, attributes)
function rcube_check_email(input, inline) function rcube_check_email(input, inline)
{ {
if (input && window.RegExp) { if (input && window.RegExp) {
var qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'; var qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]',
var dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'; dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]',
var atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'; atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+',
var quoted_pair = '\\x5c[\\x00-\\x7f]'; quoted_pair = '\\x5c[\\x00-\\x7f]',
var domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d'; quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22',
var quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22'; // Use simplified domain matching, because we need to allow Unicode characters here
var sub_domain = '('+atom+'|'+domain_literal+')'; // So, e-mail address should be validated also on server side after idn_to_ascii() use
var word = '('+atom+'|'+quoted_string+')'; sub_domain = '[^@]+',
var domain = sub_domain+'(\\x2e'+sub_domain+')*'; //domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d',
var local_part = word+'(\\x2e'+word+')*'; //sub_domain = '('+atom+'|'+domain_literal+')',
var addr_spec = local_part+'\\x40'+domain; word = '('+atom+'|'+quoted_string+')',
var delim = '[,;\s\n]'; delim = '[,;\s\n]',
var reg1 = inline ? new RegExp('(^|<|'+delim+')'+addr_spec+'($|>|'+delim+')', 'i') : new RegExp('^'+addr_spec+'$', 'i'); domain = sub_domain+'(\\x2e'+sub_domain+')*',
local_part = word+'(\\x2e'+word+')*',
addr_spec = local_part+'\\x40'+domain,
reg1 = inline ? new RegExp('(^|<|'+delim+')'+addr_spec+'($|>|'+delim+')', 'i') : new RegExp('^'+addr_spec+'$', 'i');
return reg1.test(input) ? true : false; return reg1.test(input) ? true : false;
} }
return false; return false;
}; };

File diff suppressed because it is too large Load Diff

@ -0,0 +1,3 @@
<?php
class Net_IDNA2_Exception extends Exception {
}

@ -0,0 +1,5 @@
<?php
require_once 'Net/IDNA2/Exception.php';
class Net_IDNA2_Exception_Nameprep extends Net_IDNA2_Exception {
}

@ -36,7 +36,9 @@ if (!empty($_POST['_address']) && is_object($CONTACTS))
'email' => $contact_arr[1]['mailto'], 'email' => $contact_arr[1]['mailto'],
'name' => $contact_arr[1]['name'] 'name' => $contact_arr[1]['name']
); );
$contact['email'] = idn_to_utf8($contact['email']);
// use email address part for name // use email address part for name
if (empty($contact['name']) || $contact['name'] == $contact['email']) if (empty($contact['name']) || $contact['name'] == $contact['email'])
$contact['name'] = ucfirst(preg_replace('/[\.\-]/', ' ', substr($contact['email'], 0, strpos($contact['email'], '@')))); $contact['name'] = ucfirst(preg_replace('/[\.\-]/', ' ', substr($contact['email'], 0, strpos($contact['email'], '@'))));

@ -227,14 +227,12 @@ function rcmail_compose_headers($attrib)
$fvalue = urldecode($_SESSION['mailto'][$mailto_id]); $fvalue = urldecode($_SESSION['mailto'][$mailto_id]);
case 'cc': case 'cc':
if (!$fname) if (!$fname) {
{
$fname = '_cc'; $fname = '_cc';
$header = $param = 'cc'; $header = $param = 'cc';
} }
case 'bcc': case 'bcc':
if (!$fname) if (!$fname) {
{
$fname = '_bcc'; $fname = '_bcc';
$header = $param = 'bcc'; $header = $param = 'bcc';
} }
@ -251,7 +249,7 @@ function rcmail_compose_headers($attrib)
$field_type = 'html_inputfield'; $field_type = 'html_inputfield';
break; break;
} }
if ($fname && !empty($_POST[$fname])) { if ($fname && !empty($_POST[$fname])) {
$fvalue = get_input_value($fname, RCUBE_INPUT_POST, TRUE); $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 // get recipent address(es) out of the message headers
if ($header=='to' && !empty($MESSAGE->headers->replyto)) if ($header=='to' && !empty($MESSAGE->headers->replyto))
$fvalue = $MESSAGE->headers->replyto; $fvalue = $MESSAGE->headers->replyto;
else if ($header=='to' && !empty($MESSAGE->headers->from)) else if ($header=='to' && !empty($MESSAGE->headers->from))
$fvalue = $MESSAGE->headers->from; $fvalue = $MESSAGE->headers->from;
// add recipent of original message if reply to all // 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) if ($v = $MESSAGE->headers->to)
$fvalue .= $v; $fvalue .= $v;
@ -277,39 +272,58 @@ function rcmail_compose_headers($attrib)
} }
// split recipients and put them back together in a unique way // split recipients and put them back together in a unique way
if (!empty($fvalue)) if (!empty($fvalue)) {
{
$to_addresses = $IMAP->decode_address_list($fvalue); $to_addresses = $IMAP->decode_address_list($fvalue);
$fvalue = ''; $fvalue = '';
foreach ($to_addresses as $addr_part) foreach ($to_addresses as $addr_part) {
{ if (empty($addr_part['mailto']))
if (!empty($addr_part['mailto']) continue;
&& !in_array($addr_part['mailto'], $sa_recipients)
$mailto = idn_to_utf8($addr_part['mailto']);
if (!in_array($mailto, $sa_recipients)
&& (!$MESSAGE->compose_from && (!$MESSAGE->compose_from
|| !in_array_nocase($addr_part['mailto'], $MESSAGE->compose_from) || !in_array_nocase($mailto, $MESSAGE->compose_from)
|| (count($to_addresses)==1 && $header=='to'))) // allow reply to yourself || (count($to_addresses)==1 && $header=='to')) // allow reply to yourself
{ ) {
$fvalue .= (strlen($fvalue) ? ', ':'').$addr_part['string']; 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']; $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 // get drafted headers
if ($header=='to' && !empty($MESSAGE->headers->to)) if ($header=='to' && !empty($MESSAGE->headers->to))
$fvalue = $MESSAGE->get_header('to'); $fvalue = $MESSAGE->get_header('to');
else if ($header=='cc' && !empty($MESSAGE->headers->cc))
if ($header=='cc' && !empty($MESSAGE->headers->cc))
$fvalue = $MESSAGE->get_header('cc'); $fvalue = $MESSAGE->get_header('cc');
else if ($header=='bcc' && !empty($MESSAGE->headers->bcc))
if ($header=='bcc' && !empty($MESSAGE->headers->bcc))
$fvalue = $MESSAGE->get_header('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) if ($fname && $field_type)
{ {
// pass the following attributes to the form class // pass the following attributes to the form class
@ -326,7 +340,7 @@ function rcmail_compose_headers($attrib)
if ($form_start) if ($form_start)
$out = $form_start.$out; $out = $form_start.$out;
return $out; return $out;
} }
@ -350,7 +364,7 @@ function rcmail_compose_header_from($attrib)
foreach ($a_to as $addr) foreach ($a_to as $addr)
{ {
if (!empty($addr['mailto'])) if (!empty($addr['mailto']))
$a_recipients[] = mb_strtolower($addr['mailto']); $a_recipients[] = mb_strtolower(idn_to_utf8($addr['mailto']));
} }
if (!empty($MESSAGE->headers->cc)) if (!empty($MESSAGE->headers->cc))
@ -359,7 +373,7 @@ function rcmail_compose_header_from($attrib)
foreach ($a_cc as $addr) foreach ($a_cc as $addr)
{ {
if (!empty($addr['mailto'])) 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) foreach ($user_identities as $sql_arr)
{ {
$sql_arr['email'] = mb_strtolower(idn_to_utf8($sql_arr['email']));
$identity_id = $sql_arr['identity_id']; $identity_id = $sql_arr['identity_id'];
$select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $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'])) if ($compose_mode == RCUBE_COMPOSE_DRAFT && strstr($MESSAGE->headers->from, $sql_arr['email']))
$from_id = $sql_arr['identity_id']; $from_id = $sql_arr['identity_id'];
// set identity if it's one of the reply-message recipients (with prio for default identity) // 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']; $from_id = $sql_arr['identity_id'];
} }
} }
@ -925,7 +940,7 @@ function rcmail_compose_subject($attrib)
$out = $form_start ? "$form_start\n" : ''; $out = $form_start ? "$form_start\n" : '';
$out .= $textfield->show($subject); $out .= $textfield->show($subject);
$out .= $form_end ? "\n$form_end" : ''; $out .= $form_end ? "\n$form_end" : '';
return $out; return $out;
} }

@ -24,7 +24,9 @@ $SENT_MBOX = $RCMAIL->config->get('sent_mbox');
$DRAFTS_MBOX = $RCMAIL->config->get('drafts_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)); $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 // actions that do not require imap connection here
$NOIMAP_ACTIONS = array('addcontact', 'autocomplete', 'upload', 'display-attachment', 'remove-attachment', 'get'); $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) 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; static $got_writable_abook = null;
$a_parts = $IMAP->decode_address_list($input); $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) { foreach ($a_parts as $part) {
$j++; $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) { if ($PRINT_MODE) {
$out .= sprintf('%s &lt;%s&gt;', Q($part['name']), $part['mailto']); $out .= sprintf('%s &lt;%s&gt;', Q($name), $mailto);
} }
else if (check_email($part['mailto'], false)) { else if (check_email($part['mailto'], false)) {
if ($linked) { if ($linked) {
$out .= html::a(array( $out .= html::a(array(
'href' => 'mailto:'.$part['mailto'], 'href' => 'mailto:'.$mailto,
'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($part['mailto'])), 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)),
'title' => $part['mailto'], 'title' => $mailto,
'class' => "rcmContactAddress", 'class' => "rcmContactAddress",
), ),
Q($part['name'])); Q($name ? $name : $mailto));
} }
else { 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) { if ($addicon && $got_writable_abook) {
$out .= '&nbsp;' . html::a(array( $out .= '&nbsp;' . html::a(array(
'href' => "#add", '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'), 'title' => rcube_label('addtoaddressbook'),
), ),
html::img(array( html::img(array(
@ -1289,10 +1304,10 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null)
} }
} }
else { else {
if ($part['name']) if ($name)
$out .= Q($part['name']); $out .= Q($name);
if ($part['mailto']) if ($mailto)
$out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($part['mailto'])); $out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($mailto));
} }
if ($c>$j) if ($c>$j)
@ -1375,7 +1390,7 @@ function rcmail_draftinfo_decode($str)
function rcmail_message_part_controls() function rcmail_message_part_controls()
{ {
global $MESSAGE; global $MESSAGE;
$part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC)); $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC));
@ -1397,12 +1412,12 @@ function rcmail_message_part_controls()
} }
return $table->show($attrib); return $table->show($attrib);
} }
function rcmail_message_part_frame($attrib) function rcmail_message_part_frame($attrib)
{ {
global $MESSAGE; global $MESSAGE;
$part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))]; $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']); $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_show=' : '_preload='), $_SERVER['QUERY_STRING']);
return html::iframe($attrib); return html::iframe($attrib);
} }
/** /**
* clear message composing settings * clear message composing settings
*/ */
function rcmail_compose_cleanup() function rcmail_compose_cleanup()
{ {
if (!isset($_SESSION['compose'])) if (!isset($_SESSION['compose']))
return; return;
$rcmail = rcmail::get_instance(); $rcmail = rcmail::get_instance();
$rcmail->plugins->exec_hook('attachments_cleanup', array()); $rcmail->plugins->exec_hook('attachments_cleanup', array());
$rcmail->session->remove('compose'); $rcmail->session->remove('compose');
} }
/** /**

@ -60,8 +60,7 @@ if (!$savedraft) {
function rcmail_encrypt_header($what) function rcmail_encrypt_header($what)
{ {
global $CONFIG, $RCMAIL; global $CONFIG, $RCMAIL;
if (!$CONFIG['http_received_header_encrypt']) if (!$CONFIG['http_received_header_encrypt']) {
{
return $what; return $what;
} }
return $RCMAIL->encrypt($what); return $RCMAIL->encrypt($what);
@ -69,30 +68,21 @@ function rcmail_encrypt_header($what)
// get identity record // get identity record
function rcmail_get_identity($id) function rcmail_get_identity($id)
{ {
global $USER, $OUTPUT; global $USER, $OUTPUT;
if ($sql_arr = $USER->get_identity($id)) if ($sql_arr = $USER->get_identity($id)) {
{
$out = $sql_arr; $out = $sql_arr;
$out['mailto'] = $sql_arr['email']; $out['mailto'] = $sql_arr['email'];
$out['string'] = format_email_recipient($sql_arr['email'],
// Special chars as defined by RFC 822 need to in quoted string (or escaped). rcube_charset_convert($sql_arr['name'], RCMAIL_CHARSET, $OUTPUT->get_charset()));
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'] . '>';
return $out; return $out;
}
return FALSE;
} }
return FALSE;
}
/** /**
* go from this: * go from this:
* <img src="http[s]://.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" /> * <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) // 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; global $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
@ -163,9 +153,11 @@ function rcmail_email_input_format($mailto, $count=false)
$item = trim($item); $item = trim($item);
// address in brackets without name (do nothing) // address in brackets without name (do nothing)
if (preg_match('/^<\S+@\S+>$/', $item)) { if (preg_match('/^<\S+@\S+>$/', $item)) {
$item = idn_to_ascii($item);
$result[] = $item; $result[] = $item;
// address without brackets and without name (add brackets) // address without brackets and without name (add brackets)
} else if (preg_match('/^\S+@\S+$/', $item)) { } else if (preg_match('/^\S+@\S+$/', $item)) {
$item = idn_to_ascii($item);
$result[] = '<'.$item.'>'; $result[] = '<'.$item.'>';
// address with name (handle name) // address with name (handle name)
} else if (preg_match('/\S+@\S+>*$/', $item, $matches)) { } else if (preg_match('/\S+@\S+>*$/', $item, $matches)) {
@ -176,6 +168,7 @@ function rcmail_email_input_format($mailto, $count=false)
&& preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) { && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) {
$name = '"'.addcslashes($name, '"').'"'; $name = '"'.addcslashes($name, '"').'"';
} }
$address = idn_to_ascii($address);
if (!preg_match('/^<\S+@\S+>$/', $address)) if (!preg_match('/^<\S+@\S+>$/', $address))
$address = '<'.$address.'>'; $address = '<'.$address.'>';
@ -187,7 +180,7 @@ function rcmail_email_input_format($mailto, $count=false)
// check address format // check address format
$item = trim($item, '<>'); $item = trim($item, '<>');
if ($item && !check_email($item)) { if ($item && $check && !check_email($item)) {
$EMAIL_FORMAT_ERROR = $item; $EMAIL_FORMAT_ERROR = $item;
return; return;
} }
@ -297,7 +290,7 @@ if (!empty($mailcc))
if (!empty($mailbcc)) if (!empty($mailbcc))
$headers['Bcc'] = $mailbcc; $headers['Bcc'] = $mailbcc;
if (!empty($identity_arr['bcc'])) { if (!empty($identity_arr['bcc'])) {
$headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc']; $headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc'];
$RECIPIENT_COUNT ++; $RECIPIENT_COUNT ++;
@ -319,11 +312,11 @@ if (!empty($identity_arr['organization']))
if (!empty($_POST['_replyto'])) if (!empty($_POST['_replyto']))
$headers['Reply-To'] = rcmail_email_input_format(get_input_value('_replyto', RCUBE_INPUT_POST, TRUE, $message_charset)); $headers['Reply-To'] = rcmail_email_input_format(get_input_value('_replyto', RCUBE_INPUT_POST, TRUE, $message_charset));
else if (!empty($identity_arr['reply-to'])) 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'])) if (!empty($_SESSION['compose']['reply_msgid']))
$headers['In-Reply-To'] = $_SESSION['compose']['reply_msgid']; $headers['In-Reply-To'] = $_SESSION['compose']['reply_msgid'];
// remember reply/forward UIDs in special headers // remember reply/forward UIDs in special headers
if (!empty($_SESSION['compose']['reply_uid']) && $savedraft) if (!empty($_SESSION['compose']['reply_uid']) && $savedraft)
$headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $_SESSION['compose']['reply_uid']); $headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $_SESSION['compose']['reply_uid']);

@ -94,6 +94,10 @@ function rcube_identity_form($attrib)
$form['adressing']['content']['email']['class'] = 'disabled'; $form['adressing']['content']['email']['class'] = 'disabled';
} }
$IDENTITY_RECORD['email'] = idn_to_utf8($IDENTITY_RECORD['email']);
$IDENTITY_RECORD['reply-to'] = idn_to_utf8($IDENTITY_RECORD['reply-to']);
$IDENTITY_RECORD['bcc'] = idn_to_utf8($IDENTITY_RECORD['bcc']);
// Allow plugins to modify identity form content // Allow plugins to modify identity form content
$plugin = $RCMAIL->plugins->exec_hook('identity_form', array( $plugin = $RCMAIL->plugins->exec_hook('identity_form', array(
'form' => $form, 'record' => $IDENTITY_RECORD)); 'form' => $form, 'record' => $IDENTITY_RECORD));

@ -72,7 +72,7 @@ function rcmail_identities_list($attrib)
// get identities list and define 'mail' column // get identities list and define 'mail' column
$list = $USER->list_identities(); $list = $USER->list_identities();
foreach ($list as $idx => $row) foreach ($list as $idx => $row)
$list[$idx]['mail'] = trim($row['name'] . ' <' . $row['email'] .'>'); $list[$idx]['mail'] = trim($row['name'] . ' <' . idn_to_utf8($row['email']) .'>');
// get all identites from DB and define list of cols to be displayed // get all identites from DB and define list of cols to be displayed
$plugin = $RCMAIL->plugins->exec_hook('identities_list', array( $plugin = $RCMAIL->plugins->exec_hook('identities_list', array(

@ -56,6 +56,18 @@ foreach ($a_boolean_cols as $col)
if (IDENTITIES_LEVEL == 1 || IDENTITIES_LEVEL == 3) if (IDENTITIES_LEVEL == 1 || IDENTITIES_LEVEL == 3)
unset($save_data['email']); unset($save_data['email']);
// Validate e-mail addresses
foreach (array('email', 'reply-to', 'bcc') as $item) {
if ($email = $save_data[$item]) {
$ascii_email = idn_to_ascii($email);
if (!check_email($ascii_email, false)) {
// show error message
$OUTPUT->show_message('emailformaterror', 'error', array('email' => $email), false);
rcmail_overwrite_action('edit-identity');
return;
}
}
}
// update an existing contact // update an existing contact
if ($_POST['_iid']) if ($_POST['_iid'])
@ -64,6 +76,13 @@ if ($_POST['_iid'])
$plugin = $RCMAIL->plugins->exec_hook('identity_update', array('id' => $iid, 'record' => $save_data)); $plugin = $RCMAIL->plugins->exec_hook('identity_update', array('id' => $iid, 'record' => $save_data));
$save_data = $plugin['record']; $save_data = $plugin['record'];
if ($save_data['email'])
$save_data['email'] = idn_to_ascii($save_data['email']);
if ($save_data['bcc'])
$save_data['bcc'] = idn_to_ascii($save_data['bcc']);
if ($save_data['reply-to'])
$save_data['reply-to'] = idn_to_ascii($save_data['reply-to']);
if (!$plugin['abort'] && ($updated = $USER->update_identity($iid, $save_data))) if (!$plugin['abort'] && ($updated = $USER->update_identity($iid, $save_data)))
{ {
$OUTPUT->show_message('successfullysaved', 'confirmation'); $OUTPUT->show_message('successfullysaved', 'confirmation');
@ -74,7 +93,7 @@ if ($_POST['_iid'])
if ($_POST['_framed']) if ($_POST['_framed'])
{ {
// update the changed col in list // update the changed col in list
// ... // ...
} }
} }
else if ($plugin['abort'] || $DB->is_error()) else if ($plugin['abort'] || $DB->is_error())
@ -95,6 +114,10 @@ else if (IDENTITIES_LEVEL < 2)
$plugin = $RCMAIL->plugins->exec_hook('identity_create', array('record' => $save_data)); $plugin = $RCMAIL->plugins->exec_hook('identity_create', array('record' => $save_data));
$save_data = $plugin['record']; $save_data = $plugin['record'];
$save_data['email'] = idn_to_ascii($save_data['email']);
$save_data['bcc'] = idn_to_ascii($save_data['bcc']);
$save_data['reply-to'] = idn_to_ascii($save_data['reply-to']);
if (!$plugin['abort'] && $save_data['email'] && ($insert_id = $USER->insert_identity($save_data))) if (!$plugin['abort'] && $save_data['email'] && ($insert_id = $USER->insert_identity($save_data)))
{ {
$OUTPUT->show_message('successfullysaved', 'confirmation', null, false); $OUTPUT->show_message('successfullysaved', 'confirmation', null, false);

Loading…
Cancel
Save