From 35992da52adbf0876d43b2729cd52ac6e58f683c Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Mon, 11 May 2015 09:59:15 -0500
Subject: [PATCH] validator: Verify MX record of email addresses

This allows detection of some incorrectly-typed email addresses before
tickets, users, and agents are created.
---
 include/class.forms.php     |  2 +-
 include/class.staff.php     |  2 +-
 include/class.validator.php | 10 +++++++++-
 scp/banlist.php             |  4 ++--
 scp/emailtest.php           |  4 ++--
 setup/install.php           |  2 +-
 6 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/include/class.forms.php b/include/class.forms.php
index 0249de4d8..b535d4739 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -718,7 +718,7 @@ class TextboxField extends FormField {
         $config = $this->getConfiguration();
         $validators = array(
             '' =>       null,
-            'email' =>  array(array('Validator', 'is_email'),
+            'email' =>  array(array('Validator', 'is_valid_email'),
                 __('Enter a valid email address')),
             'phone' =>  array(array('Validator', 'is_phone'),
                 __('Enter a valid phone number')),
diff --git a/include/class.staff.php b/include/class.staff.php
index e0525e63d..94b18b726 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -454,7 +454,7 @@ implements EmailContact {
         if(!$vars['lastname'])
             $errors['lastname']=__('Last name is required');
 
-        if(!$vars['email'] || !Validator::is_email($vars['email']))
+        if(!$vars['email'] || !Validator::is_valid_email($vars['email']))
             $errors['email']=__('Valid email is required');
         elseif(Email::getIdByEmail($vars['email']))
             $errors['email']=__('Already in-use as system email');
diff --git a/include/class.validator.php b/include/class.validator.php
index c14f91074..fcb350126 100644
--- a/include/class.validator.php
+++ b/include/class.validator.php
@@ -140,7 +140,7 @@ class Validator {
 
     /*** Functions below can be called directly without class instance.
          Validator::func(var..);  (nolint) ***/
-    function is_email($email, $list=false) {
+    function is_email($email, $list=false, $verify=false) {
         require_once PEAR_DIR . 'Mail/RFC822.php';
         require_once PEAR_DIR . 'PEAR.php';
         if (!($mails = Mail_RFC822::parseAddressList($email)) || PEAR::isError($mails))
@@ -156,8 +156,16 @@ class Validator {
                 return false;
         }
 
+        if ($verify && !checkdnsrr($m->host, 'MX'))
+            return false;
+
         return true;
     }
+
+    function is_valid_email($email) {
+        return self::is_email($email, false, true);
+    }
+
     function is_phone($phone) {
         /* We're not really validating the phone number but just making sure it doesn't contain illegal chars and of acceptable len */
         $stripped=preg_replace("(\(|\)|\-|\.|\+|[  ]+)","",$phone);
diff --git a/scp/banlist.php b/scp/banlist.php
index bbebfa4b7..d3bb78af8 100644
--- a/scp/banlist.php
+++ b/scp/banlist.php
@@ -33,7 +33,7 @@ if($_POST && !$errors && $filter){
         case 'update':
             if(!$rule){
                 $errors['err']=sprintf(__('%s: Unknown or invalid'), __('ban rule'));
-            }elseif(!$_POST['val'] || !Validator::is_email($_POST['val'])){
+            }elseif(!$_POST['val'] || !Validator::is_valid_email($_POST['val'])){
                 $errors['err']=$errors['val']=__('Valid email address required');
             }elseif(!$errors){
                 $vars=array('what'=>'email',
@@ -52,7 +52,7 @@ if($_POST && !$errors && $filter){
         case 'add':
             if(!$filter) {
                 $errors['err']=sprintf(__('%s: Unknown or invalid'), __('ban list'));
-            }elseif(!$_POST['val'] || !Validator::is_email($_POST['val'])) {
+            }elseif(!$_POST['val'] || !Validator::is_valid_email($_POST['val'])) {
                 $errors['err']=$errors['val']=__('Valid email address required');
             }elseif(BanList::includes(trim($_POST['val']))) {
                 $errors['err']=$errors['val']=__('Email already in the ban list');
diff --git a/scp/emailtest.php b/scp/emailtest.php
index c714ef1d0..1752bf739 100644
--- a/scp/emailtest.php
+++ b/scp/emailtest.php
@@ -25,8 +25,8 @@ if($_POST){
     if(!$_POST['email_id'] || !($email=Email::lookup($_POST['email_id'])))
         $errors['email_id']=__('Select from email address');
 
-    if(!$_POST['email'] || !Validator::is_email($_POST['email']))
-        $errors['email']=__('To email address required');
+    if(!$_POST['email'] || !Validator::is_valid_email($_POST['email']))
+        $errors['email']=__('Valid recipient email address required');
 
     if(!$_POST['subj'])
         $errors['subj']=__('Subject required');
diff --git a/setup/install.php b/setup/install.php
index 4a348cf63..1420f2dfa 100644
--- a/setup/install.php
+++ b/setup/install.php
@@ -65,7 +65,7 @@ if($_POST && $_POST['s']) {
 
             if(!$_POST['email'])
                 $errors['email'] = __('Required');
-            elseif(!Validator::is_email($_POST['email']))
+            elseif(!Validator::is_valid_email($_POST['email']))
                 $errors['email'] = __('Invalid');
 
             if(!$_POST['alerts'] && !$_POST['news'])
-- 
GitLab