Problem/Motivation

We should introduce a setting to make the top-level domain optional for email validation. Currently, a lot of modules (e.g. https://www.drupal.org/project/commerce_paypal) require the email form_element, to validate whether a given email-address has a top-level domain set or not.
But as it stands, the email validation allows emails without a top-level domain. This is fine according to https://datatracker.ietf.org/doc/html/rfc5321#section-2.3.5, but in 99% of all uses cases the top level domain should be a required component of an email-address (intranets etc. being the exception).

Therefore, we should add a setting where this is configurable

Steps to reproduce

  1. Go to any form containing a form_element with an email field (type "email").
  2. Type in any email address without a top-level domain (e.g. "max.mustermann@test")
  3. Submit the form.
  4. No validation error appears.

Proposed resolution

Introduce a setting to make the top-level domain optional for email validation, and write an update hook enabling this setting for existing installations.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Comments

jnicola created an issue. See original summary.

oadaeh’s picture

Status: Active » Closed (works as designed)

What about user@localhost?

According to 2.3.5. Domain Names of RFC 5321 (which is referenced from 3.4.1. Addr-Spec Specification of RFC 5322):

A domain name (or often just a "domain") consists of one or more components, separated by dots if more than one appears. In the case of a top-level domain used by itself in an email address, a single string is used without any dots.

It may not be valid on the Internet, but it might still be a valid domain on an intranet or localhost, and therefore, should not be disallowed.

jnicola’s picture

Hmm, okay I suppose I hadn't considered the intranet bit.

Welp, looks like I won't be leveraging core on this email check then as it's not all that useful!

CatsFromStonehenge’s picture

This is the problem with validation of user inputs. Email validation is an age old classic. If we go 100% with the official specification, then it can be either too strict or too loose, depending on what we want.

In Oadaeh's case the email validator isn't useful. I wonder if we should allow some configuration of the built-in email validator? e.g. to allow intranet or not etc.

Here's an in-depth take on using regular expressions for email validation:
http://www.regular-expressions.info/email.html

CatsFromStonehenge’s picture

Check out the PHP function:filter_var($email, FILTER_VALIDATE_EMAIL)
https://secure.php.net/manual/en/filter.filters.validate.php

Regarding "partial" addresses with no . in the domain part, a comment in the source code (in ext/filter/logical_filters.c) justifies this rejection thus:

     * The regex below is based on a regex by Michael Rushton.
     * However, it is not identical.  I changed it to only consider routeable
     * addresses as valid.  Michael's regex considers a@b a valid address
     * which conflicts with section 2.3.5 of RFC 5321 which states that:
     *
     *   Only resolvable, fully-qualified domain names (FQDNs) are permitted
     *   when domain names are used in SMTP.  In other words, names that can
     *   be resolved to MX RRs or address (i.e., A or AAAA) RRs (as discussed
     *   in Section 5) are permitted, as are CNAME RRs whose targets can be
     *   resolved, in turn, to MX or address RRs.  Local nicknames or
     *   unqualified names MUST NOT be used.
cilefen’s picture

CatsFromStonehenge’s picture

Thanks @cilefen. That's good to know :)

dmezquia’s picture

Version: 8.2.1 » 10.0.x-dev

I fixed with custom code like this:

/**
 * Implements hook_element_info_alter().
 */
function my_module_element_info_alter(array &$types) {
  if (isset($types['email'])) {
    // Add custom email validation for domains.
    $types['email']['#element_validate'][] = [Myclass::class, 'validateEmail'];
  }
}
  /**
namespace Drupal\my_module\Myclass;

use Drupal\Core\Form\FormStateInterface;

   * Custom element validation handler for #type 'email'.
   *
   * Note that #maxlength and #required is validated by _form_validate() already.
   */
  public static function validateEmail(&$element, FormStateInterface $form_state, &$complete_form) {
    $value = trim($element['#value']);
    $form_state->setValueForElement($element, $value);

    if (empty($value)) {
      return;
    }

    if ($value !== '' && !\Drupal::service('email.validator')->isValid($value) || !filter_var($value, FILTER_VALIDATE_EMAIL)) {
      $form_state->setError($element, t('The email address %mail is not valid.', ['%mail' => $value]));
    }
  }
nigelcunningham’s picture

If you want the option of rejecting non routable addresses (fred@localhost), you want the patch in https://www.drupal.org/project/webform/issues/3173490, which optionally does additional checking on top of what the core validator does.

liquidcms’s picture

Curious why the default email validation fails: "Tom Smith" even though this is valid and the Drupal mail system supports this.

andreasderijcke’s picture

A new module to make this configurable: https://www.drupal.org/project/evac

magendiran’s picture

Thanks @dmezquia

cilefen’s picture

Title: Drupal email.validator service isValid accepts emails with no domain » Drupal email.validator service isValid accepts emails with no top-level domain (TLD)
grevil’s picture

@andreasderijcke great module, thanks for your work! 🎉

grevil’s picture

Title: Drupal email.validator service isValid accepts emails with no top-level domain (TLD) » Introduce a setting to make the top-level domain optional for email validation.
Version: 10.0.x-dev » 11.x-dev
Issue summary: View changes
Status: Closed (works as designed) » Active

IMO this issue should be reopened. Apart from https://www.drupal.org/project/commerce_paypal, there are / will be a lot of contrib modules, which require an e-mail adress to have a top-level-domain. And I don't think the modules itself should add this validation.

We should introduce a setting, to make the top-level domain optional for email validation. I adjusted the issue summary accordingly.

anybody’s picture

From my opiniton this would be a perfect example for a settings.php setting in core which can be overridden... but let's see what the others think.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.