使用PHP验证国际电子邮件地址 动机

使用PHP验证国际电子邮件地址 动机,php,internationalization,email-validation,Php,Internationalization,Email Validation,在这篇文章中,我想收集最佳实践和解决方案,以解决验证电子邮件地址(包括国际电子邮件)的问题。有两种方法,如结构检查、DNS查找等。但似乎在这一过程中存在陷阱/边缘情况,这不是每个人都知道的。我希望你们能帮助我收集好的链接/代码/提示,按主题分组(例如服务器端、HTML准备等) 让我们在一个单独的答案中处理每个感兴趣的领域 验证的意义 如果我使用术语验证,我指的是数据验证。维基百科对它的定义是: […]是确保数据经过数据清理以确保数据质量的过程,也就是说,它们都是正确的和有用的 资料来源: 电子邮

在这篇文章中,我想收集最佳实践和解决方案,以解决验证电子邮件地址(包括国际电子邮件)的问题。有两种方法,如结构检查、DNS查找等。但似乎在这一过程中存在陷阱/边缘情况,这不是每个人都知道的。我希望你们能帮助我收集好的链接/代码/提示,按主题分组(例如服务器端、HTML准备等)

让我们在一个单独的答案中处理每个感兴趣的领域

验证的意义 如果我使用术语验证,我指的是数据验证。维基百科对它的定义是:

[…]是确保数据经过数据清理以确保数据质量的过程,也就是说,它们都是正确的和有用的

资料来源:

电子邮件地址验证 电子邮件地址验证是指根据RFC 5322条款测试字符串是否有效。这是描述电子邮件使用的互联网消息格式的最新版本。参考:

这不包括检查电子邮件提供商是否有效(例如一次性电子邮件)或地址是否合理(例如。a1@a2.coo)或者如果TLD可用

大多数验证器不包括:国际电子邮件地址 国际电子邮件()可以包含ASCII中不存在的各种UTF-8字符

基于wiki文章的有效示例:

  • θσερ@εχαμπλε.ψμ
  • 德奥rte@Sörensen.example.com

不是重复的:此答案收集已知解决方案以验证电子邮件地址。它还包含有关检查国际电子邮件时已知限制的信息。最后,我提供了一个可能的解决方案,如何遇到国际电子邮件

过滤变量 本文作者建议使用以下功能来验证电子邮件:

函数isValidEmail($email){
返回filter\u var($email,filter\u VALIDATE\u email)!==false;
}
如果您要求TLD成为地址的一部分,作者还建议:

function isValidEmail($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL) 
        && preg_match('/@.+\./', $email);
}
问题:不支持国际电子邮件地址
filter\u var
不包括国际电子邮件地址,这些地址包含UTF-8字符,如希腊语或俄语


预赛 使用自定义正则表达式验证结构。有详细描述的好帖子是

作者从中提出了一个正则表达式,它允许对照最新的RDF 5322进行检查。以下代码是非固定版本:

(2)(以下以下::::::\x22?\X50\x00-\x00-\x00-\x00\x00\x00\x00\x00\x00\X7 7.5 5\X0 0 0\X0\X5\X5\C\x22\x22.0.10)及(以下:::::::::::::::::::::::)2.2?[[[[[3^[3^[3^\X5\X5\X5\X5\X5\X5\C\X5\X5\X5\X5\X5\C\X5\C\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22.........................01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F])*\x22))(?:\(?:)(2)以下几方面的:(1)在本月的\x21\x21\x21\x21\x21\x21\x21\x21\x21\x21\x21\x21\x21\x21\x21\x21\x21\x23\x21\x21\x21\x21\x21\x21\3\x23\3\3\3\3\x3\3\x3\x3\x3\x3\x3\x3\x3\X5\X5 E-\X5\X7 E-\X7 E-\X7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7)的[[7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7手手手手手手手手手手手手手手(?:(?:[a-z][a-z0-9]*)|(?:(?:xn-)[a-z0-9]+)(?:-[a-z0-9]+)*)|(?:\[(?:(?:[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})(?:(?:)?!(:::::::::::::::::::::::::::::::(::[a-0-0-0-0-0-0-0-0-0-0-0-0-1,4}{{1,4}{1.9[a-0-0-0-0-0-0-9[10-0-9[10[10-0-0-0-0-0-9[10 10[10[10[10[10[10[10[10[10-0-0-0-0-0-0-0-0-0-0-9[10[10 10 10[10[10[10[10 10 10 10 10 10 10 10 10 10[10 10[10[10[10 10 10 10[10 10[10[10[10[10 10[10 10 10 10 10[10[10[10[10[10[10[10[10 10 10 10 10[10[10[10[10[10 10[a-f0-9]:{5,4}(?:[a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,3}):::(?:[a-f0-9]{1,4}(:[a-f0-9]{1,4}{0,3}))(?:(?:[a-f0 9]{1,4}){0,3}){25[0-5];(?:2[0-4][0-9]:[1240-1249]{1]。(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9])){3}]\])$/iD'; 如果(1=\preg_匹配($regex,$email)){ //电子邮件OK } 他还提到:

[…]RFC 5322生成了一个正则表达式,只要研究几分钟就可以理解,并且对于实际使用来说足够有效。[…]

问题:不支持国际电子邮件地址 此解决方案也不包括国际地址,这导致不匹配


可选:DNS查找 DNS查找不是验证,但可以补充检查。如果所有UTF-8字符构成有效的国际化域名(参考:),则DNS查找可用于所有UTF-8字符

[…]是一个互联网域名,其中至少包含一个标签,该标签以特定语言的脚本或字母表(如阿拉伯语、汉语、西里尔语、泰米尔语、希伯来语)显示在软件应用程序中[…],或以拉丁字母表为基础并带有变音符号或连字(如法语)

通过
checkdnsrr
检查给定域是否具有有效的DNS记录

/$domain之前已从给定电子邮件中提取
//$domain必须以结尾。(请参阅下面的注释)
if(checkdnsrr($domain,'MX')| | checkdnsrr($domain,'A')| | checkdnsrr($domain,'AAAA')){
//域是有效的
}
用户Martin在php.net上提到,域必须以
结尾才能被认为是有效的。没有这一点,您将得到误报

来源


处理国际邮件 可能的解决方案1:结构检查+DNS查找 到目前为止,我已经看到,您需要结合结构检查和DNS查找来获得最佳覆盖率。以下代码的第一部分基于来自Genkgo Mail()的类
EmailAddress

函数邮件有效(字符串$address):bool{
$hits=\preg_match('/^([^@]+)@([^@]+)$/',$address,$matches);
如果($hits==0){
//电子邮件无效
返回false;
}
[$address,$localPart,$domain]=$matches;
$variant=INTL_IDNA_variant_2003;
如果(\defined('INTL\u IDNA\u VARIANT\u UTS46')){
$variant=INTL_IDNA_variant_UTS46;
}
$domain=\rtrim(\idn_to_ascii($domain,IDNA_DEFAULT,$variant),“.”;
if(!\checkdnsrr($domain,'MX')){
return\checkdnsrr($domain,'A')| | \checkdnsrr($domain,'AAAA');
}否则{
返回true;
}
}
我认为这是当前的趋势。