8.3.x common.inc valid_email_address($mail)
8.0.x common.inc valid_email_address($mail)
8.1.x common.inc valid_email_address($mail)
8.2.x common.inc valid_email_address($mail)
8.4.x common.inc valid_email_address($mail)
4.6.x common.inc valid_email_address($mail)
4.7.x common.inc valid_email_address($mail)
5.x common.inc valid_email_address($mail)
6.x common.inc valid_email_address($mail)
7.x common.inc valid_email_address($mail)

Verifies the syntax of the given e-mail address.

See RFC 5322 for details.

Parameters

$mail: A string containing an e-mail address.

Return value

1 if the email address is valid, 0 if it is invalid or empty, and FALSE if there is an input error (such as passing in an array instead of a string).

Related topics

7 calls to valid_email_address()
comment_validate in modules/comment/comment.module
Validate comment data.
contact_admin_edit_validate in modules/contact/contact.admin.inc
Validate the contact category edit page form submission.
contact_mail_page_validate in modules/contact/contact.pages.inc
Validate the site-wide contact page form submission.
contact_user_page in modules/contact/contact.pages.inc
Personal contact page.
system_send_email_action_validate in modules/system/system.module
Validate system_send_email_action form submissions.

... See full list

File

includes/common.inc, line 1026
Common functions that many Drupal modules will need to reference.

Code

function valid_email_address($mail) {
  $user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\']+';
  $domain = '(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.?)+';
  $ipv4 = '[0-9]{1,3}(\.[0-9]{1,3}){3}';
  $ipv6 = '[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7}';

  return preg_match("/^$user@($domain|(\[($ipv4|$ipv6)\]))$/", $mail);
}

Comments

Jztinfinity’s picture

There a couple special cases which this algorithm doesn't cover, one is a series of email addresses separated by commas, another is "Name <"+email address+">". In these two cases the email addresses need to be parsed out.

sean3z’s picture

I think that would be outside the scope of this function. You could easily pass addresses to this function to accomplish your specific needs.

$list = 'x@x.com,s@k,test@gmail.com,xx,fin@h.k.';
foreach(explode(',', $list) as $email) {
  echo $email, ( (valid_email_address($email)) ? ' good' : ' bad' ), '<br />';
}
ClaudeS’s picture

I agree with the first suggestion, that a recipient name should be allowed along with their email address.

This is a requirement for a client's website, where contact form messages are emailed to a specific address, which requires a specially-crafted recipient name for an automated process to work.

sastha’s picture

This function returns TRUE, even for email addresses without the domain extension.

For example, info@somedomain returns TRUE which is actually a invalid email address.

The validation doesn't cover .com .net .org extensions!

ulethjay’s picture

couldn't info@somedomain be valid if drupal is deployed for use on an intranet?

firebus’s picture

info@somedomain is a valid email address from a syntax perspective. the fact that 'somedomain' cannot be a public domain name with a DNS entry notwithstanding :)

i agree that it would be nice for this function to go a little beyond the RFC

Taiger’s picture

info@somedomain should not be valid for the reason you pointed out, it cannot be a public domain.

Proof:
filter_var(info@somedomain, FILTER_VALIDATE_EMAIL) returns false.

This should be considered a bug.

ionmedia’s picture

we need more complex stuff here

check it http://code.google.com/p/php-smtp-email-validation/

Taiger’s picture

If you are using a PHP version more than or equal to 5.2.0 you can use the native filter_var function to validate email:
http://www.php.net/manual/en/function.filter-var.php

You can also use filter_var for URLs and other things:
http://www.php.net/manual/en/filter.filters.validate.php

Here is an use example:

<?php
$good = 'test@good.com';
$bad = 'test@badcom';

if(filter_var($good, FILTER_VALIDATE_EMAIL)) {
echo 'good';
}
else {
  echo 'bad';
}
?>
DaPooch’s picture

There has been discussion of this ad-nauseum and I'm not sure it's been resolved to everyone's satisfaction even for Drupal 8 yet. IMHO the vast majority of users need this function to validate for use on the inTERnet meaning a TLD should be required for a valid domain. I'm honestly amazed at how many people have honestly forgotten to add that part to their email when registering on my Drupal sites and it's in turn caused a lot of headaches. When an invalid email is allowed through during the registration process the password reset is effectively negated since they inevitably try to reset when they forget their login and then the mailserver can't get the reset email to them since their email is bad.

While an email without a TLD part may be syntactically valid, it's follwing the letter of the law and not the practical purpose of it. If it's honestly that important for some users to allow emails without a TLD part then the validator needs to be re-written to allow for either A. the option of globally allowing non TLD emails as a NON DEFAULT option, or B. An admin configuration section that allows users to declare valid domains that can then be added to the regex/filter in the function. Admittedly though those users are the exception and not the rule and the default config needs to tailor to the majority not the minority if the decision is to support one or the other.

brycefisherfleig’s picture

This comment is the most insightful in the thread. The other way of handling this is check either the domain or the whole email address by initiating an SMTP connection, after checking against the official RFC5322.

neduko’s picture

You could try the following regular expression for single line to validate the email.

^[a-zA-z0-9\.\+\~\"(.)*\"\!\#\$\%\&\'\/\=\?\^_\{\}\|]+(@){1}(([a-zA-z0-9\-]+\.{1}[a-zA-z0-9\-]+(\.{1}[a-zA-z0-9]+)*)|([0-9]{1,3}(\.{1}[0-9]{1,3}){3})|([0-9a-fA-F]{1,4}(\:{1}[0-9a-fA-F]{1,4}){7}))[^_]$

The underscore is added at the end, because the regular expression above still validates the email address as valid when you add an underscore at the end.

seannhenderson’s picture

Check the RFC. No TLD required for an email address to be valid.

Also interesting to note that the domain part is case-insensitve, while the local part IS case-sensitive. Typically, case sensitivity on the local part is not enforced, but some mail servers may still enforce it by default or as a limitation on the system they reside.