[SPIP] +2.1.12
[velocampus/web/www.git] / www / plugins / auto / verifier / inc / is_email.php
diff --git a/www/plugins/auto/verifier/inc/is_email.php b/www/plugins/auto/verifier/inc/is_email.php
new file mode 100644 (file)
index 0000000..32e00ae
--- /dev/null
@@ -0,0 +1,426 @@
+<?php\r
+\r
+if (!defined("_ECRIRE_INC_VERSION")) return;\r
+\r
+/**\r
+ * @package    isemail\r
+ * @author     Dominic Sayers <dominic_sayers@hotmail.com>\r
+ * @copyright  2009 Dominic Sayers\r
+ * @license    http://www.opensource.org/licenses/bsd-license.php BSD License\r
+ * @link       http://www.dominicsayers.com/isemail\r
+ * @version    1.16 - Added optional diagnosis codes (amended all lines with a return statement)\r
+ */\r
+\r
+/*\r
+Copyright (c) 2008-2010, Dominic Sayers\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without modification,\r
+are permitted provided that the following conditions are met:\r
+\r
+ * Redistributions of source code must retain the above copyright notice, this\r
+   list of conditions and the following disclaimer.\r
+ * Redistributions in binary form must reproduce the above copyright notice,\r
+   this list of conditions and the following disclaimer in the documentation\r
+   and/or other materials provided with the distribution.\r
+ * Neither the name of Dominic Sayers nor the names of its contributors may be\r
+   used to endorse or promote products derived from this software without\r
+   specific prior written permission.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\r
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+/*.\r
+       require_module 'standard';\r
+       require_module 'pcre';\r
+.*/\r
+/*.mixed.*/ function is_email (/*.string.*/ $email, $checkDNS = false, $diagnose = false) {\r
+       // Check that $email is a valid address. Read the following RFCs to understand the constraints:\r
+       //      (http://tools.ietf.org/html/rfc5322)\r
+       //      (http://tools.ietf.org/html/rfc3696)\r
+       //      (http://tools.ietf.org/html/rfc5321)\r
+       //      (http://tools.ietf.org/html/rfc4291#section-2.2)\r
+       //      (http://tools.ietf.org/html/rfc1123#section-2.1)\r
+\r
+       if (!defined('ISEMAIL_VALID')) {\r
+               define('ISEMAIL_VALID'                  , 0);\r
+               define('ISEMAIL_TOOLONG'                , 1);\r
+               define('ISEMAIL_NOAT'                   , 2);\r
+               define('ISEMAIL_NOLOCALPART'            , 3);\r
+               define('ISEMAIL_NODOMAIN'               , 4);\r
+               define('ISEMAIL_ZEROLENGTHELEMENT'      , 5);\r
+               define('ISEMAIL_BADCOMMENT_START'       , 6);\r
+               define('ISEMAIL_BADCOMMENT_END'         , 7);\r
+               define('ISEMAIL_UNESCAPEDDELIM'         , 8);\r
+               define('ISEMAIL_EMPTYELEMENT'           , 9);\r
+               define('ISEMAIL_UNESCAPEDSPECIAL'       , 10);\r
+               define('ISEMAIL_LOCALTOOLONG'           , 11);\r
+               define('ISEMAIL_IPV4BADPREFIX'          , 12);\r
+               define('ISEMAIL_IPV6BADPREFIXMIXED'     , 13);\r
+               define('ISEMAIL_IPV6BADPREFIX'          , 14);\r
+               define('ISEMAIL_IPV6GROUPCOUNT'         , 15);\r
+               define('ISEMAIL_IPV6DOUBLEDOUBLECOLON'  , 16);\r
+               define('ISEMAIL_IPV6BADCHAR'            , 17);\r
+               define('ISEMAIL_IPV6TOOMANYGROUPS'      , 18);\r
+               define('ISEMAIL_TLD'                    , 19);\r
+               define('ISEMAIL_DOMAINEMPTYELEMENT'     , 20);\r
+               define('ISEMAIL_DOMAINELEMENTTOOLONG'   , 21);\r
+               define('ISEMAIL_DOMAINBADCHAR'          , 22);\r
+               define('ISEMAIL_DOMAINTOOLONG'          , 23);\r
+               define('ISEMAIL_TLDNUMERIC'             , 24);\r
+               define('ISEMAIL_DOMAINNOTFOUND'         , 25);\r
+               define('ISEMAIL_NOTDEFINED'             , 99);\r
+       }\r
+\r
+       // the upper limit on address lengths should normally be considered to be 256\r
+       //      (http://www.rfc-editor.org/errata_search.php?rfc=3696)\r
+       //      NB I think John Klensin is misreading RFC 5321 and the the limit should actually be 254\r
+       //      However, I will stick to the published number until it is changed.\r
+       //\r
+       // The maximum total length of a reverse-path or forward-path is 256\r
+       // characters (including the punctuation and element separators)\r
+       //      (http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3)\r
+       $emailLength = strlen($email);\r
+       if ($emailLength > 256)                 return $diagnose ? ISEMAIL_TOOLONG      : false;        // Too long\r
+\r
+       // Contemporary email addresses consist of a "local part" separated from\r
+       // a "domain part" (a fully-qualified domain name) by an at-sign ("@").\r
+       //      (http://tools.ietf.org/html/rfc3696#section-3)\r
+       $atIndex = strrpos($email,'@');\r
+\r
+       if ($atIndex === false)                 return $diagnose ? ISEMAIL_NOAT         : false;        // No at-sign\r
+       if ($atIndex === 0)                     return $diagnose ? ISEMAIL_NOLOCALPART  : false;        // No local part\r
+       if ($atIndex === $emailLength - 1)      return $diagnose ? ISEMAIL_NODOMAIN     : false;        // No domain part\r
+// revision 1.14: Length test bug suggested by Andrew Campbell of Gloucester, MA\r
+       \r
+       // Sanitize comments\r
+       // - remove nested comments, quotes and dots in comments\r
+       // - remove parentheses and dots from quoted strings\r
+       $braceDepth     = 0;\r
+       $inQuote        = false;\r
+       $escapeThisChar = false;\r
+\r
+       for ($i = 0; $i < $emailLength; ++$i) {\r
+               $char = $email[$i];\r
+               $replaceChar = false;\r
+\r
+               if ($char === '\\') {\r
+                       $escapeThisChar = !$escapeThisChar;     // Escape the next character?\r
+               } else {\r
+                       switch ($char) {\r
+                       case '(':\r
+                               if ($escapeThisChar) {\r
+                                       $replaceChar = true;\r
+                               } else {\r
+                                       if ($inQuote) {\r
+                                               $replaceChar = true;\r
+                                       } else {\r
+                                               if ($braceDepth++ > 0) $replaceChar = true;     // Increment brace depth\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+                       case ')':\r
+                               if ($escapeThisChar) {\r
+                                       $replaceChar = true;\r
+                               } else {\r
+                                       if ($inQuote) {\r
+                                               $replaceChar = true;\r
+                                       } else {\r
+                                               if (--$braceDepth > 0) $replaceChar = true;     // Decrement brace depth\r
+                                               if ($braceDepth < 0) $braceDepth = 0;\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+                       case '"':\r
+                               if ($escapeThisChar) {\r
+                                       $replaceChar = true;\r
+                               } else {\r
+                                       if ($braceDepth === 0) {\r
+                                               $inQuote = !$inQuote;   // Are we inside a quoted string?\r
+                                       } else {\r
+                                               $replaceChar = true;\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+                       case '.':       // Dots don't help us either\r
+                               if ($escapeThisChar) {\r
+                                       $replaceChar = true;\r
+                               } else {\r
+                                       if ($braceDepth > 0) $replaceChar = true;\r
+                               }\r
+\r
+                               break;\r
+                       default:\r
+                       }\r
+\r
+                       $escapeThisChar = false;\r
+//                     if ($replaceChar) $email[$i] = 'x';     // Replace the offending character with something harmless\r
+// revision 1.12: Line above replaced because PHPLint doesn't like that syntax\r
+                       if ($replaceChar) $email = (string) substr_replace($email, 'x', $i, 1); // Replace the offending character with something harmless\r
+               }\r
+       }\r
+\r
+       $localPart      = substr($email, 0, $atIndex);\r
+       $domain         = substr($email, $atIndex + 1);\r
+       $FWS            = "(?:(?:(?:[ \\t]*(?:\\r\\n))?[ \\t]+)|(?:[ \\t]+(?:(?:\\r\\n)[ \\t]+)*))";    // Folding white space\r
+       // Let's check the local part for RFC compliance...\r
+       //\r
+       // local-part      =       dot-atom / quoted-string / obs-local-part\r
+       // obs-local-part  =       word *("." word)\r
+       //      (http://tools.ietf.org/html/rfc5322#section-3.4.1)\r
+       //\r
+       // Problem: need to distinguish between "first.last" and "first"."last"\r
+       // (i.e. one element or two). And I suck at regexes.\r
+       $dotArray       = /*. (array[int]string) .*/ preg_split('/\\.(?=(?:[^\\"]*\\"[^\\"]*\\")*(?![^\\"]*\\"))/m', $localPart);\r
+       $partLength     = 0;\r
+\r
+       foreach ($dotArray as $element) {\r
+               // Remove any leading or trailing FWS\r
+               $element        = preg_replace("/^$FWS|$FWS\$/", '', $element);\r
+               $elementLength  = strlen($element);\r
+\r
+               if ($elementLength === 0)                                                               return $diagnose ? ISEMAIL_ZEROLENGTHELEMENT    : false;        // Can't have empty element (consecutive dots or dots at the start or end)\r
+// revision 1.15: Speed up the test and get rid of "unitialized string offset" notices from PHP\r
+\r
+               // We need to remove any valid comments (i.e. those at the start or end of the element)\r
+               if ($element[0] === '(') {\r
+                       $indexBrace = strpos($element, ')');\r
+                       if ($indexBrace !== false) {\r
+                               if (preg_match('/(?<!\\\\)[\\(\\)]/', substr($element, 1, $indexBrace - 1)) > 0) {\r
+                                                                                                       return $diagnose ? ISEMAIL_BADCOMMENT_START     : false;        // Illegal characters in comment\r
+                               }\r
+                               $element        = substr($element, $indexBrace + 1, $elementLength - $indexBrace - 1);\r
+                               $elementLength  = strlen($element);\r
+                       }\r
+               }\r
+               \r
+               if ($element[$elementLength - 1] === ')') {\r
+                       $indexBrace = strrpos($element, '(');\r
+                       if ($indexBrace !== false) {\r
+                               if (preg_match('/(?<!\\\\)(?:[\\(\\)])/', substr($element, $indexBrace + 1, $elementLength - $indexBrace - 2)) > 0) {\r
+                                                                                                       return $diagnose ? ISEMAIL_BADCOMMENT_END       : false;        // Illegal characters in comment\r
+                               }\r
+                               $element        = substr($element, 0, $indexBrace);\r
+                               $elementLength  = strlen($element);\r
+                       }\r
+               }\r
+\r
+               // Remove any leading or trailing FWS around the element (inside any comments)\r
+               $element = preg_replace("/^$FWS|$FWS\$/", '', $element);\r
+\r
+               // What's left counts towards the maximum length for this part\r
+               if ($partLength > 0) $partLength++;     // for the dot\r
+               $partLength += strlen($element);\r
+\r
+               // Each dot-delimited component can be an atom or a quoted string\r
+               // (because of the obs-local-part provision)\r
+               if (preg_match('/^"(?:.)*"$/s', $element) > 0) {\r
+                       // Quoted-string tests:\r
+                       //\r
+                       // Remove any FWS\r
+                       $element = preg_replace("/(?<!\\\\)$FWS/", '', $element);\r
+                       // My regex skillz aren't up to distinguishing between \" \\" \\\" \\\\" etc.\r
+                       // So remove all \\ from the string first...\r
+                       $element = preg_replace('/\\\\\\\\/', ' ', $element);\r
+                       if (preg_match('/(?<!\\\\|^)["\\r\\n\\x00](?!$)|\\\\"$|""/', $element) > 0)     return $diagnose ? ISEMAIL_UNESCAPEDDELIM       : false;        // ", CR, LF and NUL must be escaped, "" is too short\r
+               } else {\r
+                       // Unquoted string tests:\r
+                       //\r
+                       // Period (".") may...appear, but may not be used to start or end the\r
+                       // local part, nor may two or more consecutive periods appear.\r
+                       //      (http://tools.ietf.org/html/rfc3696#section-3)\r
+                       //\r
+                       // A zero-length element implies a period at the beginning or end of the\r
+                       // local part, or two periods together. Either way it's not allowed.\r
+                       if ($element === '')                                                            return $diagnose ? ISEMAIL_EMPTYELEMENT : false;        // Dots in wrong place\r
+\r
+                       // Any ASCII graphic (printing) character other than the\r
+                       // at-sign ("@"), backslash, double quote, comma, or square brackets may\r
+                       // appear without quoting.  If any of that list of excluded characters\r
+                       // are to appear, they must be quoted\r
+                       //      (http://tools.ietf.org/html/rfc3696#section-3)\r
+                       //\r
+                       // Any excluded characters? i.e. 0x00-0x20, (, ), <, >, [, ], :, ;, @, \, comma, period, "\r
+                       if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]/', $element) > 0)      return $diagnose ? ISEMAIL_UNESCAPEDSPECIAL     : false;        // These characters must be in a quoted string\r
+               }\r
+       }\r
+\r
+       if ($partLength > 64) return $diagnose ? ISEMAIL_LOCALTOOLONG   : false;        // Local part must be 64 characters or less\r
+\r
+       // Now let's check the domain part...\r
+\r
+       // The domain name can also be replaced by an IP address in square brackets\r
+       //      (http://tools.ietf.org/html/rfc3696#section-3)\r
+       //      (http://tools.ietf.org/html/rfc5321#section-4.1.3)\r
+       //      (http://tools.ietf.org/html/rfc4291#section-2.2)\r
+       if (preg_match('/^\\[(.)+]$/', $domain) === 1) {\r
+               // It's an address-literal\r
+               $addressLiteral = substr($domain, 1, strlen($domain) - 2);\r
+               $matchesIP      = array();\r
+               \r
+               // Extract IPv4 part from the end of the address-literal (if there is one)\r
+               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) {\r
+                       $index = strrpos($addressLiteral, $matchesIP[0]);\r
+                       \r
+                       if ($index === 0) {\r
+                               // Nothing there except a valid IPv4 address, so...\r
+                               return $diagnose ? ISEMAIL_VALID : true;\r
+                       } else {\r
+                               // Assume it's an attempt at a mixed address (IPv6 + IPv4)\r
+                               if ($addressLiteral[$index - 1] !== ':')        return $diagnose ? ISEMAIL_IPV4BADPREFIX        : false;        // Character preceding IPv4 address must be ':'\r
+                               if (substr($addressLiteral, 0, 5) !== 'IPv6:')  return $diagnose ? ISEMAIL_IPV6BADPREFIXMIXED   : false;        // RFC5321 section 4.1.3\r
+\r
+                               $IPv6           = substr($addressLiteral, 5, ($index ===7) ? 2 : $index - 6);\r
+                               $groupMax       = 6;\r
+                       }\r
+               } else {\r
+                       // It must be an attempt at pure IPv6\r
+                       if (substr($addressLiteral, 0, 5) !== 'IPv6:')          return $diagnose ? ISEMAIL_IPV6BADPREFIX        : false;        // RFC5321 section 4.1.3\r
+                       $IPv6 = substr($addressLiteral, 5);\r
+                       $groupMax = 8;\r
+               }\r
+\r
+               $groupCount     = preg_match_all('/^[0-9a-fA-F]{0,4}|\\:[0-9a-fA-F]{0,4}|(.)/', $IPv6, $matchesIP);\r
+               $index          = strpos($IPv6,'::');\r
+\r
+               if ($index === false) {\r
+                       // We need exactly the right number of groups\r
+                       if ($groupCount !== $groupMax)                          return $diagnose ? ISEMAIL_IPV6GROUPCOUNT       : false;        // RFC5321 section 4.1.3\r
+               } else {\r
+                       if ($index !== strrpos($IPv6,'::'))                     return $diagnose ? ISEMAIL_IPV6DOUBLEDOUBLECOLON : false;       // More than one '::'\r
+                       $groupMax = ($index === 0 || $index === (strlen($IPv6) - 2)) ? $groupMax : $groupMax - 1;\r
+                       if ($groupCount > $groupMax)                            return $diagnose ? ISEMAIL_IPV6TOOMANYGROUPS    : false;        // Too many IPv6 groups in address\r
+               }\r
+\r
+               // Check for unmatched characters\r
+               array_multisort($matchesIP[1], SORT_DESC);\r
+               if ($matchesIP[1][0] !== '')                                    return $diagnose ? ISEMAIL_IPV6BADCHAR          : false;        // Illegal characters in address\r
+\r
+               // It's a valid IPv6 address, so...\r
+               return $diagnose ? ISEMAIL_VALID : true;\r
+       } else {\r
+               // It's a domain name...\r
+\r
+               // The syntax of a legal Internet host name was specified in RFC-952\r
+               // One aspect of host name syntax is hereby changed: the\r
+               // restriction on the first character is relaxed to allow either a\r
+               // letter or a digit.\r
+               //      (http://tools.ietf.org/html/rfc1123#section-2.1)\r
+               //\r
+               // NB RFC 1123 updates RFC 1035, but this is not currently apparent from reading RFC 1035.\r
+               //\r
+               // Most common applications, including email and the Web, will generally not\r
+               // permit...escaped strings\r
+               //      (http://tools.ietf.org/html/rfc3696#section-2)\r
+               //\r
+               // the better strategy has now become to make the "at least one period" test,\r
+               // to verify LDH conformance (including verification that the apparent TLD name\r
+               // is not all-numeric)\r
+               //      (http://tools.ietf.org/html/rfc3696#section-2)\r
+               //\r
+               // Characters outside the set of alphabetic characters, digits, and hyphen MUST NOT appear in domain name\r
+               // labels for SMTP clients or servers\r
+               //      (http://tools.ietf.org/html/rfc5321#section-4.1.2)\r
+               //\r
+               // RFC5321 precludes the use of a trailing dot in a domain name for SMTP purposes\r
+               //      (http://tools.ietf.org/html/rfc5321#section-4.1.2)\r
+               $dotArray       = /*. (array[int]string) .*/ preg_split('/\\.(?=(?:[^\\"]*\\"[^\\"]*\\")*(?![^\\"]*\\"))/m', $domain);\r
+               $partLength     = 0;\r
+               $element        = ''; // Since we use $element after the foreach loop let's make sure it has a value\r
+// revision 1.13: Line above added because PHPLint now checks for Definitely Assigned Variables\r
+\r
+               if (count($dotArray) === 1)                                     return $diagnose ? ISEMAIL_TLD  : false;        // Mail host can't be a TLD (cite? What about localhost?)\r
+\r
+               foreach ($dotArray as $element) {\r
+                       // Remove any leading or trailing FWS\r
+                       $element        = preg_replace("/^$FWS|$FWS\$/", '', $element);\r
+                       $elementLength  = strlen($element);\r
+       \r
+                       // Each dot-delimited component must be of type atext\r
+                       // A zero-length element implies a period at the beginning or end of the\r
+                       // local part, or two periods together. Either way it's not allowed.\r
+                       if ($elementLength === 0)                               return $diagnose ? ISEMAIL_DOMAINEMPTYELEMENT   : false;        // Dots in wrong place\r
+// revision 1.15: Speed up the test and get rid of "unitialized string offset" notices from PHP\r
+       \r
+                       // Then we need to remove all valid comments (i.e. those at the start or end of the element\r
+                       if ($element[0] === '(') {\r
+                               $indexBrace = strpos($element, ')');\r
+                               if ($indexBrace !== false) {\r
+                                       if (preg_match('/(?<!\\\\)[\\(\\)]/', substr($element, 1, $indexBrace - 1)) > 0) {\r
+                                                                               return $diagnose ? ISEMAIL_BADCOMMENTSTART      : false;        // Illegal characters in comment\r
+                                       }\r
+                                       $element        = substr($element, $indexBrace + 1, $elementLength - $indexBrace - 1);\r
+                                       $elementLength  = strlen($element);\r
+                               }\r
+                       }\r
+                       \r
+                       if ($element[$elementLength - 1] === ')') {\r
+                               $indexBrace = strrpos($element, '(');\r
+                               if ($indexBrace !== false) {\r
+                                       if (preg_match('/(?<!\\\\)(?:[\\(\\)])/', substr($element, $indexBrace + 1, $elementLength - $indexBrace - 2)) > 0)\r
+                                                                               return $diagnose ? ISEMAIL_BADCOMMENTEND        : false;        // Illegal characters in comment\r
+\r
+                                       $element        = substr($element, 0, $indexBrace);\r
+                                       $elementLength  = strlen($element);\r
+                               }\r
+                       }                       \r
+       \r
+                       // Remove any leading or trailing FWS around the element (inside any comments)\r
+                       $element = preg_replace("/^$FWS|$FWS\$/", '', $element);\r
+       \r
+                       // What's left counts towards the maximum length for this part\r
+                       if ($partLength > 0) $partLength++;     // for the dot\r
+                       $partLength += strlen($element);\r
+       \r
+                       // The DNS defines domain name syntax very generally -- a\r
+                       // string of labels each containing up to 63 8-bit octets,\r
+                       // separated by dots, and with a maximum total of 255\r
+                       // octets.\r
+                       //      (http://tools.ietf.org/html/rfc1123#section-6.1.3.5)\r
+                       if ($elementLength > 63)                                return $diagnose ? ISEMAIL_DOMAINELEMENTTOOLONG : false;        // Label must be 63 characters or less\r
+       \r
+                       // Any ASCII graphic (printing) character other than the\r
+                       // at-sign ("@"), backslash, double quote, comma, or square brackets may\r
+                       // appear without quoting.  If any of that list of excluded characters\r
+                       // are to appear, they must be quoted\r
+                       //      (http://tools.ietf.org/html/rfc3696#section-3)\r
+                       //\r
+                       // If the hyphen is used, it is not permitted to appear at\r
+                       // either the beginning or end of a label.\r
+                       //      (http://tools.ietf.org/html/rfc3696#section-2)\r
+                       //\r
+                       // Any excluded characters? i.e. 0x00-0x20, (, ), <, >, [, ], :, ;, @, \, comma, period, "\r
+                       if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]|^-|-$/', $element) > 0) {\r
+                                                                               return $diagnose ? ISEMAIL_DOMAINBADCHAR        : false;\r
+                       }\r
+               }\r
+\r
+               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)\r
+\r
+               if (preg_match('/^[0-9]+$/', $element) > 0)                     return $diagnose ? ISEMAIL_TLDNUMERIC           : false;        // TLD can't be all-numeric (http://www.apps.ietf.org/rfc/rfc3696.html#sec-2)\r
+\r
+               // Check DNS?\r
+               if ($checkDNS && function_exists('checkdnsrr')) {\r
+                       if (!(checkdnsrr($domain, 'A') || checkdnsrr($domain, 'MX'))) {\r
+                                                                               return $diagnose ? ISEMAIL_DOMAINNOTFOUND       : false;        // Domain doesn't actually exist\r
+                       }\r
+               }\r
+       }\r
+\r
+       // Eliminate all other factors, and the one which remains must be the truth.\r
+       //      (Sherlock Holmes, The Sign of Four)\r
+       return $diagnose ? ISEMAIL_VALID : true;\r
+}\r
+?>\r