Index: wp-includes/formatting.php
===================================================================
--- wp-includes/formatting.php	(revision 10768)
+++ wp-includes/formatting.php	(working copy)
@@ -1293,24 +1293,77 @@
 }
 
 /**
- * Checks to see if the text is a valid email address.
+ * Verifies that an email is valid.
  *
+ * Does not grok i18n domains. Not RFC compliant.
+ *
  * @since 0.71
  *
- * @param string $user_email The email address to be checked.
- * @return bool Returns true if valid, otherwise false.
+ * @param string $email Email address to verify.
+ * @param boolean $check_dns Whether to check the DNS for the domain using checkdnsrr().
+ * @return string|bool Either false or the valid email address.
  */
-function is_email($user_email) {
-	$chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,6}\$/i";
-	if (strpos($user_email, '@') !== false && strpos($user_email, '.') !== false) {
-		if (preg_match($chars, $user_email)) {
-			return true;
-		} else {
-			return false;
+function is_email( $email, $check_dns = false )
+{
+	// Test for the minimum length the email can be
+	if ( strlen( $email ) < 3 ) {
+		return apply_filters( 'is_email', false, $email, 'email_too_short' );
+	}
+
+	// Test for an @ character after the first position
+	if ( strpos( $email, '@', 1 ) === false ) {
+		return apply_filters( 'is_email', false, $email, 'email_no_at' );
+	}
+
+	// Split out the local and domain parts
+	list( $local, $domain ) = explode( '@', $email, 2 );
+
+	// LOCAL PART
+	// Test for invalid characters
+	if ( !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) {
+		return apply_filters( 'is_email', false, $email, 'local_invalid_chars' );
+	}
+
+	// DOMAIN PART
+	// Test for sequences of periods
+	if ( preg_match( '/\.{2,}/', $domain ) ) {
+		return apply_filters( 'is_email', false, $email, 'domain_period_sequence' );
+	}
+
+	// Test for leading and trailing periods and whitespace
+	if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) {
+		return apply_filters( 'is_email', false, $email, 'domain_period_limits' );
+	}
+
+	// Split the domain into subs
+	$subs = explode( '.', $domain );
+
+	// Assume the domain will have at least two subs
+	if ( 2 > count( $subs ) ) {
+		return apply_filters( 'is_email', false, $email, 'domain_no_periods' );
+	}
+
+	// Loop through each sub
+	foreach ( $subs as $sub ) {
+		// Test for leading and trailing hyphens and whitespace
+		if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) {
+			return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );
 		}
-	} else {
-		return false;
+
+		// Test for invalid characters
+		if ( !preg_match('/^[a-z0-9-]+$/i', $sub ) ) {
+			return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' );
+		}
 	}
+
+	// DNS
+	// Check the domain has a valid MX and A resource record
+	if ( $check_dns && function_exists( 'checkdnsrr' ) && !( checkdnsrr( $domain . '.', 'MX' ) || checkdnsrr( $domain . '.', 'A' ) ) ) {
+		return apply_filters( 'is_email', false, $email, 'dns_no_rr' );
+	}
+
+	// Congratulations your email made it!
+	return apply_filters( 'is_email', $email, $email, null );
 }
 
 /**
@@ -1448,8 +1501,79 @@
  * @param string $email Email address to filter.
  * @return string Filtered email address.
  */
-function sanitize_email($email) {
-	return preg_replace('/[^a-z0-9+_.@-]/i', '', $email);
+function sanitize_email( $email )
+{
+	// Test for the minimum length the email can be
+	if ( strlen( $email ) < 3 ) {
+		return apply_filters( 'sanitize_email', '', $email, 'email_too_short' );
+	}
+
+	// Test for an @ character after the first position
+	if ( strpos( $email, '@', 1 ) === false ) {
+		return apply_filters( 'sanitize_email', '', $email, 'email_no_at' );
+	}
+
+	// Split out the local and domain parts
+	list( $local, $domain ) = explode( '@', $email, 2 );
+
+	// LOCAL PART
+	// Test for invalid characters
+	$local = preg_replace( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', '', $local );
+	if ( '' === $local ) {
+		return apply_filters( 'sanitize_email', '', $email, 'local_invalid_chars' );
+	}
+
+	// DOMAIN PART
+	// Test for sequences of periods
+	$domain = preg_replace( '/\.{2,}/', '', $domain );
+	if ( '' === $domain ) {
+		return apply_filters( 'sanitize_email', '', $email, 'domain_period_sequence' );
+	}
+
+	// Test for leading and trailing periods and whitespace
+	$domain = trim( $domain, " \t\n\r\0\x0B." );
+	if ( '' === $domain ) {
+		return apply_filters( 'sanitize_email', '', $email, 'domain_period_limits' );
+	}
+
+	// Split the domain into subs
+	$subs = explode( '.', $domain );
+
+	// Assume the domain will have at least two subs
+	if ( 2 > count( $subs ) ) {
+		return apply_filters( 'sanitize_email', '', $email, 'domain_no_periods' );
+	}
+
+	// Create an array that will contain valid subs
+	$new_subs = array();
+
+	// Loop through each sub
+	foreach ( $subs as $sub ) {
+		// Test for leading and trailing hyphens
+		$sub = trim( $sub, " \t\n\r\0\x0B-" );
+
+		// Test for invalid characters
+		$sub = preg_replace( '/^[^a-z0-9-]+$/i', '', $sub );
+
+		// If there's anything left, add it to the valid subs
+		if ( '' !== $sub ) {
+			$new_subs[] = $sub;
+		}
+	}
+
+	// If there aren't 2 or more valid subs
+	if ( 2 > count( $new_subs ) ) {
+		return apply_filters( 'sanitize_email', '', $email, 'domain_no_valid_subs' );
+	}
+
+	// Join valid subs into the new domain
+	$domain = join( '.', $new_subs );
+
+	// Put the email back together
+	$email = $local . '@' . $domain;
+
+	// Congratulations your email made it!
+	return apply_filters( 'sanitize_email', $email, $email, null );
 }
 
 /**
