3245 | | * Verifies that an email is valid. |
3246 | | * |
3247 | | * Does not grok i18n domains. Not RFC compliant. |
3248 | | * |
3249 | | * @since 0.71 |
3250 | | * |
3251 | | * @param string $email Email address to verify. |
3252 | | * @param bool $deprecated Deprecated. |
3253 | | * @return string|bool Either false or the valid email address. |
3254 | | */ |
| 3245 | * Verifies that an email is valid. |
| 3246 | * |
| 3247 | * @since 0.71 |
| 3248 | * |
| 3249 | * @param string $email Email address to verify. |
| 3250 | * @param bool $deprecated Deprecated. |
| 3251 | * @return string|bool Either false or the valid email address. |
| 3252 | */ |
3260 | | // Test for the minimum length the email can be |
3261 | | if ( strlen( $email ) < 6 ) { |
3262 | | /** |
3263 | | * Filters whether an email address is valid. |
3264 | | * |
3265 | | * This filter is evaluated under several different contexts, such as 'email_too_short', |
3266 | | * 'email_no_at', 'local_invalid_chars', 'domain_period_sequence', 'domain_period_limits', |
3267 | | * 'domain_no_periods', 'sub_hyphen_limits', 'sub_invalid_chars', or no specific context. |
3268 | | * |
3269 | | * @since 2.8.0 |
3270 | | * |
3271 | | * @param bool $is_email Whether the email address has passed the is_email() checks. Default false. |
3272 | | * @param string $email The email address being checked. |
3273 | | * @param string $context Context under which the email was tested. |
3274 | | */ |
3275 | | return apply_filters( 'is_email', false, $email, 'email_too_short' ); |
| 3258 | switch( true ) { |
| 3259 | case ( !is_email_basics( $email ) ) : |
| 3260 | return apply_filters( 'is_email', false, $email ); |
| 3261 | break; |
| 3262 | case ( is_email_rfc822( $email ) ) : |
| 3263 | break; |
| 3264 | case ( is_email_rfc2822( $email ) ) : |
| 3265 | break; |
| 3266 | default : |
| 3267 | return apply_filters( 'is_email', false, $email ); |
| 3268 | break; |
3278 | | // Test for an @ character after the first position |
3279 | | if ( strpos( $email, '@', 1 ) === false ) { |
3280 | | /** This filter is documented in wp-includes/formatting.php */ |
3281 | | return apply_filters( 'is_email', false, $email, 'email_no_at' ); |
3282 | | } |
| 3273 | /** |
| 3274 | * Verifies that email fits with basics. |
| 3275 | * |
| 3276 | * the format of an email address is : local-part@domain-part |
| 3277 | * the local part may be up to 64 characters long and the domain may have a maximum of 255 characters. |
| 3278 | * the domain part is a list of dot-separated DNS labels, each label being limited to a length of 63 characters |
| 3279 | * |
| 3280 | * @param string $email |
| 3281 | */ |
| 3282 | function is_email_basics( $email ) { |
| 3283 | $parts = explode( '@', $email ); |
3294 | | // DOMAIN PART |
3295 | | // Test for sequences of periods |
3296 | | if ( preg_match( '/\.{2,}/', $domain ) ) { |
3297 | | /** This filter is documented in wp-includes/formatting.php */ |
3298 | | return apply_filters( 'is_email', false, $email, 'domain_period_sequence' ); |
| 3292 | $dots = explode( '.', $domain_part ); |
| 3293 | foreach( $dots as $dot ) { |
| 3294 | if ( strlen( $dot ) > 63 ) return false; |
3301 | | // Test for leading and trailing periods and whitespace |
3302 | | if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) { |
3303 | | /** This filter is documented in wp-includes/formatting.php */ |
3304 | | return apply_filters( 'is_email', false, $email, 'domain_period_limits' ); |
3305 | | } |
| 3299 | /** |
| 3300 | * Validates whether the value is a valid e-mail address. |
| 3301 | * In general, this validates e-mail addresses against the syntax in RFC 822, |
| 3302 | * with the exceptions that comments and whitespace folding and dotless domain names are not supported. |
| 3303 | * [php.net] |
| 3304 | * |
| 3305 | * @param string $email |
| 3306 | */ |
| 3307 | function is_email_rfc822( $email ) { |
| 3308 | if ( ! defined( 'FILTER_VALIDATE_EMAIL' ) ) return false; |
| 3309 | if ( ! function_exists( 'filter_var' ) ) return false; |
| 3310 | return ( filter_var( $email, FILTER_VALIDATE_EMAIL ) ); |
| 3311 | } |
3307 | | // Split the domain into subs |
3308 | | $subs = explode( '.', $domain ); |
| 3313 | /** |
| 3314 | * Defines and applies the grammar to use for validation, implements the RFC 2822 (and friends) ABNF grammar definitions. |
| 3315 | * code from swiftmailer v5 https://github.com/swiftmailer/swiftmailer/tree/5.x |
| 3316 | * |
| 3317 | * @author Fabien Potencier |
| 3318 | * @author Chris Corbyn |
| 3319 | * |
| 3320 | * @param string $email |
| 3321 | */ |
| 3322 | function is_email_rfc2822( $email ) { |
| 3323 | return ( preg_match( '/^' . is_email_rfc2822_grammar() . '$/D', $email ) ); |
| 3324 | } |
3310 | | // Assume the domain will have at least two subs |
3311 | | if ( 2 > count( $subs ) ) { |
3312 | | /** This filter is documented in wp-includes/formatting.php */ |
3313 | | return apply_filters( 'is_email', false, $email, 'domain_no_periods' ); |
3314 | | } |
| 3326 | /** |
| 3327 | * Refer to RFC 2822 for ABNF grammar |
| 3328 | * code from swiftmailer v5 https://github.com/swiftmailer/swiftmailer/tree/5.x |
| 3329 | * |
| 3330 | * @author Fabien Potencier |
| 3331 | * @author Chris Corbyn |
| 3332 | * |
| 3333 | */ |
| 3334 | function is_email_rfc2822_grammar() { |
| 3335 | //All basic building blocks |
| 3336 | $g['NO-WS-CTL'] = '[\x01-\x08\x0B\x0C\x0E-\x19\x7F]'; |
| 3337 | $g['WSP'] = '[ \t]'; |
| 3338 | $g['CRLF'] = '(?:\r\n)'; |
| 3339 | $g['FWS'] = '(?:(?:' . $g['WSP'] . '*' . $g['CRLF'] . ')?' . $g['WSP'] . ')'; |
| 3340 | $g['text'] = '[\x00-\x08\x0B\x0C\x0E-\x7F]'; |
| 3341 | $g['quoted-pair'] = '(?:\\\\' . $g['text'] . ')'; |
| 3342 | $g['ctext'] = '(?:' . $g['NO-WS-CTL'] . '|[\x21-\x27\x2A-\x5B\x5D-\x7E])'; |
| 3343 | //Uses recursive PCRE (?1) -- |
| 3344 | $g['ccontent'] = '(?:' . $g['ctext'] . '|' . $g['quoted-pair'] . '|(?1))'; |
| 3345 | $g['comment'] = '(\((?:' . $g['FWS'] . '|' . $g['ccontent']. ')*' . $g['FWS'] . '?\))'; |
| 3346 | $g['CFWS'] = '(?:(?:' . $g['FWS'] . '?' . $g['comment'] . ')*(?:(?:' . $g['FWS'] . '?' . $g['comment'] . ')|' . $g['FWS'] . '))'; |
| 3347 | $g['qtext'] = '(?:' . $g['NO-WS-CTL'] . '|[\x21\x23-\x5B\x5D-\x7E])'; |
| 3348 | $g['qcontent'] = '(?:' . $g['qtext'] . '|' . $g['quoted-pair'] . ')'; |
| 3349 | $g['quoted-string'] = '(?:' . $g['CFWS'] . '?"' . '(' . $g['FWS'] . '?' . $g['qcontent'] . ')*' . $g['FWS'] . '?"' . $g['CFWS'] . '?)'; |
| 3350 | $g['atext'] = '[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]'; |
| 3351 | $g['atom'] = '(?:' . $g['CFWS'] . '?' . $g['atext'] . '+' . $g['CFWS'] . '?)'; |
| 3352 | $g['dot-atom-text'] = '(?:' . $g['atext'] . '+' . '(\.' . $g['atext'] . '+)*)'; |
| 3353 | $g['dot-atom'] = '(?:' . $g['CFWS'] . '?' . $g['dot-atom-text'] . '+' . $g['CFWS'] . '?)'; |
| 3354 | $g['word'] = '(?:' . $g['atom'] . '|' . $g['quoted-string'] . ')'; |
| 3355 | $g['phrase'] = '(?:' . $g['word'] . '+?)'; |
| 3356 | $g['no-fold-quote'] = '(?:"(?:' . $g['qtext'] . '|' . $g['quoted-pair'] . ')*")'; |
| 3357 | $g['dtext'] = '(?:' . $g['NO-WS-CTL'] . '|[\x21-\x5A\x5E-\x7E])'; |
| 3358 | $g['no-fold-literal'] = '(?:\[(?:' . $g['dtext'] . '|' . $g['quoted-pair'] . ')*\])'; |
| 3359 | //Message IDs |
| 3360 | $g['id-left'] = '(?:' . $g['dot-atom-text'] . '|' . $g['no-fold-quote'] . ')'; |
| 3361 | $g['id-right'] = '(?:' . $g['dot-atom-text'] . '|' . $g['no-fold-literal'] . ')'; |
| 3362 | //Addresses, mailboxes and paths |
| 3363 | $g['local-part'] = '(?:' . $g['dot-atom'] . '|' . $g['quoted-string'] . ')'; |
| 3364 | $g['dcontent'] = '(?:' . $g['dtext'] . '|' . $g['quoted-pair'] . ')'; |
| 3365 | $g['domain-literal'] = '(?:' . $g['CFWS'] . '?\[(' . $g['FWS'] . '?' . $g['dcontent'] . ')*?' . $g['FWS'] . '?\]' . $g['CFWS'] . '?)'; |
| 3366 | $g['domain'] = '(?:' . $g['dot-atom'] . '|' . $g['domain-literal'] . ')'; |
3316 | | // Loop through each sub |
3317 | | foreach ( $subs as $sub ) { |
3318 | | // Test for leading and trailing hyphens and whitespace |
3319 | | if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) { |
3320 | | /** This filter is documented in wp-includes/formatting.php */ |
3321 | | return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' ); |
3322 | | } |
3323 | | |
3324 | | // Test for invalid characters |
3325 | | if ( ! preg_match( '/^[a-z0-9-]+$/i', $sub ) ) { |
3326 | | /** This filter is documented in wp-includes/formatting.php */ |
3327 | | return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' ); |
3328 | | } |
3329 | | } |
3330 | | |
3331 | | // Congratulations your email made it! |
3332 | | /** This filter is documented in wp-includes/formatting.php */ |
3333 | | return apply_filters( 'is_email', $email, $email, null ); |
| 3368 | return '(?:' . $g['local-part'] . '@' . $g['domain'] . ')'; |