电子邮件地址验证方法(订阅按钮)
Posted
技术标签:
【中文标题】电子邮件地址验证方法(订阅按钮)【英文标题】:Email address validation methods (Subscribe button) 【发布时间】:2011-03-16 06:36:36 【问题描述】:我正在用 php 编写一个网站,我目前正在联系我们页面上,我想知道验证电子邮件地址的最佳方法是什么?
-
通过向他们的电子邮件发送验证链接?
正则表达式
还有其他方法吗?
您能否告诉我原因以及实现目标的指南?我不希望有人为我编写代码,因为这对我来说没有乐趣,我不会学习,只是对用于实现上述任一方法的技术的一些指导。
我还将使用这些方法在我的网页上实现订阅按钮。这是最好的方法吗?我应该考虑其他任何方法吗?
【问题讨论】:
可能重复:***.com/questions/201323/… Regex 不会验证电子邮件,它只会验证用户输入看起来像电子邮件。 (adasdsa@dadsd.com 将验证)如果您确实需要验证,您必须发送验证电子邮件。 【参考方案1】:我通常会经历这些步骤
-
正则表达式
向邮箱发送激活码
如果第一步失败,它永远不会到达第二步。 如果由于电子邮件不存在而导致电子邮件发送失败,我会删除帐户或做一些其他事情
--编辑
3 - 如果由于某种原因未发送激活电子邮件、未删除电子邮件、未批准 7 天(或根据您的配置),则每 2-3 小时尝试重新发送电子邮件,在那些日子之后,如果没有成功,电子邮件将被删除
4 - 如果电子邮件发送成功但未激活,它将保持未批准状态,但可以通过生成新的激活码随时重新激活
【讨论】:
我还想补充一点,为了方便用户,为未验证的用户分配某种“预先批准”状态,这样当邮件传递速度很慢时,用户仍然可以使用您的服务。而且,不要对你的正则表达式太严格,只要确保它“有点像电子邮件地址”,你不想要太多的漏报。 @Dennis:我不认为输入一个看似合理但可能是错误的电子邮件地址足以让用户获得更多访问权限。 请不要使用正则表达式来验证电子邮件地址。不可能编写与 RFC2822 中的规范完全匹配的正则表达式。你最终会得到误报和误报。误报是一个大问题,因为它们会阻止有效的电子邮件地址通过。 Jeffrey Friedl 在“掌握正则表达式”中开发了一个电子邮件匹配正则表达式。它大约有 7000 个字符长,匹配 98% 的有效地址格式。最好只使用使用它的库。【参考方案2】:我认为最好的是 3. 和 1 的组合。
在初始阶段,您在语法上验证电子邮件(以捕捉拼写错误):
filter_var($email, FILTER_VALIDATE_EMAIL)
然后,您会发送一封带有确认地址的电子邮件(以捕获错误和故意错误的信息)。
【讨论】:
+1 人们需要知道filter_var()
,它太棒了。【参考方案3】:
最好的方法是发送一封包含验证链接的电子邮件。至少如果您不想要激活电子邮件,请验证电子邮件地址。最好的电子邮件验证功能是RFC-compliant email address validator by Dominic Sayers。
只需在项目中包含 php 文件并像这样使用它:
if (is_email($email, $checkDNS, $diagnose)) //$checkDNS and $diagnose are false by default
echo 'Email valid';
else
echo 'Email invalid';
如果 $checkDNS 设置为 true,它将验证域是否存在。如果域不存在,即使电子邮件有效,该函数也会返回 false。
如果 $diagnose 设置为 true,该函数会返回一个代码而不是布尔值,它会告诉您为什么电子邮件无效(如果有效,则返回 0)。
【讨论】:
【参考方案4】:这取决于用户是否真的想收到回复。
如果用户提出问题,他会希望得到答复,并且可能会提供他的有效电子邮件地址。在这种情况下,我会使用非常松散的正则表达式检查来发现拼写错误或丢失的地址。 (类似于.+@.+
。)
如果用户不想被联系,但您想知道他们的地址,则需要使用验证链接。没有其他方法可以确保电子邮件地址有效且属于用户。
【讨论】:
【参考方案5】:真正知道电子邮件是否有效的唯一方法是向其发送电子邮件。如果确实需要,请使用these 之一。 Technically,对于本地域,@ 之后甚至不必有任何句点。所需要的只是一个域跟随@。
【讨论】:
等到人们开始将 IPV6 冒号分隔的值作为他们的域。 :-)【参考方案6】:正则表达式并不真正适合确定电子邮件地址语法的有效性,filter_var
函数的FILTER_VALIDATE_EMAIL
选项也相当不可靠。我使用EmailAddressValidator Class 来测试电子邮件地址的语法。
我整理了几个filter_var
(PHP 版本 5.3.2-1ubuntu4.2)返回的错误结果的示例。可能还有更多。有些确实有点极端,但仍然值得注意:
RFC 1035 2.3.1。首选名称语法http://tools.ietf.org/search/rfc1035 概括为:域由点分隔符分隔的标签组成(但对于本地域不一定如此)。
echo filter_var('name@example', FILTER_VALIDATE_EMAIL);
// name@example
RFC 1035 2.3.1。首选名称语法 标签必须遵循 ARPANET 主机名的规则。它们必须以字母开头,并以字母或数字开头,内部字符只能是字母、数字和连字符。
echo filter_var('name@1example.com', FILTER_VALIDATE_EMAIL);
// name@1example
RFC 2822 3.2.5。带引号的字符串https://www.rfc-editor.org/rfc/rfc2822#section-3.2.5 这是有效的(尽管它被许多邮件服务器拒绝):
echo filter_var('name"quoted"string@example', FILTER_VALIDATE_EMAIL);
// FALSE
RFC 5321 4.5.3.1.1。本地部分https://www.rfc-editor.org/rfc/rfc5321#section-4.5.3.1.1 用户名或其他本地部分的最大总长度为 64 个八位字节。 测试 70 个字符:
echo filter_var('AbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghij@example.com', FILTER_VALIDATE_EMAIL);
// AbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghij@example.com
RFC 5321 4.5.3.1.2。域名https://www.rfc-editor.org/rfc/rfc5321#section-4.5.3.1.2 域名或号码的最大总长度为 255 个八位字节。 测试 260 个字符:
echo filter_var('name@AbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghij.com', FILTER_VALIDATE_EMAIL);
// name@AbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghijAbcdefghij.com
查看Validate an E-Mail Address with PHP, the Right Way 了解更多信息。
【讨论】:
Doug Lovell 来自 Linux Journal 的文章在某些情况下实际上是错误的。他重复了 RFC 3696 中的原始错误,这些错误现已在勘误表中得到纠正。不幸的是,Linux Journal 认为不适合纠正这篇误导性文章,它仍然被引用为权威。【参考方案7】:在发送验证电子邮件之前,您还可以使用checkdnsrr()
来验证域是否存在并且是否设置了 MX 记录。这将检测使用虚假域(如 user@idontexist.com)的电子邮件。
function validateEmail($email, $field, $msg = '')
if (!filter_var($email, FILTER_VALIDATE_EMAIL))
return false;
list($user, $domain) = explode('@', $email);
if (function_exists('checkdnsrr') && !checkdnsrr($domain, 'MX'))
return false;
return true;
我们需要使用function_exists()
来验证checkdnsrr()
对我们可用,因为它在PHP 5.3 之前的Windows 上不可用。
【讨论】:
为什么您认为发送电子邮件需要 MX 记录? “如果没有 MX 记录,则服务器回退到 A,也就是说,它向同域的 A 记录发出请求。” @sanmai 虽然这在理论上可能是正确的,但您很少(如果有的话)在实践中看到这种情况发生。此外,在验证电子邮件地址时,除了向该地址发送电子邮件并等待回复外,没有任何自动化流程是完美的。包括这个方法。但是,如果提供的错误电子邮件地址是一个问题,这将有助于缓解这种情况。 @john-conde 我已经看到这种情况至少发生了几次。想象一下,您描述一位经理为什么您的宝贵客户无法使用他的工作(他们检查过)电子邮件地址进行注册。 我也见过 sanmai 的东西。这并不常见,但它是真实的。归根结底,检查 MX 记录不会给你带来太多好处,无论如何,所以我不会打扰。 嗯。也许那么这最好用作确定电子邮件地址合法概率的几个决定因素之一?仅与其他测试结合使用。【参考方案8】:取决于你的目标。如果您必须拥有有效且有效的电子邮件,那么您必须发送一封要求验证收据的电子邮件。在这种情况下,除了为您的用户提供方便外,不需要正则表达式验证。
但是,如果您希望帮助用户避免拼写错误,同时尽量减少用户的烦恼,请使用正则表达式进行验证。
【讨论】:
【参考方案9】:这里有一些很好的答案,除了正则表达式位之外,我同意所选的答案。正如其他人指出的那样,要找到一个完全实现 RFC 5321 的所有怪癖的正则表达式,即使不是不可能,也是很困难的。
欢迎您使用我的免费 PHP 函数 is_email()
来验证地址。可用here。
它将确保地址完全符合 RFC 5321。它还可以选择检查域是否实际存在。
您不应依赖验证器来告诉您用户的电子邮件地址是否真实存在:一些 ISP 会向其用户提供不合规的地址,尤其是在不使用拉丁字母的国家/地区。更多关于电子邮件验证的文章在这里:http://isemail.info/about。
【讨论】:
【参考方案10】: function checkEmail($email)
if(preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])
↪*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/",
$email))
list($username,$domain)=split('@',$email);
if(!checkdnsrr($domain,'MX'))
return false;
return true;
return false;
【讨论】:
您的正则表达式拒绝了许多有效的电子邮件地址。例如 *@example.com、“Hello world”@example.com、someone@[127.0.0.1]、someone@[2001:1234:1234::1.2.3.4] 虽然我会因为 ipv6 不匹配而让你失望,但正则表达式的其余部分太差了,无法考虑。以上是关于电子邮件地址验证方法(订阅按钮)的主要内容,如果未能解决你的问题,请参考以下文章