<?php  /**   * To validate an email address according to RFCs 5321, 5322 and others   *    * Copyright (c) 2008-2010, Dominic Sayers                                                      <br>   * Test schema documentation Copyright (c) 2010, Daniel Marschall                               <br>   * All rights reserved.   *    * Redistribution and use in source and binary forms, with or without modification,   * are permitted provided that the following conditions are met:   *    *     - Redistributions of source code must retain the above copyright notice,   *       this list of conditions and the following disclaimer.   *     - Redistributions in binary form must reproduce the above copyright notice,   *       this list of conditions and the following disclaimer in the documentation   *       and/or other materials provided with the distribution.   *     - Neither the name of Dominic Sayers nor the names of its contributors may be   *       used to endorse or promote products derived from this software without   *       specific prior written permission.   *    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   *    * @package     is_email   * @author      Dominic Sayers <dominic@sayers.cc>   * @copyright   2008-2010 Dominic Sayers   * @license     http://www.opensource.org/licenses/bsd-license.php BSD License   * @link        http://www.dominicsayers.com/isemail   * @version     2.4.2 - Workaround PHP bug (http://bugs.php.net/48645) in test script   */    // The quality of this code has been improved greatly by using PHPLint  // Copyright (c) 2009 Umberto Salsi  // This is free software; see the license for copying conditions.  // More info: http://www.icosaedro.it/phplint/  /*.          require_module 'standard';          require_module 'pcre';  .*/  /*.mixed.*/ function is_email (/*.string.*/ $email, $checkDNS = false, $errorlevel = false) {          // Check that $email is a valid address. Read the following RFCs to understand the constraints:          //      (http://tools.ietf.org/html/rfc5321)          //      (http://tools.ietf.org/html/rfc5322)          //      (http://tools.ietf.org/html/rfc4291#section-2.2)          //      (http://tools.ietf.org/html/rfc1123#section-2.1)          //      (http://tools.ietf.org/html/rfc3696) (guidance only)            //      $errorlevel     Behaviour          //      --------------- ---------------------------------------------------------------------------          //      E_ERROR         Return validation failures only. For technically valid addresses return          //                      ISEMAIL_VALID          //      E_WARNING       Return warnings for unlikely but technically valid addresses. This includes          //                      addresses at TLDs (e.g. johndoe@com), addresses with FWS and comments,          //                      addresses that are quoted and addresses that contain no alphabetic or          //                      numeric characters.          //      false           Return true for valid addresses, false for invalid ones. No warnings.          //          //      Errors can be distinguished from warnings if ($return_value > ISEMAIL_ERROR)  // version 2.0: Enhance $diagnose parameter to $errorlevel            if (!defined('ISEMAIL_VALID')) {                  // No errors                  define('ISEMAIL_VALID'                  , 0);                  // Warnings (valid address but unlikely in the real world)                  define('ISEMAIL_WARNING'                , 64);                  define('ISEMAIL_TLD'                    , 65);                  define('ISEMAIL_TLDNUMERIC'             , 66);                  define('ISEMAIL_QUOTEDSTRING'           , 67);                  define('ISEMAIL_COMMENTS'               , 68);                  define('ISEMAIL_FWS'                    , 69);                  define('ISEMAIL_ADDRESSLITERAL'         , 70);                  define('ISEMAIL_UNLIKELYINITIAL'        , 71);                  define('ISEMAIL_SINGLEGROUPELISION'     , 72);                  define('ISEMAIL_DOMAINNOTFOUND'         , 73);                  define('ISEMAIL_MXNOTFOUND'             , 74);                  // Errors (invalid address)                  define('ISEMAIL_ERROR'                  , 128);                  define('ISEMAIL_TOOLONG'                , 129);                  define('ISEMAIL_NOAT'                   , 130);                  define('ISEMAIL_NOLOCALPART'            , 131);                  define('ISEMAIL_NODOMAIN'               , 132);                  define('ISEMAIL_ZEROLENGTHELEMENT'      , 133);                  define('ISEMAIL_BADCOMMENT_START'       , 134);                  define('ISEMAIL_BADCOMMENT_END'         , 135);                  define('ISEMAIL_UNESCAPEDDELIM'         , 136);                  define('ISEMAIL_EMPTYELEMENT'           , 137);                  define('ISEMAIL_UNESCAPEDSPECIAL'       , 138);                  define('ISEMAIL_LOCALTOOLONG'           , 139);                  define('ISEMAIL_IPV4BADPREFIX'          , 140);                  define('ISEMAIL_IPV6BADPREFIXMIXED'     , 141);                  define('ISEMAIL_IPV6BADPREFIX'          , 142);                  define('ISEMAIL_IPV6GROUPCOUNT'         , 143);                  define('ISEMAIL_IPV6DOUBLEDOUBLECOLON'  , 144);                  define('ISEMAIL_IPV6BADCHAR'            , 145);                  define('ISEMAIL_IPV6TOOMANYGROUPS'      , 146);                  define('ISEMAIL_DOMAINEMPTYELEMENT'     , 147);                  define('ISEMAIL_DOMAINELEMENTTOOLONG'   , 148);                  define('ISEMAIL_DOMAINBADCHAR'          , 149);                  define('ISEMAIL_DOMAINTOOLONG'          , 150);                  define('ISEMAIL_IPV6SINGLECOLONSTART'   , 151);                  define('ISEMAIL_IPV6SINGLECOLONEND'     , 152);                  // Unexpected errors                  define('ISEMAIL_BADPARAMETER'           , 190);                  define('ISEMAIL_NOTDEFINED'             , 191);  // revision 2.1: Redefined unexpected error constants so they don't clash with the ISEMAIL_WARNING bit          }            switch ($errorlevel) {                  case E_WARNING: $diagnose = true;       $warn = true;   break;                  case E_ERROR:   $diagnose = true;       $warn = false;  break;                  case false:     $diagnose = false;      $warn = false;  break;                  default:        $diagnose = false;      $warn = false;          }            $return_status = ($diagnose) ? ISEMAIL_VALID : true;  // version 2.0: Enhance $diagnose parameter to $errorlevel            // the upper limit on address lengths should normally be considered to be 254          //      (http://www.rfc-editor.org/errata_search.php?rfc=3696)          //      NB My erratum has now been verified by the IETF so the correct answer is 254          //          // The maximum total length of a reverse-path or forward-path is 256          // characters (including the punctuation and element separators)          //      (http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3)          //      NB There is a mandatory 2-character wrapper round the actual address          $emailLength = strlen($email);  // revision 1.17: Max length reduced to 254 (see above)          if ($emailLength > 254)                 return $diagnose ? ISEMAIL_TOOLONG      : false;        // Too long            // Contemporary email addresses consist of a "local part" separated from          // a "domain part" (a fully-qualified domain name) by an at-sign ("@").          //      (http://tools.ietf.org/html/rfc3696#section-3)          $atIndex = strrpos($email,'@');            if ($atIndex === false)                 return $diagnose ? ISEMAIL_NOAT         : false;        // No at-sign          if ($atIndex === 0)                     return $diagnose ? ISEMAIL_NOLOCALPART  : false;        // No local part          if ($atIndex === $emailLength - 1)      return $diagnose ? ISEMAIL_NODOMAIN     : false;        // No domain part  // revision 1.14: Length test bug suggested by Andrew Campbell of Gloucester, MA            // Sanitize comments          // - remove nested comments, quotes and dots in comments          // - remove parentheses and dots from quoted strings          $braceDepth     = 0;          $inQuote        = false;          $escapeThisChar = false;            for ($i = 0; $i < $emailLength; ++$i) {                  $char = $email[$i];                  $replaceChar = false;                    if ($char === '\\')     $escapeThisChar = !$escapeThisChar;                     // Escape the next character?                  else {                          switch ($char) {                          case '(':                                  if      ($escapeThisChar)       $replaceChar    = true;                                  else if ($inQuote)              $replaceChar    = true;                                  else if ($braceDepth++ > 0)     $replaceChar    = true;         // Increment brace depth                                    break;                          case ')':                                  if      ($escapeThisChar)       $replaceChar    = true;                                  else if ($inQuote)              $replaceChar    = true;                                  else {                                          if (--$braceDepth > 0)  $replaceChar    = true;         // Decrement brace depth                                          if ($braceDepth < 0)    $braceDepth     = 0;                                  }                                    break;                          case '"':                                  if      ($escapeThisChar)       $replaceChar    = true;                                  else if ($braceDepth === 0)     $inQuote        = !$inQuote;    // Are we inside a quoted string?                                  else                            $replaceChar    = true;                                    break;                          case '.':                                  if      ($escapeThisChar)       $replaceChar    = true;         // Dots don't help us either                                  else if ($braceDepth > 0)       $replaceChar    = true;                                    break;                          default:                          }                            $escapeThisChar = false;  //                      if ($replaceChar) $email[$i] = 'x';                                     // Replace the offending character with something harmless  // revision 1.12: Line above replaced because PHPLint doesn't like that syntax                          if ($replaceChar) $email = (string) substr_replace($email, 'x', $i, 1); // Replace the offending character with something harmless                  }          }            $localPart      = substr($email, 0, $atIndex);          $domain         = substr($email, $atIndex + 1);          $FWS            = "(?:(?:(?:[ \\t]*(?:\\r\\n))?[ \\t]+)|(?:[ \\t]+(?:(?:\\r\\n)[ \\t]+)*))";    // Folding white space          // Let's check the local part for RFC compliance...          //          // local-part      =       dot-atom / quoted-string / obs-local-part          // obs-local-part  =       word *("." word)          //      (http://tools.ietf.org/html/rfc5322#section-3.4.1)          //          // Problem: need to distinguish between "first.last" and "first"."last"          // (i.e. one element or two). And I suck at regexes.          $dotArray       = /*. (array[int]string) .*/ preg_split('/\\.(?=(?:[^\\"]*\\"[^\\"]*\\")*(?![^\\"]*\\"))/m', $localPart);          $partLength     = 0;            foreach ($dotArray as $element) {                  // Remove any leading or trailing FWS                  $new_element = preg_replace("/^$FWS|$FWS\$/", '', $element);                  if ($warn && ($element !== $new_element)) $return_status = ISEMAIL_FWS; // FWS is unlikely in the real world                  $element = $new_element;  // version 2.3: Warning condition added                  $elementLength  = strlen($element);                    if ($elementLength === 0)                                                               return $diagnose ? ISEMAIL_ZEROLENGTHELEMENT    : false;        // Can't have empty element (consecutive dots or dots at the start or end)  // revision 1.15: Speed up the test and get rid of "unitialized string offset" notices from PHP                    // We need to remove any valid comments (i.e. those at the start or end of the element)                  if ($element[0] === '(') {                          if ($warn) $return_status = ISEMAIL_COMMENTS;   // Comments are unlikely in the real world  // version 2.0: Warning condition added                          $indexBrace = strpos($element, ')');                          if ($indexBrace !== false) {                                  if (preg_match('/(?<!\\\\)[\\(\\)]/', substr($element, 1, $indexBrace - 1)) > 0)                                                                                                          return $diagnose ? ISEMAIL_BADCOMMENT_START     : false;        // Illegal characters in comment                                  $element        = substr($element, $indexBrace + 1, $elementLength - $indexBrace - 1);                                  $elementLength  = strlen($element);                          }                  }                    if ($element[$elementLength - 1] === ')') {                          if ($warn) $return_status = ISEMAIL_COMMENTS;   // Comments are unlikely in the real world  // version 2.0: Warning condition added                          $indexBrace = strrpos($element, '(');                          if ($indexBrace !== false) {                                  if (preg_match('/(?<!\\\\)(?:[\\(\\)])/', substr($element, $indexBrace + 1, $elementLength - $indexBrace - 2)) > 0)                                                                                                          return $diagnose ? ISEMAIL_BADCOMMENT_END       : false;        // Illegal characters in comment                                  $element        = substr($element, 0, $indexBrace);                                  $elementLength  = strlen($element);                          }                  }                    // Remove any remaining leading or trailing FWS around the element (having removed any comments)                  $new_element = preg_replace("/^$FWS|$FWS\$/", '', $element);                  if ($warn && ($element !== $new_element)) $return_status = ISEMAIL_FWS; // FWS is unlikely in the real world                  $element = $new_element;  // version 2.0: Warning condition added                    // What's left counts towards the maximum length for this part                  if ($partLength > 0) $partLength++;     // for the dot                  $partLength += strlen($element);                    // Each dot-delimited component can be an atom or a quoted string                  // (because of the obs-local-part provision)                  if (preg_match('/^"(?:.)*"$/s', $element) > 0) {                          // Quoted-string tests:                          if ($warn) $return_status = ISEMAIL_QUOTEDSTRING;       // Quoted string is unlikely in the real world  // version 2.0: Warning condition added                          // Remove any FWS                          $element = preg_replace("/(?<!\\\\)$FWS/", '', $element);       // A warning condition, but we've already raised ISEMAIL_QUOTEDSTRING                          // My regex skillz aren't up to distinguishing between \" \\" \\\" \\\\" etc.                          // So remove all \\ from the string first...                          $element = preg_replace('/\\\\\\\\/', ' ', $element);                          if (preg_match('/(?<!\\\\|^)["\\r\\n\\x00](?!$)|\\\\"$|""/', $element) > 0)     return $diagnose ? ISEMAIL_UNESCAPEDDELIM       : false;        // ", CR, LF and NUL must be escaped  // version 2.0: allow ""@example.com because it's technically valid                  } else {                          // Unquoted string tests:                          //                          // Period (".") may...appear, but may not be used to start or end the                          // local part, nor may two or more consecutive periods appear.                          //      (http://tools.ietf.org/html/rfc3696#section-3)                          //                          // A zero-length element implies a period at the beginning or end of the                          // local part, or two periods together. Either way it's not allowed.                          if ($element === '')                                                            return $diagnose ? ISEMAIL_EMPTYELEMENT         : false;        // Dots in wrong place                            // Any ASCII graphic (printing) character other than the                          // at-sign ("@"), backslash, double quote, comma, or square brackets may                          // appear without quoting.  If any of that list of excluded characters                          // are to appear, they must be quoted                          //      (http://tools.ietf.org/html/rfc3696#section-3)                          //                          // Any excluded characters? i.e. 0x00-0x20, (, ), <, >, [, ], :, ;, @, \, comma, period, "                          if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]/', $element) > 0)      return $diagnose ? ISEMAIL_UNESCAPEDSPECIAL     : false;        // These characters must be in a quoted string                          if ($warn && (preg_match('/^\\w+/', $element) === 0)) $return_status = ISEMAIL_UNLIKELYINITIAL; // First character is an odd one                  }          }            if ($partLength > 64)                                                                           return $diagnose ? ISEMAIL_LOCALTOOLONG         : false;        // Local part must be 64 characters or less            // Now let's check the domain part...            // The domain name can also be replaced by an IP address in square brackets          //      (http://tools.ietf.org/html/rfc3696#section-3)          //      (http://tools.ietf.org/html/rfc5321#section-4.1.3)          //      (http://tools.ietf.org/html/rfc4291#section-2.2)          if (preg_match('/^\\[(.)+]$/', $domain) === 1) {                  // It's an address-literal                  if ($warn) $return_status = ISEMAIL_ADDRESSLITERAL;     // Quoted string is unlikely in the real world  // version 2.0: Warning condition added                  $addressLiteral = substr($domain, 1, strlen($domain) - 2);                  $groupMax       = 8;  // revision 2.1: new IPv6 testing strategy                  $matchesIP      = array();                    // Extract IPv4 part from the end of the address-literal (if there is one)                  if (preg_match('/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', $addressLiteral, $matchesIP) > 0) {                          $index = strrpos($addressLiteral, $matchesIP[0]);                            if ($index === 0) {                                  // Nothing there except a valid IPv4 address, so...                                  return ($diagnose) ? $return_status : true;  // version 2.0: return warning if one is set                          } else {  //-                             // Assume it's an attempt at a mixed address (IPv6 + IPv4)  //-                             if ($addressLiteral[$index - 1] !== ':')                                return $diagnose ? ISEMAIL_IPV4BADPREFIX        : false;        // Character preceding IPv4 address must be ':'  // revision 2.1: new IPv6 testing strategy                                  if (substr($addressLiteral, 0, 5) !== 'IPv6:')                          return $diagnose ? ISEMAIL_IPV6BADPREFIXMIXED   : false;        // RFC5321 section 4.1.3  //-  //-                             $IPv6           = substr($addressLiteral, 5, ($index === 7) ? 2 : $index - 6);  //-                             $groupMax       = 6;  // revision 2.1: new IPv6 testing strategy                                  $IPv6           = substr($addressLiteral, 5, $index - 5) . '0000:0000'; // Convert IPv4 part to IPv6 format                          }                  } else {                          // It must be an attempt at pure IPv6                          if (substr($addressLiteral, 0, 5) !== 'IPv6:')                                  return $diagnose ? ISEMAIL_IPV6BADPREFIX        : false;        // RFC5321 section 4.1.3                          $IPv6 = substr($addressLiteral, 5);  //-                     $groupMax = 8;  // revision 2.1: new IPv6 testing strategy                  }  //echo "\n<br /><pre>\$IPv6 = $IPv6</pre>\n"; // debug                  $groupCount     = preg_match_all('/^[0-9a-fA-F]{0,4}|\\:[0-9a-fA-F]{0,4}|(.)/', $IPv6, $matchesIP);                  $index          = strpos($IPv6,'::');    //echo "\n<br /><pre>\$matchesIP[0] = " . var_export($matchesIP[0], true) . "</pre>\n"; // debug                  if ($index === false) {                          // We need exactly the right number of groups                          if ($groupCount !== $groupMax)                                                  return $diagnose ? ISEMAIL_IPV6GROUPCOUNT       : false;        // RFC5321 section 4.1.3                  } else {                          if ($index !== strrpos($IPv6,'::'))                                             return $diagnose ? ISEMAIL_IPV6DOUBLEDOUBLECOLON : false;       // More than one '::'                          if ($index === 0 || $index === (strlen($IPv6) - 2)) $groupMax++;        // RFC 4291 allows :: at the start or end of an address with 7 other groups in addition  //echo "\n<br /><pre>\$groupMax = $groupMax</pre>\n"; // debug                          if ($groupCount > $groupMax)                                                    return $diagnose ? ISEMAIL_IPV6TOOMANYGROUPS    : false;        // Too many IPv6 groups in address                          if ($groupCount === $groupMax) $return_status = ISEMAIL_SINGLEGROUPELISION;     // Eliding a single group with :: is deprecated by RFCs 5321 & 5952                  }                    // Check for single : at start and end of address                  if (($matchesIP[0][0] === '') && ($matchesIP[0][1] !== ':'))                            return $diagnose ? ISEMAIL_IPV6SINGLECOLONSTART : false;        // Address starts with a single colon                  if (($matchesIP[0][$groupCount - 1] === ':') && ($matchesIP[0][$groupCount - 2] !== ':')) return $diagnose ? ISEMAIL_IPV6SINGLECOLONEND : false;        // Address ends with a single colon                    // Check for unmatched characters                  array_multisort($matchesIP[1], SORT_DESC);                  if ($matchesIP[1][0] !== '') {  //echo "\n<br /><pre>\$matchesIP[1] = " . var_export($matchesIP[1], true) . "</pre>\n"; // debug                  return $diagnose ? ISEMAIL_IPV6BADCHAR          : false;        // Illegal characters in address  } // debug                  // It's a valid IPv6 address, so...                  return ($diagnose) ? $return_status : true;  // revision 2.1: bug fix: now correctly return warning status          } else {                  // It's a domain name...                    // The syntax of a legal Internet host name was specified in RFC-952                  // One aspect of host name syntax is hereby changed: the                  // restriction on the first character is relaxed to allow either a                  // letter or a digit.                  //      (http://tools.ietf.org/html/rfc1123#section-2.1)                  //                  // NB RFC 1123 updates RFC 1035, but this is not currently apparent from reading RFC 1035.                  //                  // Most common applications, including email and the Web, will generally not                  // permit...escaped strings                  //      (http://tools.ietf.org/html/rfc3696#section-2)                  //                  // the better strategy has now become to make the "at least one period" test,                  // to verify LDH conformance (including verification that the apparent TLD name                  // is not all-numeric)                  //      (http://tools.ietf.org/html/rfc3696#section-2)                  //                  // Characters outside the set of alphabetic characters, digits, and hyphen MUST NOT appear in domain name                  // labels for SMTP clients or servers                  //      (http://tools.ietf.org/html/rfc5321#section-4.1.2)                  //                  // RFC5321 precludes the use of a trailing dot in a domain name for SMTP purposes                  //      (http://tools.ietf.org/html/rfc5321#section-4.1.2)                  $dotArray       = /*. (array[int]string) .*/ preg_split('/\\.(?=(?:[^\\"]*\\"[^\\"]*\\")*(?![^\\"]*\\"))/m', $domain);                  $partLength     = 0;                  $element        = ''; // Since we use $element after the foreach loop let's make sure it has a value  // revision 1.13: Line above added because PHPLint now checks for Definitely Assigned Variables                    if ($warn && (count($dotArray) === 1))  $return_status = ISEMAIL_TLD;   // The mail host probably isn't a TLD  // version 2.0: downgraded to a warning                    foreach ($dotArray as $element) {                          // Remove any leading or trailing FWS                          $new_element    = preg_replace("/^$FWS|$FWS\$/", '', $element);                          if ($warn && ($element !== $new_element)) $return_status = ISEMAIL_FWS; // FWS is unlikely in the real world                          $element = $new_element;  // version 2.0: Warning condition added                          $elementLength  = strlen($element);                            // Each dot-delimited component must be of type atext                          // A zero-length element implies a period at the beginning or end of the                          // local part, or two periods together. Either way it's not allowed.                          if ($elementLength === 0)                                                       return $diagnose ? ISEMAIL_DOMAINEMPTYELEMENT   : false;        // Dots in wrong place  // revision 1.15: Speed up the test and get rid of "unitialized string offset" notices from PHP                            // Then we need to remove all valid comments (i.e. those at the start or end of the element                          if ($element[0] === '(') {                                  if ($warn) $return_status = ISEMAIL_COMMENTS;   // Comments are unlikely in the real world  // version 2.0: Warning condition added                                  $indexBrace = strpos($element, ')');                                  if ($indexBrace !== false) {                                          if (preg_match('/(?<!\\\\)[\\(\\)]/', substr($element, 1, $indexBrace - 1)) > 0)                                                                                                          return $diagnose ? ISEMAIL_BADCOMMENT_START     : false;        // Illegal characters in comment  // revision 1.17: Fixed name of constant (also spotted by turboflash - thanks!)                                          $element        = substr($element, $indexBrace + 1, $elementLength - $indexBrace - 1);                                          $elementLength  = strlen($element);                                  }                          }                            if ($element[$elementLength - 1] === ')') {                                  if ($warn) $return_status = ISEMAIL_COMMENTS;   // Comments are unlikely in the real world  // version 2.0: Warning condition added                                  $indexBrace = strrpos($element, '(');                                  if ($indexBrace !== false) {                                          if (preg_match('/(?<!\\\\)(?:[\\(\\)])/', substr($element, $indexBrace + 1, $elementLength - $indexBrace - 2)) > 0)                                                                                                          return $diagnose ? ISEMAIL_BADCOMMENT_END       : false;        // Illegal characters in comment  // revision 1.17: Fixed name of constant (also spotted by turboflash - thanks!)                                          $element        = substr($element, 0, $indexBrace);                                          $elementLength  = strlen($element);                                  }                          }                            // Remove any leading or trailing FWS around the element (inside any comments)                          $new_element    = preg_replace("/^$FWS|$FWS\$/", '', $element);                          if ($warn && ($element !== $new_element)) $return_status = ISEMAIL_FWS; // FWS is unlikely in the real world                          $element = $new_element;  // version 2.0: Warning condition added                            // What's left counts towards the maximum length for this part                          if ($partLength > 0) $partLength++;     // for the dot                          $partLength += strlen($element);                            // The DNS defines domain name syntax very generally -- a                          // string of labels each containing up to 63 8-bit octets,                          // separated by dots, and with a maximum total of 255                          // octets.                          //      (http://tools.ietf.org/html/rfc1123#section-6.1.3.5)                          if ($elementLength > 63)                                                        return $diagnose ? ISEMAIL_DOMAINELEMENTTOOLONG : false;        // Label must be 63 characters or less                            // Any ASCII graphic (printing) character other than the                          // at-sign ("@"), backslash, double quote, comma, or square brackets may                          // appear without quoting.  If any of that list of excluded characters                          // are to appear, they must be quoted                          //      (http://tools.ietf.org/html/rfc3696#section-3)                          //                          // If the hyphen is used, it is not permitted to appear at                          // either the beginning or end of a label.                          //      (http://tools.ietf.org/html/rfc3696#section-2)                          //                          // Any excluded characters? i.e. 0x00-0x20, (, ), <, >, [, ], :, ;, @, \, comma, period, "                          if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]|^-|-$/', $element) > 0) return $diagnose ? ISEMAIL_DOMAINBADCHAR       : false;        // Illegal character in domain name                  }                    if ($partLength > 255)                                                                  return $diagnose ? ISEMAIL_DOMAINTOOLONG        : false;        // Domain part must be 255 characters or less (http://tools.ietf.org/html/rfc1123#section-6.1.3.5)                    if ($warn && (preg_match('/^[0-9]+$/', $element) > 0))  $return_status = ISEMAIL_TLDNUMERIC;    // TLD probably isn't all-numeric (http://www.apps.ietf.org/rfc/rfc3696.html#sec-2)  // version 2.0: Downgraded to a warning                    // Check DNS?                  if ($diagnose && ($return_status === ISEMAIL_VALID) && $checkDNS && function_exists('checkdnsrr')) {                          if (!(checkdnsrr($domain, 'A')))        $return_status = ISEMAIL_DOMAINNOTFOUND;        // 'A' record for domain can't be found                          if (!(checkdnsrr($domain, 'MX')))       $return_status = ISEMAIL_MXNOTFOUND;            // 'MX' record for domain can't be found                  }          }            // Eliminate all other factors, and the one which remains must be the truth.          //      (Sherlock Holmes, The Sign of Four)          return ($diagnose) ? $return_status : true;  // version 2.0: return warning if one is set  }  ?>  
