提问人:Cameron 提问时间:8/19/2012 最后编辑:hakreCameron 更新时间:6/9/2023 访问量:393235
如何在PHP中验证电子邮件地址
How to validate an email address in PHP
问:
我有这个功能来验证电子邮件地址:
function validateEMAIL($EMAIL) {
$v = "/[a-zA-Z0-9_-.+]+@[a-zA-Z0-9-]+.[a-zA-Z]+/";
return (bool)preg_match($v, $EMAIL);
}
这可以检查电子邮件地址是否有效吗?
答:
检查电子邮件地址格式是否正确的最简单、最安全的方法是使用 filter_var()
函数:
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
// invalid emailaddress
}
此外,还可以检查域是否定义了记录:MX
if (!checkdnsrr($domain, 'MX')) {
// domain is not valid
}
但这仍然不能保证邮件存在。找出答案的唯一方法是发送确认邮件。
现在您已经有了简单的答案,如果您想学习,请随时阅读有关电子邮件地址验证的信息,或者以其他方式使用快速答案并继续前进。没有难受的感觉。
尝试使用正则表达式验证电子邮件地址是一项“不可能”的任务。我甚至会说你所做的正则表达式是无用的。关于电子邮件地址有三个 rfc,编写正则表达式来捕获错误的电子邮件地址,同时没有误报是凡人无法做到的。查看此列表,了解 PHP 函数使用的正则表达式的测试(失败和成功)。filter_var()
即使是内置的PHP函数,电子邮件客户端或服务器也无法正确处理。在大多数情况下仍然是最好的选择。filter_var
如果您想知道 PHP(当前)使用哪种正则表达式模式来验证电子邮件地址,请参阅 PHP 源代码。
如果您想了解有关电子邮件地址的更多信息,我建议您开始阅读规范,但我必须警告您,这绝非易事:
评论
filter_var
我认为你最好使用 PHP 的内置过滤器 - 在这种特殊情况下:
当提供参数时,它可以返回 true 或 false。FILTER_VALIDATE_EMAIL
为此,您可以使用filter_var。
<?php
function validateEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
?>
评论
address
在关于电子邮件验证 https://stackoverflow.com/a/41129750/1848217 的“首要问题”中回答了这个问题
对我来说,检查电子邮件的正确方法是:
- 检查符号 @ 是否存在,在它之前和之后有一些非 @ 符号:
/^[^@]+@[^@]+$/
- 尝试向此地址发送带有一些“激活码”的电子邮件。
- 当用户“激活”他的电子邮件地址时,我们将看到一切正常。
当然,当用户 输入“奇怪”的电子邮件,以帮助他避免常见的错误,比如没有 域中的点、部分或名称中的空格,不带引号等。但 如果用户确实需要地址“hello@world”,则必须接受它。
此外,您必须记住电子邮件地址标准过去和现在都可以 evolute,所以你不能只输入一些“标准有效”的正则表达式一次,然后 永远。你必须记住,一些具体的互联网 服务器可能会使通用标准的某些细节失败,但实际上可以与 自己的“修改标准”。
因此,只需检查@,在前端提示用户并在给定地址上发送验证电子邮件即可。
评论
@
/^[^@]+@[^@+]$/
/^[^@]+@[^@]+$/
filter_var
joe@domain
filter_var($email, FILTER_VALIDATE_EMAIL, $newOptions)
如果您只是在寻找一个允许各种点、下划线和破折号的实际正则表达式,如下所示: .这将允许验证一个看起来相当愚蠢的电子邮件。[a-zA-z0-9.-]+\@[a-zA-z0-9.-]+.[a-zA-Z]+
tom_anderson.1-neo@my-mail_matrix.com
根据我的经验,解决方案有太多的误报,解决方案有漏报(尤其是所有较新的 TLD)。regex
filter_var()
相反,最好确保该地址具有电子邮件地址的所有必需部分(用户、“@”符号和域),然后验证域本身是否存在。
无法确定(服务器端)外部域是否存在电子邮件用户。
这是我在 Utility 类中创建的方法:
public static function validateEmail(string $email): bool {
// SET INITIAL RETURN VARIABLE
// ENSURE -> EMAIL ISN'T EMPTY | AN @ SYMBOL IS PRESENT
$emailIsValid = FALSE;
if (
!empty($email) &&
strpos($email, '@') !== FALSE
) {
// GET EMAIL PARTS
$email = explode('@', $email);
$user = $email[0];
$domain = $email[1];
// VALIDATE EMAIL ADDRESS
if (
count($email) === 2 &&
!empty($user) &&
!empty($domain) &&
checkdnsrr($domain)
) {
$emailIsValid = TRUE;
}
}
// RETURN RESULT
return $emailIsValid;
}
评论
stristr
如果有多个 @ 符号,将无法获取域。最好检查一下explode('@',$email)
sizeof($array)==2
checkdnsrr()
这不仅会验证您的电子邮件,还会清除意外字符:
$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);
}
评论
error`@gmail.com
`
/(?![[:alnum:]]|@|-|_|\.)./
如今,如果您使用 HTML5 表单,那么您已经安全了 80%,因为浏览器引擎有自己的验证器。为了补充它,将这个正则表达式添加到 ur 中并否定它:type=email
preg_match_all()
if (!preg_match_all("/(?![[:alnum:]]|@|-|_|\.)./",$email)) { .. }
查找HTML5表单用于验证
https://regex101.com/r/mPEKmy/1 的正则表达式
评论
如果要检查电子邮件地址提供的域是否有效,请使用以下内容:
/*
* 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 安装中不可用,它需要扩展 PECL intl >= 1.0.2 和 PECL idn >= 0.1。idn_to_ascii()
idn_to_utf8()
另请记住,IPv4 或 IPv6 作为电子邮件中的域部分(例如)无法验证,只有命名主机可以验证。user@[IPv6:2001:db8::1]
在此处查看更多内容。
评论
看完这里的答案后,这就是我最终得到的:
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;
}
评论
array_slice
explode("@", $email)[1]
使用以下代码:
// Variable to check
$email = "[email protected]";
// 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");
}
评论
FILTER_VALIDATE_EMAIL内置了一个更好的正则表达式,但任何正则表达式都可能产生不好的结果。
例如。。
// "not an email" is invalid so its false.
php > var_export(filter_var("not an email", FILTER_VALIDATE_EMAIL));
false
// "[email protected]" looks like an email, so it passes even though its not real.
php > var_export(filter_var("[email protected]", FILTER_VALIDATE_EMAIL));
'[email protected]'
// "[email protected]" passes, gmail is a valid email server,
// but gmail require more than 3 letters for the address.
var_export(filter_var("[email protected]", FILTER_VALIDATE_EMAIL));
'[email protected]'
您可能需要考虑使用像 Real Email 这样的 API,它可以进行深入的邮箱检查以检查电子邮件是否真实。
有点像..
$email = "[email protected]";
$api_key = ???;
$request_context = stream_context_create(array(
'http' => array(
'header' => "Authorization: Bearer " . $api_key
)
));
$result_json = file_get_contents("https://isitarealemail.com/api/email/validate?email=" . $email, false, $request_context);
if (json_decode($result_json, true)['status'] == "valid") {
echo("email is valid");
} else if (json_decode($result_json, true)['status'] == "invalid") {
echo("email is invalid");
} else {
echo("email was unknown");
}
有三个 RFC 为“Internet 消息格式”奠定了基础。
- RFC 822 (英语)
- RFC 2822(取代 RFC 822)
- RFC 5322(取代 RFC 2822)
但是,RFC 5322 以最技术性的方式定义了电子邮件 ID 及其命名结构。这更合适,奠定一个互联网标准的基础,这个标准足够自由,允许所有的用例,但又足够保守,可以用某种形式主义来约束它。
但是,来自软件开发人员社区的电子邮件验证要求具有以下需求:
- 避免不需要的垃圾邮件发送者
- 确保用户不会无意中犯错
- 确保电子邮件ID属于实际输入者
他们对实现一个技术上包罗万象的定义并不完全感兴趣,该定义允许电子邮件 ID 的所有形式(IP 地址,包括端口 ID 和所有)。适合其用例的解决方案应仅确保所有合法的电子邮件持有者都能够通过。从技术角度(RFC 5322 方式)到可用性角度(此解决方案),“合法”的定义差异很大。验证的可用性方面旨在确保通过验证机制验证的所有电子邮件 ID 都属于实际人员,并将它们用于通信目的。因此,这为验证过程引入了另一个角度,确保实际“正在使用”的电子邮件 ID,而 RFC-5322 定义显然不足以满足这一要求。
因此,在实践中,实际要求可以归结为以下几点——
- 确保一些非常基本的验证检查
- 确保输入的电子邮件正在使用中
第二个要求通常涉及,向输入的电子邮件 ID 发送寻求电子邮件的标准响应,并根据响应机制中描述的操作对用户进行身份验证。这是使用最广泛的机制,用于确保验证“正在使用”的电子邮件 ID 的第二个要求。这确实涉及从后端服务器实现的往返,而不是直接的单屏实现,但是,不能消除这一点。
第一个要求源于开发人员不希望完全“非电子邮件”字符串作为电子邮件传递的需要。这通常涉及空白、没有“@”符号或没有域名的字符串。鉴于域名的 punycode 表示形式,如果需要启用域验证,则需要进行全面的实施,以确保域名有效。因此,鉴于这方面需求的基本性质,验证“<something>@<something>.<something>”是满足要求的唯一合适方法。
可以满足此要求的典型正则表达式是: ^[^@\s]+@[^@\s.]+.[^@\s.]+$ 上面的正则表达式遵循标准的Perl正则表达式标准,被大多数编程语言广泛遵循。验证语句为: <除空格和“@”符号之外的任何内容>@<除空格和“@”符号之外的任何内容>.<除空格、@ 符号和点之外的任何内容>
对于那些想要更深入地了解更相关的实现的人,他们可以遵循以下验证方法。 <e-mail local part>@<domain name>
对于<电子邮件本地部分> - 遵循“普遍适用性指导小组”的指导方针 - UASG-026 对于<域名>,您可以使用标准库遵循任何域验证方法,具体取决于您的编程语言。有关该主题的最新研究,请遵循文档UASG-018A。
那些有兴趣了解在实施国际化电子邮件解决方案时可能遇到的整个过程、挑战和问题的人,他们也可以通过以下 RFC:
RFC 6530(国际化电子邮件概述和框架) RFC 6531(国际化电子邮件的 SMTP 扩展) RFC 6532(国际化电子邮件标头) RFC 6533(国际化交付状态和处置通知) RFC 6855(对 UTF-8 的 IMAP 支持) RFC 6856(邮局协议版本 3 (POP3) 对 UTF-8 的支持) RFC 6857(国际化电子邮件的传递后邮件降级) RFC 6858(简化国际化电子邮件的 POP 和 IMAP 降级)。
我准备了一个检查电子邮件有效性的函数:
function isValidEmail($email)
{
$re = '/([\w\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)/m';
preg_match_all($re, $email, $matches, PREG_SET_ORDER, 0);
if(count($matches) > 0) return $matches[0][0] === $email;
return false;
}
问题在于,它甚至认为无效的电子邮件是有效的。FILTER_VALIDATE_EMAIL
以下是示例:
if(isValidEmail("[email protected]")) echo "valid";
if(!isValidEmail("fo^[email protected]")) echo "invalid";
上一个:如何发送电子邮件附件?
下一个:mail链接到 HTML 正文
评论
validateEmail
$email
$EMAIL