diff --git a/core/includes/common.inc b/core/includes/common.inc
index 9c65647..9e97d00 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -6927,6 +6927,9 @@ function drupal_common_theme() {
     'tel' => array(
       'render element' => 'element',
     ),
+    'email' => array(
+      'render element' => 'element',
+    ),
     'form' => array(
       'render element' => 'element',
     ),
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 85bffc6..c43365e 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -3703,8 +3703,48 @@ function theme_textfield($variables) {
   element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder'));
   _form_set_class($element, array('form-text'));
 
+  $extra = form_add_autocomplete($element);
+  $output = '<input' . drupal_attributes($element['#attributes']) . ' />';
+
+  return $output . $extra;
+}
+
+/**
+ * Returns HTML for an email form element.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: An associative array containing the properties of the element.
+ *     Properties used: #title, #value, #description, #size, #maxlength,
+ *     #placeholder, #required, #attributes, #autocomplete_path.
+ *
+ * @ingroup themeable
+ */
+function theme_email($variables) {
+  $element = $variables['element'];
+  element_set_attributes($element, array('type', 'id', 'name', 'value', 'size', 'maxlength', 'placeholder'));
+  _form_set_class($element, array('form-text', 'form-email'));
+
+  $extra = form_add_autocomplete($element);
+  $output = '<input' . drupal_attributes($element['#attributes']) . ' />';
+
+  return $output . $extra;
+}
+
+/**
+ * Return the autocompletion HTML for a form element.
+ *
+ * @param $element
+ *   The renderable element to process for autocompletion.
+ *
+ * @return
+ *   The rendered autocompletion element HTML, or an empty string if the field
+ *   has no autocompletion enabled.
+ */
+function form_add_autocomplete(&$element) {
   $extra = '';
-  if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) {
+
+  if (!empty($element['#autocomplete_path']) && drupal_valid_path($element['#autocomplete_path'])) {
     drupal_add_library('system', 'drupal.autocomplete');
     $element['#attributes']['class'][] = 'form-autocomplete';
 
@@ -3717,9 +3757,21 @@ function theme_textfield($variables) {
     $extra = '<input' . drupal_attributes($attributes) . ' />';
   }
 
-  $output = '<input' . drupal_attributes($element['#attributes']) . ' />';
+  return $extra;
+}
 
-  return $output . $extra;
+/**
+ * Form element validation handler for #type 'email'.
+ *
+ * Note that #maxlength and #required is validated by _form_validate() already.
+ */
+function form_validate_email(&$element, &$form_state) {
+  $value = trim($element['#value']);
+  form_set_value($element, $value, $form_state);
+
+  if ($value !== '' && !valid_email_address($value)) {
+    form_error($element, t('The e-mail address %mail is not valid.', array('%mail' => $value)));
+  }
 }
 
 /**
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index c21cd68..0b306d9 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1723,7 +1723,7 @@ function _install_configure_form($form, &$form_state, &$install_state) {
     '#weight' => -20,
   );
   $form['site_information']['site_mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => st('Site e-mail address'),
     '#default_value' => ini_get('sendmail_from'),
     '#description' => st("Automated e-mails, such as registration information, will be sent from this address. Use an address ending in your site's domain to help prevent these e-mails from being flagged as spam."),
@@ -1746,7 +1746,8 @@ function _install_configure_form($form, &$form_state, &$install_state) {
     '#attributes' => array('class' => array('username')),
   );
 
-  $form['admin_account']['account']['mail'] = array('#type' => 'textfield',
+  $form['admin_account']['account']['mail'] = array(
+    '#type' => 'email',
     '#title' => st('E-mail address'),
     '#maxlength' => EMAIL_MAX_LENGTH,
     '#required' => TRUE,
@@ -1825,12 +1826,6 @@ function install_configure_form_validate($form, &$form_state) {
   if ($error = user_validate_name($form_state['values']['account']['name'])) {
     form_error($form['admin_account']['account']['name'], $error);
   }
-  if ($error = user_validate_mail($form_state['values']['account']['mail'])) {
-    form_error($form['admin_account']['account']['mail'], $error);
-  }
-  if ($error = user_validate_mail($form_state['values']['site_mail'])) {
-    form_error($form['site_information']['site_mail'], $error);
-  }
 }
 
 /**
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 4acbe6d..66992a3 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1779,7 +1779,7 @@ function comment_form($form, &$form_state, $comment) {
 
   // Add author e-mail and homepage fields depending on the current user.
   $form['author']['mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('E-mail'),
     '#default_value' => $comment->mail,
     '#required' => (!$user->uid && $anonymous_contact == COMMENT_ANONYMOUS_MUST_CONTACT),
@@ -1977,9 +1977,6 @@ function comment_form_validate($form, &$form_state) {
       }
     }
   }
-  if ($form_state['values']['mail'] && !valid_email_address($form_state['values']['mail'])) {
-    form_set_error('mail', t('The e-mail address you specified is not valid.'));
-  }
   if ($form_state['values']['homepage'] && !valid_url($form_state['values']['homepage'], TRUE)) {
     form_set_error('homepage', t('The URL of your homepage is not valid. Remember that it must be fully qualified, i.e. of the form <code>http://example.com/directory</code>.'));
   }
diff --git a/core/modules/contact/contact.pages.inc b/core/modules/contact/contact.pages.inc
index a2927be..57b56e6 100644
--- a/core/modules/contact/contact.pages.inc
+++ b/core/modules/contact/contact.pages.inc
@@ -73,7 +73,7 @@ function contact_site_form($form, &$form_state) {
     '#required' => TRUE,
   );
   $form['mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('Your e-mail address'),
     '#maxlength' => 255,
     '#default_value' => $user->uid ? $user->mail : '',
@@ -123,9 +123,6 @@ function contact_site_form_validate($form, &$form_state) {
   if (!$form_state['values']['cid']) {
     form_set_error('cid', t('You must select a valid category.'));
   }
-  if (!valid_email_address($form_state['values']['mail'])) {
-    form_set_error('mail', t('You must enter a valid e-mail address.'));
-  }
 }
 
 /**
@@ -215,7 +212,7 @@ function contact_personal_form($form, &$form_state, $recipient) {
     '#required' => TRUE,
   );
   $form['mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('Your e-mail address'),
     '#maxlength' => 255,
     '#default_value' => $user->uid ? $user->mail : '',
@@ -254,17 +251,6 @@ function contact_personal_form($form, &$form_state, $recipient) {
 }
 
 /**
- * Form validation handler for contact_personal_form().
- *
- * @see contact_personal_form_submit()
- */
-function contact_personal_form_validate($form, &$form_state) {
-  if (!valid_email_address($form_state['values']['mail'])) {
-    form_set_error('mail', t('You must enter a valid e-mail address.'));
-  }
-}
-
-/**
  * Form submission handler for contact_personal_form().
  *
  * @see contact_personal_form_validate()
diff --git a/core/modules/contact/contact.test b/core/modules/contact/contact.test
index 48c8bb0..d7f26ac 100644
--- a/core/modules/contact/contact.test
+++ b/core/modules/contact/contact.test
@@ -126,7 +126,7 @@ class ContactSitewideTestCase extends DrupalWebTestCase {
     $this->assertText(t('Your e-mail address field is required.'), t('E-mail required.'));
 
     $this->submitContact($this->randomName(16), $invalid_recipients[0], $this->randomName(16), $categories[0], $this->randomName(64));
-    $this->assertText(t('You must enter a valid e-mail address.'), t('Valid e-mail required.'));
+    $this->assertRaw(t('The e-mail address %mail is not valid.', array('%mail' => 'invalid')), 'Valid e-mail required.');
 
     $this->submitContact($this->randomName(16), $recipients[0], '', $categories[0], $this->randomName(64));
     $this->assertText(t('Subject field is required.'), t('Subject required.'));
diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php
index c9fc562..af7ef6e 100644
--- a/core/modules/simpletest/drupal_web_test_case.php
+++ b/core/modules/simpletest/drupal_web_test_case.php
@@ -2245,6 +2245,7 @@ class DrupalWebTestCase extends DrupalTestCase {
           case 'textarea':
           case 'hidden':
           case 'password':
+          case 'email':
             $post[$name] = $edit[$name];
             unset($edit[$name]);
             break;
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index d28ecfb..1c865a6 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -1477,7 +1477,7 @@ function system_site_information_settings() {
     '#description' => t("How this is used depends on your site's theme."),
   );
   $form['site_information']['site_mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('E-mail address'),
     '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
     '#description' => t("The <em>From</em> address in automated e-mails sent during registration and new password requests, and other notifications. (Use an address ending in your site's domain to help prevent this e-mail being flagged as spam.)"),
@@ -1532,10 +1532,6 @@ function system_site_information_settings() {
  * Validates the submitted site-information form.
  */
 function system_site_information_settings_validate($form, &$form_state) {
-  // Validate the e-mail address.
-  if ($error = user_validate_mail($form_state['values']['site_mail'])) {
-    form_set_error('site_mail', $error);
-  }
   // Check for empty front page path.
   if (empty($form_state['values']['site_frontpage'])) {
     // Set to default "user".
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 332e559..473377d 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -374,6 +374,16 @@ function system_element_info() {
     '#theme' => 'tel',
     '#theme_wrappers' => array('form_element'),
   );
+  $types['email'] = array(
+    '#input' => TRUE,
+    '#size' => 60,
+    '#maxlength' => 128,
+    '#autocomplete_path' => FALSE,
+    '#process' => array('ajax_process_form'),
+    '#element_validate' => array('form_validate_email'),
+    '#theme' => 'email',
+    '#theme_wrappers' => array('form_element'),
+  );
   $types['machine_name'] = array(
     '#input' => TRUE,
     '#default_value' => NULL,
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 928daad..84987ec 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -607,28 +607,6 @@ function user_validate_name($name) {
 }
 
 /**
- * Validates a user's email address.
- *
- * Checks that a user's email address exists and follows all standard
- * validation rules. Returns error messages when the address is invalid.
- *
- * @param $mail
- *   A user's email address.
- *
- * @return
- *   If the address is invalid, a human-readable error message is returned.
- *   If the address is valid, nothing is returned.
- */
-function user_validate_mail($mail) {
-  if (!$mail) {
-    return t('You must enter an e-mail address.');
-  }
-  if (!valid_email_address($mail)) {
-    return t('The e-mail address %mail is not valid.', array('%mail' => $mail));
-  }
-}
-
-/**
  * Validates an image uploaded by a user.
  *
  * @see user_account_form()
@@ -963,7 +941,7 @@ function user_account_form(&$form, &$form_state) {
   );
 
   $form['account']['mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('E-mail address'),
     '#maxlength' => EMAIL_MAX_LENGTH,
     '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
@@ -1150,19 +1128,14 @@ function user_account_form_validate($form, &$form_state) {
   // Trim whitespace from mail, to prevent confusing 'e-mail not valid'
   // warnings often caused by cutting and pasting.
   $mail = trim($form_state['values']['mail']);
-  form_set_value($form['account']['mail'], $mail, $form_state);
 
-  // Validate the e-mail address, and check if it is taken by an existing user.
-  if ($error = user_validate_mail($form_state['values']['mail'])) {
-    form_set_error('mail', $error);
-  }
-  elseif ((bool) db_select('users')->fields('users', array('uid'))->condition('uid', $account->uid, '<>')->condition('mail', db_like($form_state['values']['mail']), 'LIKE')->range(0, 1)->execute()->fetchField()) {
+  if ((bool) db_select('users')->fields('users', array('uid'))->condition('uid', $account->uid, '<>')->condition('mail', db_like($mail), 'LIKE')->range(0, 1)->execute()->fetchField()) {
     // Format error message dependent on whether the user is logged in or not.
     if ($GLOBALS['user']->uid) {
-      form_set_error('mail', t('The e-mail address %email is already taken.', array('%email' => $form_state['values']['mail'])));
+      form_set_error('mail', t('The e-mail address %email is already taken.', array('%email' => $mail)));
     }
     else {
-      form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $form_state['values']['mail'], '@password' => url('user/password'))));
+      form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $mail, '@password' => url('user/password'))));
     }
   }
 
diff --git a/core/modules/user/user.test b/core/modules/user/user.test
index 367bf82..6a3aae2 100644
--- a/core/modules/user/user.test
+++ b/core/modules/user/user.test
@@ -292,20 +292,6 @@ class UserValidationTestCase extends DrupalWebTestCase {
       $this->$test($result, $description . ' (' . $name . ')');
     }
   }
-
-  // Mail validation. More extensive tests can be found at common.test
-  function testMailAddresses() {
-    $test_cases = array( // '<username>' => array('<description>', 'assert<testName>'),
-      ''                => array('Empty mail address', 'assertNotNull'),
-      'foo'             => array('Invalid mail address', 'assertNotNull'),
-      'foo@example.com' => array('Valid mail address', 'assertNull'),
-    );
-    foreach ($test_cases as $name => $test_case) {
-      list($description, $test) = $test_case;
-      $result = user_validate_mail($name);
-      $this->$test($result, $description . ' (' . $name . ')');
-    }
-  }
 }
 
 /**
