我有这个功能来验证电子邮件地址:
function validateEMAIL($EMAIL) {
$v = "/[a-zA-Z0-9_-.+]+@[a-zA-Z0-9-]+.[a-zA-Z]+/";
return (bool)preg_match($v, $EMAIL);
}
这可以检查电子邮件地址是否有效吗?
validateEmail
是正确的,并且通过了 $email
,而不是 $EMAIL
。
检查电子邮件地址是否格式正确的最简单、最安全的方法是使用 filter_var()
函数:
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
// invalid emailaddress
}
此外,您可以检查域是否定义了 MX
记录:
if (!checkdnsrr($domain, 'MX')) {
// domain is not valid
}
但这仍然不能保证邮件存在。找出这一点的唯一方法是发送确认邮件。
现在您有了简单的答案,如果您想学习或只是使用快速答案并继续前进,请随时阅读有关电子邮件地址验证的信息。别往心里放。
尝试使用正则表达式验证电子邮件地址是一项“不可能”的任务。我什至会说你所做的那个正则表达式是没用的。有三个关于电子邮件地址的 rfc 和编写正则表达式来捕获错误的电子邮件地址,同时没有误报是凡人无法做到的。查看 this list 以了解 PHP 的 filter_var()
函数使用的正则表达式的测试(失败和成功)。
即使是内置的 PHP 函数、电子邮件客户端或服务器也无法正确处理。在大多数情况下,filter_var
仍然是最佳选择。
如果您想知道 PHP(当前)使用哪种正则表达式模式来验证电子邮件地址,请参阅 the PHP source。
如果您想了解有关电子邮件地址的更多信息,我建议您开始阅读规范,但我必须警告您,这无论如何都不容易阅读:
RFC5322
RFC5321
RFC3696
rfc6531(允许 unicode 字符,尽管许多客户端/服务器不接受它)
为此,您可以使用 filter_var。
<?php
function validateEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
?>
address
在您的网络中已知时,才能访问 some@address。要验证可达性,您可以检查 DNS(检查主机是否存在)或使用 SMTP(检查邮箱是否存在)。
根据我的经验,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;
}
stristr
将无法获取域。最好是 explode('@',$email)
并检查 sizeof($array)==2
checkdnsrr()
将返回 false。
这不仅会验证您的电子邮件,还会对意外字符进行清理:
$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
是有效的电子邮件。请注意,它包含 `
。
在这里阅读答案后,这就是我最终得到的结果:
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 = "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");
}
在关于电子邮件验证的“热门问题”中回答了这个问题https://stackoverflow.com/a/41129750/1848217
对我来说检查电子邮件的正确方法是:检查符号@是否存在,并且在它之前和之后有一些非@符号: /^[^@]+@[^@]+$/ 尝试发送电子邮件至这个地址带有一些“激活码”。当用户“激活”他的电子邮件地址时,我们会看到一切正常。当然,当用户输入“奇怪”的电子邮件时,您可以在前端显示一些警告或工具提示,以帮助他避免常见错误,例如域部分没有点或名称中有空格而没有引用等等。但是如果用户真的想要它,你必须接受地址“hello@world”。此外,您必须记住,电子邮件地址标准曾经并且可以不断发展,因此您不能只输入一些“标准有效”的正则表达式,一劳永逸。而且您必须记住,一些具体的互联网服务器可能无法满足通用标准的某些细节,实际上可以使用自己的“修改后的标准”。
因此,只需检查@,在前端提示用户并在给定地址发送验证电子邮件。
@
,但它并没有真正检查它对于管理电子邮件的任何 RFC 是否有效。它也不能像写的那样工作。我通过 regex101.com 运行它,但它无法匹配有效地址
/^[^@]+@[^@+]$/
修复为 /^[^@]+@[^@]+$/
filter_var
方法相比,它如何改进?它也不能解决它接受格式错误的地址的问题。您的正则表达式会很乐意接受 joe@domain
作为有效的电子邮件地址,如果它不是
filter_var($email, FILTER_VALIDATE_EMAIL, $newOptions)
。但是您在服务器上有旧功能,在某些情况下您无法更新。你会用一些新的有效电子邮件失去客户。此外,我再次注意到,并非所有电子邮件服务服务器都严格按照电子邮件地址的通用和现代标准工作。
如果您想检查电子邮件地址提供的域是否有效,请使用以下内容:
/*
* 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)
}
}
这是过滤大量无效电子邮件地址以及标准电子邮件验证的便捷方法,因为有效的电子邮件格式并不意味着有效的电子邮件。
请注意,idn_to_ascii()
(或他的姐妹函数 idn_to_utf8()
)函数可能在您的 PHP 安装中不可用,它需要扩展 PECL intl >= 1.0.2 和 PECL idn >= 0.1。
另请注意,无法验证 IPv4 或 IPv6 作为电子邮件中的域部分(例如 user@[IPv6:2001:db8::1]
),只有 named 主机可以。
查看更多here。
如果您只是在寻找一个允许各种点、下划线和破折号的实际正则表达式,如下所示:[a-zA-z0-9.-]+\@[a-zA-z0-9.-]+.[a-zA-Z]+
。这将允许验证像 tom_anderson.1-neo@my-mail_matrix.com
这样看起来相当愚蠢的电子邮件。
/(?![[:alnum:]]|@|-|_|\.)./
如今,如果您使用带有 type=email
的 HTML5 表单,那么您已经安全了 80%,因为浏览器引擎有自己的验证器。为了补充它,将此正则表达式添加到您的 preg_match_all()
并否定它:
if (!preg_match_all("/(?![[:alnum:]]|@|-|_|\.)./",$email)) { .. }
Find the regex used by HTML5 forms for validation
https://regex101.com/r/mPEKmy/1
FILTER_VALIDATE_EMAIL 中内置了一个更好的正则表达式,但任何正则表达式都会产生不好的结果。
例如..
// "not an email" is invalid so its false.
php > var_export(filter_var("not an email", FILTER_VALIDATE_EMAIL));
false
// "foo@a.com" looks like an email, so it passes even though its not real.
php > var_export(filter_var("foo@a.com", FILTER_VALIDATE_EMAIL));
'foo@a.com'
// "foo@gmail.com" passes, gmail is a valid email server,
// but gmail require more than 3 letters for the address.
var_export(filter_var("foo@gmail.com", FILTER_VALIDATE_EMAIL));
'foo@gmail.com'
您可能需要考虑使用像 Real Email 这样的 API,它可以进行深入的邮箱检查以检查电子邮件是否真实。
有一点像 ..
$email = "foo@bar.com";
$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 表示,如果需要启用域验证,他们需要参与确保域名有效的完整实施。因此,鉴于这方面需求的基本性质,验证“
可以满足此要求的典型正则表达式是: ^[^@\s]+@[^@\s.]+.[^@\s.]+$ 上述正则表达式遵循标准的 Perl 正则表达式标准,大多数编程语言广泛遵循。验证语句是:<除空格和“@”符号之外的任何内容>@<除空格和“@”符号之外的任何内容>。<除空格、@ 符号和点之外的任何内容>
对于那些想要更深入地了解更相关的实现的人,他们可以遵循以下验证方法。 <电子邮件本地部分>@<域名>
对于<电子邮件本地部分> - 遵循“Universal Acceptance Steering Group”的指导方针 - UASG-026 对于 <域名>,您可以使用标准库遵循任何域验证方法,具体取决于您的编程语言。有关该主题的最新研究,请遵循文档 UASG-018A。
那些有兴趣了解在实施国际化电子邮件解决方案时可能遇到的整体流程、挑战和问题的人,还可以查看以下 RFC:
RFC 6530(国际化电子邮件概述和框架) RFC 6531(国际化电子邮件的 SMTP 扩展) RFC 6532(国际化电子邮件标头) RFC 6533(国际化传递状态和处置通知) RFC 6855(对 UTF-8 的 IMAP 支持) RFC 6856(邮政Office 协议版本 3 (POP3) 支持 UTF-8)RFC 6857(国际化电子邮件的投递后邮件降级)RFC 6858(国际化电子邮件的简化 POP 和 IMAP 降级)。
问题标题相当笼统,但问题的主体表明它是关于基于 PHP 的解决方案。将尝试解决这两个问题。
一般而言,对于所有编程语言:通常,使用 reg-ex 验证电子邮件地址是任何基于 Internet 的服务提供商都应该停止的事情。各种域名和电子邮件的可能性- 邮件地址的种类增加了很多,任何验证尝试,如果没有很好的考虑最终可能会拒绝一些有效的用户进入您的系统。为了避免这种情况,最好的方法之一是向用户发送电子邮件并验证它是否被接收。“Universal Acceptance Steering Group”的好人编制了一个语言列表,这些库被发现符合/不符合各种参数,包括针对国际化域名和国际化电子邮件地址的验证。请通过 here 和 here 找到这些文档的链接。
具体来说 PHP:PHP 中有一个很好的库,即 EmailValidator。它是一个电子邮件地址验证器,包括许多验证方法,例如 DNS 验证。特别推荐的验证器称为 RFCValidator,它根据多个 RFC 验证电子邮件地址。在包容 IDN 和国际化电子邮件地址方面,它具有良好的合规性。
我已经使 Python 和 PHP 实现正确验证任何电子邮件地址,该地址被确认为来自真实域的邮件服务器的真实电子邮件地址。
根据 GPL-3.0 许可发布。
你去:
https://lja.fi/index.php/github-stuff/
--lja
我准备了一个检查电子邮件有效性的功能:
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("foo@gmail.com")) echo "valid";
if(!isValidEmail("fo^o@gmail.com")) echo "invalid";
filter_var
将落后相当长的一段时间,即使他们现在更改它(我已发布错误报告)。