正则表达式匹配电子邮件

时间:2017-04-28 22:55:34

标签: c# regex

我需要一个与电子邮件地址匹配的正则表达式,本地@域符合以下要求:

本地部分可以包含A-z,0-9,点,下划线和短划线。

可以包含A-z,0-9,点和短划线。域需要包含至少一个点。

如何确保:域名不能以点或短划线开头或结尾。并且域需要包含至少一个点?

这两件事在我试图解决它时确实会给我带来麻烦。

尝试了以下内容:

Regex.IsMatch(email, @"(?:[^.-])([\w.-])@([\w.-])(?:[.-]$)");

4 个答案:

答案 0 :(得分:6)

正确答案是:

仅验证@是否存在,域部分是否与几个简单规则匹配,本地部分是< = 64个字符,整个事物是< = 254个字符。

是的,排除完全非法的字符,好的。并确保使用 last @符号,而不是第一个。有关有效域名的所有商品,请参阅RFC 1035。也许RFC 819可以提供帮助。

如果您使用的是HTML,那么只需使用电子邮件输入<input type="email" autocomplete="off" autocorrect="off">,您就可以获得浏览器本身强制执行的大部分正确内容,而无需任何工作对你而言。见email input validation at MDN。虽然请注意,即使也可能过于严格,具体取决于浏览器。请参阅this bug浏览器的正确行为是接受电子邮件地址中的unicode(接受IDN标签),然后执行从U标签到​​A标签的转换,然后才执行验证。

如果您愿意,也可以检查是否可以在DNS中找到域名,但这是一个不必要且费力的步骤。

为什么我用巨幅印刷品大喊大叫?因为如此。臭。许多网站完全得到了这个,并且可怕错误。

首先,请阅读:I Knew How To Validate An Email Address Until I Read The RFC

然后,跟我说理片刻。正如文章所说的那样:

  1. 除了关于@符号的基本规则,各个部分的长度以及完全禁止的字符之外,电子邮件地址是否有效的唯一限定因素是该电子邮件地址的发布者 - 域所有者。
  2. 确定电子邮件地址是否真正与任何人联系的唯一决定因素是向该地址发送电子邮件,并查看该人是否收到该邮件地址。
  3. 考虑一下邮件。让我们假设有人给你一个有趣的地址,比如说,这个:

    AAB!129 Thor Circle 1/2 atomized Pile$
    Armelioborrigenduliamo, GRICKL, θ-niner *
    18957382:90347342;21017900~19127734.6
    THE MOON
    

    由于您以前可能从未向月球发送邮件,您是否确定要按照您熟悉的地区标准判断月球邮件地址?你怎么知道这不是一个有效的地址?如果这些人真的很奇怪怎么办?如果您是一家计划与您的客户做生意并且赚取大量资金的公司 - 为什么只要地址有效,您是否关心他们的地址是否很奇怪?

    事实上,美国的标准商业惯例证明了您无法验证其他权威地址的这一现实:邮政地址清理。这意味着,当有人向您提交邮寄地址时,您会向美国邮政局发送API调用,询问这是否是有效地址,并进一步询问其规范形式。这是因为只有邮局可以告诉您地址是否有效。即便如此,你还不知道在你尝试发送一封信之前,你的信是否会传给任何人!

    那么,为什么你会如此推测,以至于拒绝某人使用一个完全有效的电子邮件地址,他们的电子邮件提供商知道它是有效的(类似于向另一个国家甚至另一个星球发送邮件),只是因为它有你不习惯的某种格式,或者你无知的假设是错误的?

    如果您只是因为拼写错误而试图避免收错电子邮件地址,那么您仍然可以这样做。向用户显示&#34;嘿,关于您的地址的某些内容看起来并不合适。您确定它是否包含您已选择的这些字符? !#$%^&amp; *()&#34; {} []`〜请记住,如果我们无法通过电子邮件发送给您,您就无法创建帐户。&#34;然后人们会收到警告,但如果他们真的想要,他们仍然可以提交。 (好吧,是的,排除完全禁止的角色。我列出的那些不一定有效。查一查。你应该查看它。真的。你不应该接受一些随机网络人士的话。获得理解。)

    继续,甚至让它有点痛苦 - 让他们提交两次。或者选中一个方框并再次提交。只是不要阻止他们使用他们想要的任何东西。

    我个人有时决定不使用无法接受本地部分(在@之前)加号的电子邮件地址的网站或服务。如果我只是必须拥有帐户,我会咬牙切齿,有点生气,然后提交一个与我真正想要使用的地址不同的地址。

    除非你真的想减少可以与之做生意的客户群。然后继续进行限制......

    好的,此时,你恨我

    你认为我反应过度了。您只想验证您的电子邮件地址!会这么难吗?事实上,你只是会忽略我并继续写下一个能完成这项任务的人。它已经足够好了。

    好吧。如果你不听原因,那么here's some regex for you that does it right。 (只是,我实际上并不知道它是否做得对,但是我愿意打赌它是一个更接近正确的视线,而不是任何人在这里可以自己想出的更少比天和工作日。)

    神奇的电子邮件验证正则表达式

    (?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
    )+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
    \r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
    ?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ 
    \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
    31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
    ](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
    (?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
    (?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
    |(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
    ?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
    r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
     \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
    ?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
    )*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
     \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
    )(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
    )+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
    *:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
    |\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
    \n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
    \r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
    ]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
    ]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
    ?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
    :(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
    :\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
    :(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
    [ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] 
    \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
    \\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
    @,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
    (?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t]
    )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
    ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?
    :[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[
    \]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-
    \031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(
    ?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;
    :\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
    ^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\"
    .\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
    ]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
    [\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
    r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] 
    \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]
    |\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0
    00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\
    .|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,
    ;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
    :[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*
    (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
    \[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
    ^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
    ]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(
    ?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
    ".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(
    ?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
    \["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t
    ])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t
    ])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?
    :\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|
    \Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:
    [^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
    ]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)
    ?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
    ()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)
    ?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
    @,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[
     \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,
    ;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
    )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
    ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?
    (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
    \[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:
    \r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[
    "()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])
    *))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])
    +|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\
    .(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
    |(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(
    ?:\r\n)?[ \t])*))*)?;\s*)
    

    当然,它已被打破。删除换行符。

答案 1 :(得分:1)

在一种黑暗和自我毁灭的精神错乱中,我决定回答你的问题。

您的确切要求:

  • 本地部分可以包含A-z,0-9,点,下划线和短划线。
  • 域名可以包含A-z,0-9,点和短划线。
  • 域名需要包含至少一个点。
  • 域名不能以点或破折号开头或结尾。

您的RegEx符合这些确切要求而不再符合(不区分大小写):

^[\w.-]+@(?=[a-z\d][^.]*\.)[a-z\d.-]*[^.]$

Try it out at regex101.com

我小心翼翼地确保这几乎没有回溯。在regex101.com,您可以看到它执行了多少步骤。好地址有13个步骤验证,非常好。在末尾带点的地址是性能最差的,因为这会导致整个域部分一次回溯一个字符,但它们可能很少见。

请投票下载这篇文章,就像你在其他帖子上投票一样,试图回答给出的问题。

然后,请参阅我的其他answer on this page并将其投票。

备注:

在C#中,\w包含a wide range of Unicode characters。这可能是也可能不是您正在寻找的。如果没有,您可以按原样保留Regex并使用符合ECMAScript标准的模式。或者,您可以将其更改为a-z0-9_(方括号内)。但\w更短。

\dincludes some additional numeric characters

  

\ d匹配任何十进制数字。它等同于\ p {Nd}正则表达式模式,它包括标准的十进制数字0-9以及许多其他字符集的十进制数字。

您可以再次使用ECMAScript兼容模式,或者只需将其更改为0-9。但\d更短。

请注意,这种正则表达式有很多有用的方法。它允许域部分中的IP地址(不正确),它不限制正则表达式的总长度或域部分的长度。它不正确地限制了不应该限制的本地部分的字符。它根本不是一个好的规范。

答案 2 :(得分:0)

修改

我认为这样可行:

Regex regex = new Regex(@"^([\w\.\-]+)@((?!\.|\-)[\w\-]+)((\.(\w){2,3})+)$");

注意:域名不能包含点和空格

但是,您可以尝试使用Mail Address Class,而不是使用正则表达式。通过这种方式,你不必为理解别人的正则表达而打破头脑

public bool IsEmailValid(string address)
{
    try
    {
        MailAddress m = new MailAddress(address);
        return true;
    }
    catch (FormatException)
    {
       return false;
    }
}

答案 3 :(得分:0)

你应该从http://www.regular-expressions.info这样的来源学习正则表达式 - 到目前为止的尝试显示了很多缺失的知识,并且所述的问题非常复杂(甚至忽略了自定义正则表达式几乎肯定是错误的方法,尽管它可能是一个有用的预过滤器。)

为什么这个正则表达式不起作用 - @"(?:[^.-])([\w.-])@([\w.-])(?:[.-]$)");

我将通过将正则表达式分解为英语来解释(这对于正则表达式来说通常是一种很棒的技术):

首先,这里的所有括号都没有功能,所以我忽略了它们(请参阅教程,了解它们的意思)

本地

  • [^.-] - 1个不是点或短划线的字符
  • [\w.-] - 1个字母数字或字母或短划线

因此 local 的定义是任何以<2>字符串结尾的字符串

@ - 字面意思,字符'@'

  • [\w.-] - 1个字母数字或字母或短划线
  • [.-] - 1个字符是点或短划线
  • $ - 字符串的结尾。

所以 domain 的定义是一个带有上述约束的2个字符的字符串。

这显然与给定问题相差甚远。

什么是满足给定约束的正则表达式?

Regexes基本上是按顺序左右评估的。在一组连续的描述中表达您的约束,然后将它们转换为正则表达式结构。我会为了给定的约束(我认为不完整)这样做。在每一行之间精神上插入'后跟'。

字符串的开头 - ^ - 表示字符串开头的正则表达方式

local - [\w._-]* - 任意数量的(字母数字,点,破折号)。

@ - @ - 文字字符

关键要求是至少1个点。此点将明确显示在正则表达式中,因此将域视为{preDot} {dot} {postDot}。为简单起见,请将{dot}定义为.第一次次。

  • \w - 单个字母数字字符 - 这是不以点或短划线开头要求
  • [\w-]* - 任意数量的字母数字或破折号字符
  • \. - 单个(第一个)点字符 - 这是特殊的必须存在
  • (\w*[\.-])* - 任意数量(任意数量的字母数字字符,后跟点或短划线)
  • [\w-]+ - 一个或多个字母数字或短划线字符 - 这是不得以点要求结束

字符串结尾 - $ - 表示字符串结尾的正则表达方式

以下是相应的代码:

var literal = @"\w*";

var preDot = @"\w[\w-]*";
var dot = @"\.";
var postDot = @"(\w*[\.-])*[\w-]+";
var domain = $"{preDot}{dot}{postDot}";

var email = $"^{literal}@{domain}$";

仅供参考 - 正则表达式最终为^\w*@\w[\w-]*\.(\w*[\.-])*[\w-]+$,但这在很大程度上是无关紧要的,试图将其理解/维护/更改为单个字符串会很糟糕,而故障可以跟进。