Follow us on Twitter X-Cart on Facebook Wiki
Shopping cart software Solutions for online shops and malls

Improved Email Address Validation

 
Reply
   X-Cart forums > X-Cart 4 > Dev Questions
 
Thread Tools Search this Thread
  #1  
Old 11-23-2011, 08:00 AM
 
exsecror exsecror is offline
 

X-Wizard
  
Join Date: Apr 2007
Posts: 1,284
 

Default Improved Email Address Validation

Probably one of the most important aspects of doing business online is the ability to ensure that a customer is kept well informed about the status of their order, whether that status may be that it shipped or it had to be backordered or that a credit card payment (for those that capture payment during shipment and not at time of sale) did not go through.

The issue that can arise however (and we experience this frequently) is the customer will often purposefully provide a fake email address or one with a disposable email service or even by accident provide an email address that is invalid due to typographical errors or the mailbox may be full. In order to combat this issue we re-wrote the func_check_email() procedure that comes with X-Cart to further enhance it's abilities. The reason for this is that the procedure only checks for syntax validity, not existence or validity of the mailbox itself.

MODIFICATION REQUIREMENTS:MODIFICATION RECOMMENDATIONS:
  • PHP filter Extension (if not present, will use X-Cart fallback)
NOTICE:

This modification is provided as-is with no guarantee or warranty. It is intended for advanced users only as patches are not provided and does not include an admin interface. It is assumed that any manual additions to the filter table will be done through a direct SQL console interface such as the MySQL Workbench, phpMyAdmin, PremiumSoft Navicat MySQL or MySQL CLI.

================================================== ======

STEP 1: The Email Validation SQL Table

The first step is to add the SQL table that will be referenced by the functions func_check_email() and func_check_email_towerdata(). This is mainly intended as both a caching assistant and to handle permanently blacklisted usernames and domain names (as well as bad MX records).

Code:
DROP TABLE IF EXISTS `filter_email_validation`; CREATE TABLE `filter_email_validation` ( `filter_value` varchar(255) NOT NULL, `filter_type` enum('D','M','L') NOT NULL, `filter_permanent` tinyint(4) NOT NULL, `filter_expires` int(11) NOT NULL, PRIMARY KEY (`filter_value`) )
The table supports 3 types of records:

L - localpart or username
D - domain name
M - MX record (for people that use bad or fake MX records like mx.fakemx.net)

There's also a field called filter_permanent which denotes 0 (false) or 1 (true) that the filter is a permanent one and should not be purged during frequent checks against the filter_expires field. Once you have that table created proceed to step 2.

================================================== ======

STEP 2: Modification of func_check_email()

Now that we have the SQL table necessary to make this work created, it is time to re-write the func_check_email() function.

Locate the function func_check_email() and replace the entire contents with the following:

include/func/func.mail.php:

PHP Code:
// {{{ func_check_email()
/**
 * This function checks if an email is valid
 * 
 * @param string $email the email address to check
 * @return bool true if valid; false if not
 */
function func_check_email($email) {
    @
db_query('DELETE FROM filter_email_validation WHERE filter_expires < UNIX_TIMESTAMP() AND filter_permanent = 0');
    
    
$email                    trim(strtolower(stripslashes($email)));
    
$filters                  func_query('SELECT filter_type, filter_value FROM filter_email_validation');
    
$email_regular_expression func_email_validation_regexp();

    list(
$localpart$domain) = split('@'$email);
    @
getmxrr($domain$mx_results);
    
    if (
count($mx_results) === 0) {
        return 
false;
    }
     
    if (
extension_loaded('filter')) {
        if (!
filter_var(filter_var($emailFILTER_SANITIZE_EMAIL), FILTER_VALIDATE_EMAIL)) {
            return 
false;
        }
    }
    else {
        if (!
preg_match('/' $email_regular_expression '/Di'$email)) {
            return 
false;
        }
    }
    
    foreach (
$filters as $filter) {
        switch (
$filter['filter_type']) {
            case 
'D':
                if (
$domain === $filter['filter_value']) {
                    return 
false;
                }
                break;
            case 
'L':
                if (
$localpart === $filter['filter_value']) {
                    return 
false;
                } 
                break;
            case 
'M':
                if (
array_search($filter['filter_value'], $mx_results) !== false) {
                    return 
false;
                }
                break;
            default:
                break;
        }
    }
    
    if (!
func_check_email_towerdata($email)) {
        return 
false;
    }
    
    return 
true;
}
// }}} 
As you can see this is a much more extension function than the original on provided. It checks for the existence of MX records, runs through the filter_email_validation table to ensure nothing matches and then will make an external call to the TowerData validation service via another function (which will be provided in Step 3). Once you have completely re-written the function, proceed to Step 3.
Reply With Quote

The following user thanks exsecror for this useful post:
am2003 (11-23-2011)
  #2  
Old 11-23-2011, 08:06 AM
 
exsecror exsecror is offline
 

X-Wizard
  
Join Date: Apr 2007
Posts: 1,284
 

Default Re: Improved Email Address Validation

STEP 3: The creation of func_check_email_towerdata()

Now that you have finished modifying func_check_email() it is time to create the func_check_email_towerdata() function which will use TowerData's Email Validation Service (http://www.towerdata.com/services/web/email_validation.html) to validate the email address further.

NOTE: You must have an account with TowerData for this to work and you must have the SOAP extension and PHP 5.2 or greater. Without any of these conditions met (they are not checked) you will break the entire func_check_email() function which breaks anything dependent on it.

include/func/func.mail.php:
PHP Code:
// {{{ func_check_email_towerdata()
/**
 * This function runs further checks to see if an email 
 * is valid
 * 
 * @param string $email the email address to check
 * @return bool true if valid; false if not
 */
function func_check_email_towerdata($email) {    
    
$default_timeout ini_get('default_socket_timeout');
    list(
$localpart$domain) = split('@'$email);
    
    @
ini_set('default_socket_timeout'3);
        
    try {
        
$client = new SoapClient('http://soap.towerdata.com/validate.wsdl',
                                 array(
'trace'              => 0,
                                       
'connection_timeout' => 3));
                                 
        
$params = array('login'                  => 'YOUR TOWERDATA USERNAME',
                        
'password'               => 'YOUR TOWERDATA PASSWORD',
                        
'version'                => '1.2',
                        
'email_validation_level' => 5,
                        
'correction_emails'      => 'false',
                        
'max_email_corrections'  => 1,
                        
'Records'                => array('Record' => array('email' => $email)));
        
        
$result $client->Validate($params);
        
$code   $result->Records->Record->email->status->code;
        
        @
ini_set('default_socket_timeout'$default_timeout);
        
        switch ((int)
$code) {
            case 
5/* Validation Timeout */
            
case 10/* Syntax OK */
            
case 20/* Syntax OK and domain valid according to the domain database */
            
case 30/* Syntax OK and domain exists */
            
case 40/* Syntax OK, domain exists, and domain can receive email */
            
case 50/* Syntax OK, domain exists, and mailbox does not reject mail */
                
return true;
                break;
            case 
200/* Invalid top-level-domain (TLD) in address */
            
case 310/* Domain does not exist */
            
case 315/* Domain does not have a valid IP address */
            
case 325/* Domain can not receive email */
                
$filter['filter_type']  = 'D';
                
$filter['filter_value'] = $domain;
                
$filter['filter_permanent'] = 0;
                
$filter['filter_expires'] = time() + 2592000/* filter expires after 30 days */

                
@func_array2insert('filter_email_validation'$filtertrue);
                return 
false;
                break;
            case 
400/* The mailbox is invalid or the username does not exist at the domain */
                
$filter['filter_type']  = 'L';
                
$filter['filter_value'] = $localpart;
                
$filter['filter_permanent'] = 0;
                
$filter['filter_expires'] = time() + 1296000/* filter expires after 15 days */

                
@func_array2insert('filter_email_validation'$filtertrue);
                return 
false;
                break;
            case 
420/* Mail is not accepted for this domain */
                
$filter['filter_type']  = 'D';
                
$filter['filter_value'] = $domain;
                
$filter['filter_permanent'] = 0;
                
$filter['filter_expires'] = time() + 2592000/* filter expires after 30 days */
                
                
@func_array2insert('filter_email_validation'$filtertrue);
                return 
false;
                break;
            case 
500/* Addresses with that username are not allowed */
                
$filter['filter_type']  = 'L';
                
$filter['filter_value'] = $localpart;
                
$filter['filter_permanent'] = 0;
                
$filter['filter_expires'] = time() + 1296000/* filter expires after 15 days */

                
@func_array2insert('filter_email_validation'$filtertrue);
                return 
false;
                break;
            case 
505/* Addresses with that domain are not allowed */
                
$filter['filter_type']  = 'D';
                
$filter['filter_value'] = $domain;
                
$filter['filter_permanent'] = 0;
                
$filter['filter_expires'] = time() + 2592000/* filter expires after 30 days */
                
                
@func_array2insert('filter_email_validation'$filtertrue);
                return 
false;
                break;
            default:
                return 
false;
                break;
        }
    }
    catch (
Exception $e)
    {
        @
ini_set('default_socket_timeout'$default_timeout);
        return 
true;
    }
    catch (
SoapFault $e)
    {
        @
ini_set('default_socket_timeout'$default_timeout);
        return 
true;
    }
}
// }}} 

NOTE: By default the system will block failed domain names for 30 days and failed usernames for 15 days. You may tweak these to your desire but you should not go beyond 30 days for sanity reasons.

Once you have fully tested this modification it should help reduce any problems you have from bad e-mails being used that can tie up mail servers or prevent communication. It is suggested you change the language variable txt_email_invalid to be more specific as to why the email address failed when they are attempting to register or use any part of the site that utilizes func_check_email().

Hopefully you will find this as useful as we have over the years.
Reply With Quote

The following user thanks exsecror for this useful post:
am2003 (11-23-2011)
  #3  
Old 02-20-2015, 01:28 AM
 
buywink buywink is offline
 

Advanced Member
  
Join Date: Apr 2012
Posts: 93
 

Default Re: Improved Email Address Validation

Will it work on 4.6.1?
__________________
x-cart Gold 4.4.5
Reply With Quote
Reply
   X-Cart forums > X-Cart 4 > Dev Questions


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -8. The time now is 10:22 AM.

   

 
X-Cart forums © 2001-2020