alecpl
2009-10-14 e4acbbd8cc02b960bd5240538016b2c69c33d6bd
- Added server-side e-mail address validation with 'email_dns_check' option (#1485857)


7 files modified
80 ■■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
config/main.inc.php.dist 3 ●●●●● patch | view | raw | blame | history
plugins/managesieve/managesieve.php 3 ●●●●● patch | view | raw | blame | history
program/include/main.inc 52 ●●●●● patch | view | raw | blame | history
program/localization/en_US/messages.inc 1 ●●●● patch | view | raw | blame | history
program/localization/pl_PL/messages.inc 1 ●●●● patch | view | raw | blame | history
program/steps/mail/sendmail.inc 19 ●●●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG RoundCube Webmail
===========================
- Added server-side e-mail address validation with 'email_dns_check' option (#1485857)
- Fix login page loading into an iframe when session expires (#1485952)
- added option 'force_https_port' in 'force_https' plugin (#1486091)
- Option 'force_https' replaced by 'force_https' plugin
config/main.inc.php.dist
@@ -364,6 +364,9 @@
// Must be less than 'session_lifetime'
$rcmail_config['min_keep_alive'] = 60;
// Enable DNS checking for e-mail address validation
$rcmail_config['email_dns_check'] = false;
/***** these settings can be overwritten by user's preferences *****/
// skin name: folder from skins/
plugins/managesieve/managesieve.php
@@ -818,6 +818,9 @@
  private function check_email($email)
  {
    if (function_exists('check_email'));
      return check_email($email);
    // Check for invalid characters
    if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $email))
      return false;
program/include/main.inc
@@ -1401,6 +1401,58 @@
/**
 * E-mail address validation
 */
function check_email($email)
{
  // Check for invalid characters
  if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $email))
    return false;
  // Check that there's one @ symbol, and that the lengths are right
  if (!preg_match('/^([^@]{1,64})@([^@]{1,255})$/', $email, $email_array))
    return false;
  // Check local part
  $local_array = explode('.', $email_array[1]);
  foreach ($local_array as $local_part)
    if (!preg_match('/^(([A-Za-z0-9!#$%&\'*+\/=?^_`{|}~-]+)|("[^"]+"))$/', $local_part))
      return false;
  // Check domain part
  if (preg_match('/^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}$/', $email_array[2])
      || preg_match('/^\[(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\]$/', $email_array[2]))
    return true; // If an IP address
  else {
    // If not an IP address
    $domain_array = explode('.', $email_array[2]);
    if (sizeof($domain_array) < 2)
      return false; // Not enough parts to be a valid domain
    foreach ($domain_array as $domain_part)
      if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]))$/', $domain_part))
        return false;
    if (!rcmail::get_instance()->config->get('email_dns_check'))
      return true;
    if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && version_compare(PHP_VERSION, '5.3.0', '<'))
      return true;
    // find MX record(s)
    if (getmxrr($email_array[2], $mx_records))
      return true;
    // find any DNS record
    if (checkdnsrr($email_array[2], 'ANY'))
      return true;
  }
  return false;
}
/**
 * Helper class to turn relative urls into absolute ones
 * using a predefined base
 */
program/localization/en_US/messages.inc
@@ -106,5 +106,6 @@
$messages['smtptoerror'] = 'SMTP Error ($code): Failed to add recipient "$to"';
$messages['smtprecipientserror'] = 'SMTP Error: Unable to parse recipients list';
$messages['smtperror'] = 'SMTP Error: $msg';
$messages['emailformaterror'] = 'Incorrect e-mail address: $email';
?>
program/localization/pl_PL/messages.inc
@@ -110,5 +110,6 @@
$messages['smtprecipientserror'] = 'Błąd SMTP: Parsowanie listy odbiorców nie powiodło się';
$messages['smtperror'] = 'Błąd SMTP: $msg';
$messages['invalidrequest'] = 'Błędne żądanie! Nie zapisano danych.';
$messages['emailformaterror'] = 'Błędny adres e-mail: $email';
?>
program/steps/mail/sendmail.inc
@@ -151,6 +151,8 @@
// parse email address input
function rcmail_email_input_format($mailto)
{
  global $EMAIL_FORMAT_ERROR;
  $regexp = array('/[,;]\s*[\r\n]+/', '/[\r\n]+/', '/[,;]\s*$/m', '/;/', '/(\S{1})(<\S+@\S+>)/U');
  $replace = array(', ', ', ', '', ',', '\\1 \\2');
@@ -181,8 +183,16 @@
        $address = '<'.$address.'>';
      $result[] = $name.' '.$address;
      $item = $address;
    } else if (trim($item)) {
      // @TODO: handle errors
      continue;
    }
    // check address format
    $item = trim($item, '<>');
    if ($item && !check_email($item)) {
      $EMAIL_FORMAT_ERROR = $item;
      return;
    }
  }
@@ -200,10 +210,17 @@
$input_charset = $OUTPUT->get_charset();
$message_charset = isset($_POST['_charset']) ? $_POST['_charset'] : $input_charset;
$EMAIL_FORMAT_ERROR = NULL;
$mailto = rcmail_email_input_format(get_input_value('_to', RCUBE_INPUT_POST, TRUE, $message_charset));
$mailcc = rcmail_email_input_format(get_input_value('_cc', RCUBE_INPUT_POST, TRUE, $message_charset));
$mailbcc = rcmail_email_input_format(get_input_value('_bcc', RCUBE_INPUT_POST, TRUE, $message_charset));
if ($EMAIL_FORMAT_ERROR) {
  $OUTPUT->show_message('emailformaterror', 'error', array('email' => $EMAIL_FORMAT_ERROR));
  $OUTPUT->send('iframe');
}
if (empty($mailto) && !empty($mailcc)) {
  $mailto = $mailcc;
  $mailcc = null;