summaryrefslogtreecommitdiff
path: root/program
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2009-10-14 10:52:27 +0000
committeralecpl <alec@alec.pl>2009-10-14 10:52:27 +0000
commite4acbbd8cc02b960bd5240538016b2c69c33d6bd (patch)
treed24c4b6dc5687287e71d6673be9ff2281b4161ea /program
parentb5713396f1bfd135b457bcad9cceb20f48ba23c7 (diff)
- Added server-side e-mail address validation with 'email_dns_check' option (#1485857)
Diffstat (limited to 'program')
-rw-r--r--program/include/main.inc52
-rw-r--r--program/localization/en_US/messages.inc1
-rw-r--r--program/localization/pl_PL/messages.inc1
-rw-r--r--program/steps/mail/sendmail.inc19
4 files changed, 72 insertions, 1 deletions
diff --git a/program/include/main.inc b/program/include/main.inc
index e96840003..06d7780d1 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -1401,6 +1401,58 @@ function rcube_html_editor($mode='')
/**
+ * 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
*/
diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc
index 6fc7be862..b0a812ce7 100644
--- a/program/localization/en_US/messages.inc
+++ b/program/localization/en_US/messages.inc
@@ -106,5 +106,6 @@ $messages['smtpfromerror'] = 'SMTP Error ($code): Failed to set sender "$from"';
$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';
?>
diff --git a/program/localization/pl_PL/messages.inc b/program/localization/pl_PL/messages.inc
index 69b9b4285..1fc765982 100644
--- a/program/localization/pl_PL/messages.inc
+++ b/program/localization/pl_PL/messages.inc
@@ -110,5 +110,6 @@ $messages['smtptoerror'] = 'Błąd SMTP ($code): Nie można dodać odbiorcy "$to
$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';
?>
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index e8ef47a55..e8445aa4c 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -151,6 +151,8 @@ function rcmail_attach_emoticons(&$mime_message)
// 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 @@ function rcmail_email_input_format($mailto)
$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 @@ $message_id = sprintf('<%s@%s>', md5(uniqid('rcmail'.mt_rand(),true)), $RCMAIL->
$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;