多年来,我慢慢地开发了一个正则表达式,它可以正确验证大多数电子邮件地址,假设它们不使用IP地址作为服务器部分。

我在几个PHP程序中使用它,而且大多数时候都可以使用。然而,不时有人与我联系,他们对使用它的网站有问题,我最终不得不做出一些调整(最近我意识到我不允许四个字符的TLD)。

你有或见过验证电子邮件的最佳正则表达式是什么?

我见过几种使用函数的解决方案,这些函数使用了几个较短的表达式,但我宁愿在简单函数中使用一个长的复杂表达式,而不是在更复杂的函数中使用几个短表达式。


当前回答

这是我使用的PHP代码。我选择这个解决方案是出于“误报比误报好”的精神,正如这里的另一位评论者所说的,并考虑到保持您的响应时间并降低服务器负载。。。当正则表达式可以消除大多数简单的用户错误时,真的不需要浪费服务器资源。如果你愿意,你可以随时通过发送测试邮件来跟进。

function validateEmail($email) {
  return (bool) stripos($email,'@');
}

其他回答

我知道这个问题是关于正则表达式的,但我猜,在阅读这些解决方案的所有开发人员中,90%都在尝试验证浏览器中显示的HTML格式的电子邮件地址。

如果是这种情况,我建议查看新的HTML5<inputtype=“email”>表单元素:

HTML5:

 <input type="email" required />

CSS 3:

 input:required {
      background-color: rgba(255, 0, 0, 0.2);
 }

 input:focus:invalid {
     box-shadow: 0 0 1em red;
     border-color: red;
 }

 input:focus:valid {
     box-shadow: 0 0 1em green;
     border-color: green;
 }

它是在HTML5表单验证没有JS-JSFidle代码游乐场。

这有两个优点:

自动验证,无需定制解决方案:简单易实现没有JavaScript,如果禁用了JavaScript也不会出现问题没有服务器需要为此计算任何东西用户有即时反馈旧浏览器应自动回退到输入类型“文本”移动浏览器可以显示专用键盘(@-键盘)使用CSS 3,表单验证反馈非常简单

明显的缺点可能是缺少对旧浏览器的验证,但这会随着时间的推移而改变。比起这些疯狂的正则表达式杰作,我更喜欢这个。

另请参见:

没有JS的HTML5表单验证-JSFiddle-代码游乐场Web表单-深入HTML5。疯狂的一种形式SUMO上的HTML5表单验证

当您使用PHP编写时,我建议您使用PHP内置的电子邮件验证。

filter_var($value, FILTER_VALIDATE_EMAIL)

如果您运行的是低于5.3.6的PHP版本,请注意这个问题:错误#53091:当我试图过滤一个大于2264个字符的文本时出现崩溃

如果您想了解此内置验证如何工作的更多信息,请参阅此处:PHP的filter_var filter_VALIDATE_EMAIL实际工作吗?

我用这个;

^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$

电子邮件正则表达式(RFC 5322)

(?im)^(?=.{1,64}@)(?:("[^"\\]*(?:\\.[^"\\]*)*"@)|((?:[0-9a-z](?:\.(?!\.)|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)?[0-9a-z]@))(?=.{1,255}$)(?:(\[(?:\d{1,3}\.){3}\d{1,3}\])|((?:(?=.{1,63}\.)[0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9])|((?=.{1,63}$)[0-9a-z][-\w]*))$

演示https://regex101.com/r/ObS3QZ/1

# (?im)^(?=.{1,64}@)(?:("[^"\\]*(?:\\.[^"\\]*)*"@)|((?:[0-9a-z](?:\.(?!\.)|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)?[0-9a-z]@))(?=.{1,255}$)(?:(\[(?:\d{1,3}\.){3}\d{1,3}\])|((?:(?=.{1,63}\.)[0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9])|((?=.{1,63}$)[0-9a-z][-\w]*))$

# Note - remove all comments '(comments)' before running this regex
# Find  \([^)]*\)  replace with nothing

(?im)                                     # Case insensitive
^                                         # BOS

                                          # Local part
(?= .{1,64} @ )                           # 64 max chars
(?:
     (                                         # (1 start), Quoted
          " [^"\\]*
          (?: \\ . [^"\\]* )*
          "
          @
     )                                         # (1 end)
  |                                          # or,
     (                                         # (2 start), Non-quoted
          (?:
               [0-9a-z]
               (?:
                    \.
                    (?! \. )
                 |                                          # or,
                    [-!#\$%&'\*\+/=\?\^`\{\}\|~\w]
               )*
          )?
          [0-9a-z]
          @
     )                                         # (2 end)
)
                                          # Domain part
(?= .{1,255} $ )                          # 255 max chars
(?:
     (                                         # (3 start), IP
          \[
          (?: \d{1,3} \. ){3}
          \d{1,3} \]
     )                                         # (3 end)
  |                                          # or,
     (                                         # (4 start), Others
          (?:                                       # Labels (63 max chars each)
               (?= .{1,63} \. )
               [0-9a-z] [-\w]* [0-9a-z]*
               \.
          )+
          [a-z0-9] [\-a-z0-9]{0,22} [a-z0-9]
     )                                         # (4 end)
  |                                          # or,
     (                                         # (5 start), Localdomain
          (?= .{1,63} $ )
          [0-9a-z] [-\w]*
     )                                         # (5 end)
)
$                                         # EOS

我也有类似的愿望:希望快速检查电子邮件地址中的语法,而不要过分使用电子邮件发送实用程序(邮件::RFC822::地址答案显然是正确的答案)。我同意这个(我是一个POSIX正则表达式的人,所以我通常不会使用PCRE中的\d等,因为它们让我看不清楚):

preg_match("_^[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*@[0-9A-Za-z]([-0-9A-Za-z]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([-0-9A-Za-z]{0,61}[0-9A-Za-z])?)*\$_", $adr)

这是RFC正确的,但它明确排除了过时的表单以及直接IP地址(IP地址和传统IP地址),而该实用程序的目标组中的某些人(主要是:在IRC上的#sendmail中打扰我们的人)通常不希望或不需要这些地址。

IDN(国际化域名)明确不在电子邮件范围内:地址如“foo@cäcilenchor bonn.de“必须写”foo@xn--ccilienchor-bonn-vnb.de而在网络上(这包括HTML中的mailto:links和这样的乐趣),只允许GUI向用户显示(并接受然后转换)这样的名称。