如何在PHP中验证电子邮件地址

时间:2012-08-19 13:29:35

标签: php regex email email-validation

我有此功能来验证电子邮件地址:

function validateEMAIL($EMAIL) {
    $v = "/[a-zA-Z0-9_-.+]+@[a-zA-Z0-9-]+.[a-zA-Z]+/";

    return (bool)preg_match($v, $EMAIL);
}

是否可以检查电子邮件地址是否有效?

11 个答案:

答案 0 :(得分:515)

检查电子邮件地址是否格式正确的最简单,最安全的方法是使用filter_var()功能:

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    // invalid emailaddress
}

此外,您可以检查域是否定义了MX记录:

if (!checkdnsrr($domain, 'MX')) {
    // domain is not valid
}

但这仍不能保证邮件存在。找到答案的唯一方法是发送确认邮件。


现在您可以轻松回答有关电子邮件地址验证的问题,如果您需要学习或者只是使用快速答案并继续前进。别往心里放。

尝试使用正则表达式验证电子邮件地址是一项“不可能”的任务。我甚至会说你所制作的正则表达式毫无用处。有三个rfc关于emailaddresses和写一个正则表达式来捕捉错误的电子邮件,同时没有误报是没有凡人可以做的事情。查看this list以获取PHP filter_var()函数使用的正则表达式的测试(失败和成功)。

即使内置的PHP函数,电子邮件客户端或服务器也无法正常运行。在大多数情况下,filter_var仍是最佳选择。

如果您想知道PHP(当前)用于验证电子邮件地址的正则表达式模式,请参阅the PHP source

如果您想了解有关电子邮件地址的更多信息,我建议您开始阅读规范,但我必须警告您,这不是一个容易阅读的内容:

请注意filter_var()已经说明,仅在PHP 5.2中提供。如果您希望它与早期版本的PHP一起使用,您可以使用PHP中使用的正则表达式:

<?php

$pattern = '/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD';

$emailaddress = 'test@gmail.com';

if (preg_match($pattern, $emailaddress) === 1) {
    // emailaddress is valid
}

P.S。关于上面使用的正则表达式模式的注释(来自PHP源代码)。 Michael Rushton似乎有一些版权。如上所述:“请随意使用并重新分发此代码。但请保留此版权声明。”

答案 1 :(得分:37)

您可以使用filter_var

<?php
   function validateEmail($email) {
      return filter_var($email, FILTER_VALIDATE_EMAIL);
   }
?>

答案 2 :(得分:12)

根据我的经验,regex解决方案有太多误报,filter_var()解决方案有误报(特别是对于所有较新的TLDs)。

相反,最好确保地址包含电子邮件地址(用户,“@”符号和域)的所有必需部分,然后验证域本身是否存在。

无法确定(服务器端)是否存在外部域的电子邮件用户。

这是我在Utility类中创建的方法:

public static function validateEmail($email)
{
    // SET INITIAL RETURN VARIABLES

        $emailIsValid = FALSE;

    // MAKE SURE AN EMPTY STRING WASN'T PASSED

        if (!empty($email))
        {
            // GET EMAIL PARTS

                $domain = ltrim(stristr($email, '@'), '@') . '.';
                $user   = stristr($email, '@', TRUE);

            // VALIDATE EMAIL ADDRESS

                if
                (
                    !empty($user) &&
                    !empty($domain) &&
                    checkdnsrr($domain)
                )
                {$emailIsValid = TRUE;}
        }

    // RETURN RESULT

        return $emailIsValid;
}

答案 3 :(得分:9)

我认为你可能最好使用PHP的内置filters - 在这种特殊情况下:

当提供FILTER_VALIDATE_EMAIL参数时,它可以返回true或false。

答案 4 :(得分:7)

这不仅会验证您的电子邮件,还会针对意外字符对其进行清理:

$email  = $_POST['email'];
$emailB = filter_var($email, FILTER_SANITIZE_EMAIL);

if (filter_var($emailB, FILTER_VALIDATE_EMAIL) === false ||
    $emailB != $email
) {
    echo "This email adress isn't valid!";
    exit(0);
}

答案 5 :(得分:2)

在关于电子邮件验证的“热门问题”中回答了此问题https://stackoverflow.com/a/41129750/1848217

  

对我来说,检查电子邮件的正确方法是:

     
      
  1. 检查符号@是否存在,之前和之后有一些非@符号:/^[^@]+@[^@]+$/
  2.   
  3. 尝试使用一些“激活码”向此地址发送电子邮件。
  4.   
  5. 当用户“激活”他的电子邮件地址时,我们会发现一切正常。
  6.         

    当然,您可以在用户前端显示一些警告或工具提示   键入“奇怪”的电子邮件,以帮助他避免常见错误,如没有   域名部分中的点或名称中的空格,不带引号等。但   如果用户真的需要,你必须接受“hello @ world”地址。

         

    此外,您必须记住电子邮件地址标准是否可以   evolute,所以你不能只输入一些“标准有效”的正则表达式   一直以来。你必须记住一些具体的互联网   服务器可能会失败一些标准的细节,实际上可以使用   自己的“修改标准”。

所以,只需检查@,在前端提示用户,并在给定地址发送验证电子邮件。

答案 6 :(得分:1)

如果您只是寻找允许各种点,下划线和短划线的实际正则表达式,则如下所示:[a-zA-z0-9.-]+\@[a-zA-z0-9.-]+.[a-zA-Z]+。这将允许验证像tom_anderson.1-neo@my-mail_matrix.com这样相当愚蠢的电子邮件。

答案 7 :(得分:0)

export default async (req) => {
  const report = req.body.webAudits;
  const def = deferred();

  if(report.length > 0) {
    var reportList = [];
    for(const [reportIndex, item] of report.entries()) {
      for(const [runIndex, run] of item.runs.entries()) {
        const result = await waComplianceBusiness(req, run.id);
        var failureList = [];
        if(result.data.overviews) {
          const compliance = result.data.overviews[0].compliance;
          if(compliance) {
            for(const [index, rule] of compliance.entries()) {
              const response = await waRuleOverview(req, run.id, rule.id);
              const failedConditions = response.data.failedConditions;
              const ruleName = response.data.ruleName;

              if(response.data.pagesFailed > 0) {
                for(const [condIndex, condition] of failedConditions.entries()) {
                  const request = {
                    itemId: condition.conditionResult.id,
                    itemType: condition.conditionResult.idType,
                    parentId: condition.conditionResult.parentId,
                    parentType: condition.conditionResult.parentType
                  }
                  const body = {
                    runId: run.id,
                    ruleId: rule.id,
                    payload: request
                  }

                  waConditionOverview(req, body).done(response => {
                    // do stuff here
                  });
                }
              }
            }
            if(failureList.length > 0) {
              item.runs[runIndex].failures = failureList;
            }
          }
        }
      }
    }
    def.resolve(report);
    return def.promise
  }
  else {
    return [];
  }
}

如今,如果您使用带有/(?![[:alnum:]]|@|-|_|\.)./ 的HTML5表单,那么您已经有80%的安全性,因为浏览器引擎有自己的验证器。为了补充它,将此正则表达式添加到type=email并取消它:

preg_match_all()

Find the regex used by HTML5 forms for validation
https://regex101.com/r/mPEKmy/1

答案 8 :(得分:0)

如果您想检查提供的电子邮件地址是否有效,请使用以下内容:

/*
* Check for valid MX record for given email domain
*/
if(!function_exists('check_email_domain')){
    function check_email_domain($email) {
        //Get host name from email and check if it is valid
        $email_host = explode("@", $email);     
        //Add a dot to the end of the host name to make a fully qualified domain name and get last array element because an escaped @ is allowed in the local part (RFC 5322)
        $host = end($email_host) . "."; 
        //Convert to ascii (http://us.php.net/manual/en/function.idn-to-ascii.php)
        return checkdnsrr(idn_to_ascii($host), "MX"); //(bool)       
    }
}

这是过滤大量无效电子邮件地址以及标准电子邮件验证的便捷方式,因为有效的电子邮件格式并不代表有效的电子邮件

请注意,您的PHP安装中idn_to_ascii()(或其姐妹函数idn_to_utf8())函数可能不,它需要扩展PECL intl&gt; = 1.0.2和PECL idn> = 0.1。

另请注意,无法验证IPv4或IPv6作为电子邮件中的域部分(例如user@[IPv6:2001:db8::1]),只能命名主机。

查看更多here

答案 9 :(得分:0)

在这里阅读答案后,这就是我的结论:

public static function isValidEmail(string $email) : bool
{
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return false;
    }

    //Get host name from email and check if it is valid
    $email_host = array_slice(explode("@", $email), -1)[0];

    // Check if valid IP (v4 or v6). If it is we can't do a DNS lookup
    if (!filter_var($email_host,FILTER_VALIDATE_IP, [
        'flags' => FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE,
    ])) {
        //Add a dot to the end of the host name to make a fully qualified domain name
        // and get last array element because an escaped @ is allowed in the local part (RFC 5322)
        // Then convert to ascii (http://us.php.net/manual/en/function.idn-to-ascii.php)
        $email_host = idn_to_ascii($email_host.'.');

        //Check for MX pointers in DNS (if there are no MX pointers the domain cannot receive emails)
        if (!checkdnsrr($email_host, "MX")) {
            return false;
        }
    }

    return true;
}

答案 10 :(得分:0)

使用以下代码:

// Variable to check
$email = "john.doe@example.com";

// Remove all illegal characters from email
$email = filter_var($email, FILTER_SANITIZE_EMAIL);

// Validate e-mail
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
  echo("Email is a valid email address");
} else {
  echo("Oppps! Email is not a valid email address");
}