电子邮件地址中允许使用哪些字符?

848

我并不是在问如何完整验证电子邮件。

我只想知道电子邮件地址中用户名服务器部分允许使用哪些字符。这可能有些简化了,也许电子邮件地址可以采用其他形式,但我不关心。我只是询问这个简单的形式:用户名@服务器(例如 wild.wezyr@best-server-ever.com),并且两部分允许使用哪些字符。


264
“+”符号是允许的。当网站不允许“+”符号时,我会感到很烦,因为我的电子邮件地址里有一个“+”符号,而许多网站都不允许使用它。 - Dan Herbert
12
之前有类似的问题:stackoverflow.com/questions/760150/。悲哀的是,尽管那个问题比这个早了近8个月,但那个问题的答案要好得多。几乎所有下面的答案在最初发布时就已经过时了。请参阅 维基百科条目(不用担心,它有相关的官方参考资料)。 - John Y
29
与一些答案相反,如果加上引号,电子邮件地址的本地部分是允许包含空格的。例如,"hello world"@example.com 是合法的。 - user253751
11
当你创建一个Gmail邮箱时,它不允许你使用加号(+)符号来创建地址。加号符号(即正则表达式“Plus-addressing”)允许任何拥有Gmail地址的人在他们的用户名后面添加加号符号和字符串,以便创建一个用于他们账户的“备选”(“别名”)电子邮件地址。例如:“example@gmail.com”和“example+tag@gmail.com”。这种方法的一个典型(并且可能是“主要”)用途是为您的账户创建别名电子邮件地址,这些地址允许您标记和过滤传入的电子邮件信息,理论上可以通过发送者进行过滤。 - Kevin Fegan
10
反过来更为普遍。如果一个网站不能信任其允许的电子邮件地址是正确的,我就不相信他们能够妥善处理我的个人信息。 - Dan Herbert
显示剩余17条评论
18个回答

994
请查看RFC 5322:互联网消息格式和在较小程度上RFC 5321:简单邮件传输协议RFC 822也涵盖电子邮件地址,但主要处理其结构:
 addr-spec   =  local-part "@" domain        ; global address     
 local-part  =  word *("." word)             ; uninterpreted
                                             ; case-preserved
 
 domain      =  sub-domain *("." sub-domain)     
 sub-domain  =  domain-ref / domain-literal     
 domain-ref  =  atom                         ; symbolic reference

通常情况下,维基百科有一篇不错的关于电子邮件地址的文章

电子邮件地址的本地部分可以使用以下任何ASCII字符:

  • 大写和小写拉丁字母 AZaz
  • 数字 09
  • 特殊字符 !#$%&'*+-/=?^_`{|}~
  • 点号 .,但不能是第一个或最后一个字符,除非加上引号,并且也不能连续出现,除非加上引号(例如,John..Doe@example.com 不允许,但 "John..Doe"@example.com 允许);
  • 空格和 "(),:;<>@[\] 字符是有限制的(只允许在引号字符串内使用,如下面的段落所述,并且必须在反斜杠前面加上反斜杠或双引号);
  • 注释允许在本地部分的括号两端使用;例如,john.smith(comment)@example.com(comment)john.smith@example.com 都等同于 john.smith@example.com
除了ASCII字符外,截至2012年你还可以使用国际字符以上U+007F,以UTF-8编码,如RFC 6532规范所述并在维基百科上解释。请注意,截至2019年,这些标准仍被标记为建议性的,但正在缓慢推出。本规范中的更改实质上将国际字符添加为有效的字母数字字符(atext),而不影响允许和限制特殊字符的规则,如!#@:
有关验证,请参见使用正则表达式验证电子邮件地址domain部分定义如下
互联网协议(请求评论)中的标准规定,组件主机名标签只能包含ASCII字母a到z(不区分大小写),数字0到9和连字符(-)。RFC 952中的主机名初始规范规定标签不能以数字或连字符开头,也不能以连字符结尾。然而,后续规范(RFC 1123)允许主机名标签以数字开头。不允许使用其他符号、标点符号或空格。

24
@WildWzyr,这并不是那么简单。电子邮件地址有许多关于允许的规则。参考规范比列出所有规则更简单。如果你想要完整的正则表达式,请查看此处以了解为什么这并不简单:http://www.regular-expressions.info/email.html - Dan Herbert
6
没有简单的列表,仅因你希望它简单并不意味着它就是这样。有些字符只能在特定的位置出现,而不能出现在其他位置。你不能一直得到自己想要的。 - user177800
16
@WildWezyr,句号字符在电子邮件地址的本地部分是允许使用的,但不能出现在开头或结尾,也不能与另一个句号相邻。因此,答案并不像仅仅列出允许使用的字符那么简单,存在一些关于如何使用这些字符的规则。例如,ann..other.@example.com 不是有效的电子邮件地址,但 ann.other@example.com 是有效的,即使它们都使用相同的字符。 - Mark Pim
14
请记住,随着国际化域名的出现,允许使用的字符列表将会大幅扩展。 - Chinmay Kanchi
53
由于地址国际化,这个回答已经不再有效。请查看Mason的回答。 - ZacharyP
显示剩余15条评论

398

注意!这个帖子中有一堆知识已经过时了。

为了避免在当前和未来的世界中,以及世界上任何地方误报实际电子邮件地址,您需要至少了解RFC 3490,“应用程序中的国际化域名(IDNA)”的高级概念。我知道美国人可能对此不太了解,但它已经在全球范围内(主要是非英语占主导地位的地区)得到广泛和迅速增长的使用。

要点是您现在可以使用像mason@日本.com和wildwezyr@fahrvergnügen.net这样的地址。不,这还不与所有现有技术兼容(正如许多人所抱怨的那样,即使是简单的qmail风格的+ident地址也经常被错误拒绝)。但是有一个RFC,有一个规范,现在由IETF和ICANN支持,并且更重要的是,目前有大量正在使用这种改进的实现。

直到我回到日本并开始看到像hei@やる.ca和Amazon URL这样的电子邮件地址时,我自己对这个发展了解不多。

http://www.amazon.co.jp/エレクトロニクス-デジタルカメラ-ポータブルオーディオ/b/ref=topnav_storetab_e?ie=UTF8&node=3210981

我知道您不想要链接到规范,但如果您仅依赖于互联网论坛上黑客过时的知识,您的电子邮件验证器将拒绝非英语用户越来越希望使用的电子邮件地址。对于这些用户,这样的验证将像我们所有人讨厌的普遍愚蠢表格一样令人讨厌,无法处理“+”或三部分域名等内容。
所以我不是说这不麻烦,但“允许在某些/任何/没有条件下使用”的字符的完整列表是所有语言中的(几乎)所有字符。如果您想“接受所有有效的电子邮件地址(以及许多无效的电子邮件地址)”,则必须考虑IDN,这基本上使基于字符的方法无用(抱歉),除非您首先将国际化电子邮件地址转换(自2015年9月已停用,曾经像这样——一个工作的替代方案是在这里)为Punycode
在执行此操作后,您可以按照上述大部分建议进行操作。

20
没问题,幕后,域名仍然只是ASCII编码。但是,如果你的网络应用程序或表单接受用户输入的内容,那么需要执行与Web浏览器或邮件客户端相同的操作,将用户输入的IDN主机名转换为DNS兼容格式,然后验证。否则,这些国际化电子邮件地址将无法通过验证。(像我链接到的转换器只会修改给定的非ASCII字符,因此可以放心地在非国际化的电子邮件地址上使用它们(它们将不做任何修改返回)。) - Mason
3
对于JavaScript开发人员,我现在正在研究如何做到这一点,而Punycode.js似乎是最完整和精细的解决方案。 - wwaawaw
5
请注意,国际化电子邮件(按当前定义)不会使用punycode或类似方法转换非ASCII地址,而是扩展了SMTP协议本身的大部分内容以使用UTF8编码。 - IMSoP
4
我是否遗漏了什么或者这篇文章没有回答问题?我看到“另一个回答是错误的,你需要接受更多字符”,但它没有说明额外的字符是哪些。我也没有(容易地)在RFC中看到它是否涵盖了全部Unicode码点还是只涵盖BMP。 - Samuel Harmer
3
这似乎是正确答案的正确方向。如果您包括有关保留和允许字符的具体信息,我打赌它将获得更多投票。 - Sean
显示剩余4条评论

105

电子邮件地址的格式为:local-part@domain-part(最多64@255个字符,总共不超过256个字符)。

local-partdomain-part可以有不同允许字符集,但这并不是全部,因为还有更多规则。

通常,本地部分可以使用这些ASCII字符:

  • 小写拉丁字母:abcdefghijklmnopqrstuvwxyz,
  • 大写拉丁字母:ABCDEFGHIJKLMNOPQRSTUVWXYZ,
  • 数字:0123456789,
  • 特殊字符:!#$%&'*+-/=?^_`{|}~,
  • 点号:.(不是第一个或最后一个字符,除非加引号 或 不重复),
  • 空格标点符号例如:"(),:;<>@[\](有一些限制),
  • 注释:()(在括号内允许,例如(comment)john.smith@example.com)。

域名部分:

  • 小写拉丁字母:abcdefghijklmnopqrstuvwxyz,
  • 大写拉丁字母:ABCDEFGHIJKLMNOPQRSTUVWXYZ,
  • 数字:0123456789,
  • 连字符:-(不是第一个或最后一个字符),
  • 可以包含IP地址,用方括号括起来:jsmith@[192.168.2.1]jsmith@[IPv6:2001:db8::1]

这些电子邮件地址是有效的:

  • prettyandsimple@example.com
  • very.common@example.com
  • disposable.style.email.with+symbol@example.com
  • other.email-with-dash@example.com
  • x@example.com (本地部分只有一个字母)
  • "much.more unusual"@example.com
  • "very.unusual.@.unusual.com"@example.com
  • "very.(),:;<>[]\".VERY.\"very@\ \"very\".unusual"@strange.example.com
  • example-indeed@strange-example.com
  • admin@mailserver1 (无顶级域的本地域名)
  • #!$%&'*+-/=?^_`{}|~@example.org
  • "()<>[]:,;@\\"!#$%&'-/=?^_`{}| ~.a"@example.org
  • " "@example.org (引号中间有空格)
  • example@localhost (从本地主机发送)
  • example@s.solutions (请参阅互联网顶级域列表
  • user@com
  • user@localserver
  • user@[IPv6:2001:db8::1]

以下是无效示例:

  • Abc.example.com(没有@字符)
  • A@b@c@example.com(引号外只允许一个@
  • a"b(c)d,e:f;gi[j\k]l@example.com(此本地部分中的特殊字符均不在引号外允许)
  • just"not"right@example.com(引号中的字符串必须由点分隔或是唯一构成本地部分的元素)
  • this is"not\allowed@example.com(空格、引号和反斜杠只有在引号内并且前面有反斜杠时才允许存在)
  • this\ still\"not\allowed@example.com(即使转义(前面有反斜杠),空格、引号和反斜杠仍必须包含在引号内)
  • john..doe@example.com@之前有两个点号);(附带说明:Gmail会通过此类地址)
  • john.doe@example..com@之后有两个点号)
  • 一个有前导空格的有效地址
  • 一个有尾随空格的有效地址

来源:维基百科的电子邮件地址页面


Perl's RFC2822正则表达式用于验证电子邮件地址:

(?:(?:\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*)

针对RFC2822地址的完整正则表达式仅为3.7k。

参考:PHP中的RFC 822电子邮件地址解析器.


电子邮件地址的正式定义在以下文档中:

  • RFC 5322(第3.2.3节和3.4.1节,取代RFC 2822)、RFC 5321、RFC 3696、
  • RFC 6531(允许使用的字符)。

相关内容:


23
作为对想要实施这个正则表达式的人的额外警告:不要这样做。只需要验证它是否符合“something@something.something”的格式,然后完成。 - Chris Sobolewski
1
虽然这样的代码不易维护,但解码并弄清其功能确实是一项不错的练习。 - unjankify
9
我说这简直是疯狂的。谁会在生产中使用它?正则表达式应该有一个不再使用的点,而它已经远远超过了那个点。 - tomuxmon
3
我经常看到的是“按照RFC822验证”。实际上,这通常并不是需要的。RFC822并没有定义可以发送到的地址;它定义了可以出现在消息中的地址,这两者并不相同。可以发送到的地址是由RFC821(SMTP)和后续标准确定的。特别地,该规范不允许注释,排除了像a@abc(bananas)def.com这样的可用RFC822地址但无法发送的地址。因此,许多电子邮件验证器正在针对错误的内容进行验证。 - Synchro
1
@ChrisSobolewski 绝对正确。此验证的目的是为了帮助用户,避免明显的错误(比如忘记@或类似的错误)。对电子邮件地址进行以“@”为分隔符的拆分,并检查是否返回两个非零字符串就足够了。 - undefined
显示剩余5条评论

26

维基百科有一篇很好的文章,而官方规范在这里

电子邮件地址的本地部分可以使用任何以下ASCII字符:

  • 大小写英文字母(a-z,A-Z)
  • 数字0到9
  • 字符!#$%&'* + - / =?^ _ ` { | } ~
  • 字符.(点,句号,句点),但不能是第一个或最后一个字符,并且也不能连续出现两次以上。

此外,引用字符串(即:“John Doe”@example.com)是允许的,因此允许那些本来被禁止的字符,不过它们并不常用。RFC 5321还警告“期望接收邮件的主机应避免定义需要(或使用)引用字符串形式的本地部分的邮箱”。


@WildWezyr 合法的主机名可以是 IP 地址、FQN 或可解析为本地网络主机的其他内容。 - JensenDied
引用字符串对于通过网关是必不可少的,还记得Banyan Vines吗? - mckenzm

16
您可以从维基百科文章开始:
  • 大写和小写的英文字母(a-z,A-Z)
  • 数字0到9
  • 字符!# $%& ' * + - / =?^_ `{|}〜
  • 句号“。”(点号,句号)只要它不是第一个或最后一个字符,并且也不连续出现两次或更多。

13

在讨论电子邮件地址的有效本地部分时,被接受的答案提到了维基百科文章,但维基百科不是这方面的权威。 IETF RFC 3696则是这方面的权威文件,应参考第5页的第3节:电子邮件地址限制:

现代电子邮件地址由一个“本地部分”和一个“域部分”(完全合格的域名)组成,中间用at-sign(“@”)隔开。域��分的语法与上一节中的语法相似。该节中指出的有关过滤和名称列表的问题同样适用于电子邮件环境中使用的域名。域名也可以用方括号中的IP地址替换,但强烈不建议除了测试和故障排除之外的其他情况下使用。

本地部分可以使用下面描述的引号约定来显示。在实践中很少使用引号形式,但对于某些合法目的而言是必需的。因此,在过滤例程中不应拒绝引号形式,而应将其传递给电子邮件系统以供目标主机评估。

确切的规则是任何ASCII字符(包括控制字符)都可以出现在引号��或引用字符串中。当需要引用时,使用反斜杠字符来引用下一个字符。例如:

  Abc\@def@example.com

是一个有效的电子邮件地址格式。空格也可以出现,例如

  Fred\ Bloggs@example.com

反斜杠字符也可以用来引用自身,例如:

  Joe.\\Blow@example.com

除了使用反斜杠字符进行引用外,通常也可以使用传统的双引号字符来包含字符串。例如:

In addition to quoting using the backslash character, conventional double-quote characters may be used to surround strings. For example


  "Abc@def"@example.com

  "Fred Bloggs"@example.com

第一段中提到的前两个例子的替代形式。这些带引号的形式很少被推荐,在实践中也不常见。但是,如上所述,处理电子邮件地址的应用程序必须支持这些形式。特别是,带引号的形式经常出现在与其他系统和环境转换相关的地址上;这些转换要求仍然存在,而且由于接受用户提供的电子邮件地址的系统不能“知道”该地址是否与旧系统相关联,因此必须接受并传递这些地址形式到电子邮件环境中。

没有引号时,本地部分可以由任何字母字符、数字或任何特殊字符组合而成。

  ! # $ % & ' * + - / = ?  ^ _ ` . { | } ~

句点(“.”)也可能出现,但不能用于开始或结束本地部分,也不能连续出现两个或更多个句点。换句话说,任何ASCII图形(可打印)字符,除了at符号(“@”),反斜杠,双引号,逗号或方括号之外,都可以不带引号出现。如果要显示这些被排除的字符中的任何一个,则必须进行引用。例如表单:

  user+mailbox@example.com

  customer/department=shipping@example.com

  $A12345@example.com

  !def!xyz%abc@example.com

  _somename@example.com

像其他人一样,我提交了一个正则表达式,可以用于验证PHP和JavaScript的电子邮件地址:

are valid and are seen fairly regularly, but any of the characters listed above are permitted.

/^[a-z0-9!'#$%&*+\/=?^_`{|}~-]+(?:\.[a-z0-9!'#$%&*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-zA-Z]{2,}$/i

1
从技术上讲,电子邮件地址也被允许在顶级域中,因此您可以考虑将最后一组的“+”更改为“*”。另一方面,从技术上讲,在顶级域中有效的地址可能是一个空白的打字错误,因为这些地址远不如常见。规范与生活...;-) - Cromax
@Cromax - 没错。我们必须在我们能做的和通常做的之间找到一个平衡点。 - Mac

13

谷歌在其gmail.com地址上做了一件有趣的事情。Gmail.com地址仅允许字母(a-z),数字和点号(忽略点号)。例如,pikachu@gmail.com与pi.kachu@gmail.com相同,这两个电子邮件地址将发送到同一个邮箱。PIKACHU@gmail.com也会投递到同一个邮箱。

因此,回答这个问题有时取决于实现者希望遵循多少RFC标准。谷歌的gmail.com地址风格与标准兼容。他们这样做是为了避免不同的人使用类似的电子邮件地址导致混淆,例如:

*** gmail.com accepting rules ***
d.oy.smith@gmail.com   (accepted)
d_oy_smith@gmail.com   (bounce and account can never be created)
doysmith@gmail.com     (accepted)
D.Oy'Smith@gmail.com   (bounce and account can never be created)

维基百科链接是关于电子邮件地址通常允许什么的好参考。 http://en.wikipedia.org/wiki/Email_address


3
是的,关于为什么Gmail不允许使用这个创建电子邮件,您给出了一个很好的答案。但是您可以轻松地发送和接收来自 {john'doe}@my.server 的电子邮件,也在 hMail 服务器上进行了测试。 - Piotr Kula
您可以通过向{piotr'kula}@kula.solutions发送电子邮件来测试您的客户端 - 如果它能正常工作,您将会收到一个漂亮的自动回复。否则,什么也不会发生。 - Piotr Kula
3
Gmail遵循RFC 6530标准,也就是说,Gmail允许的每个电子邮件地址都符合RFC标准。但是,Gmail会根据额外的规则进一步限制可接受的地址集,并将在本地部分中带有点号(.)、可选加号(+)和字母数字字符的地址视为同义地址。 - Teemu Leisti
谷歌限制账户创建标准... 我想象他们会清除传入的电子邮件账户字符串中的额外“标点符号”和前缀加号别名字符串,以便将邮件路由到正确的账户。很容易。 这样一来,他们有效地不允许人们创建仅仅是为了恶作剧而设立的电子邮件地址,因此创建的有效地址通常可以通过简单甚至最复杂的验证。 - BradChesney79
不仅仅是Gmail,一些提供商有“中继过滤器”,会拒绝某些带有“=”的引用字符串,特别是作为分隔符的字符串。这是为了阻止用户设置网关并将垃圾邮件地址嵌套在私人引用字符串中。 "@"是有效的,但“=@=”不是(被认为)有效的。 - mckenzm

11

检查是否包含@和.,然后发送电子邮件进行验证。

20%的网站仍然无法使用我的.name电子邮件地址,因为有些人在验证电子邮件时出了问题,或者因为该地址早于新地址有效期。


9
即使不加点也没问题;我至少听说过一个顶级域名(具体是.ua)的电子邮件地址是<name>@ua -- 没有点!请注意,这并非严格必要。 - user1311045
这基本上是避免破坏验证的最简单方法,因为几乎一切都被允许,如果有不被允许的内容,接收方的服务器会通知您。 - Avamander

8

名称:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&'*+-/=?^_`{|}~.

服务器:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.

5
<>[] 怎么办?例如:"()<>[]:,;@\\\"!#$%&'-/=?^_{}| ~.a"@example.org`? - kenorb
24
请引用来源。没有来源的话,这看起来像是猜测。 - Mathieu K.
17
这已经过时了,可能从来就不正确。 - Jason Harrison

7
简短回答是有两个答案。一个是你应该做的标准,即明智且不会让你陷入麻烦的行为。另一个(更广泛)的标准是你应该接受而不引起麻烦的行为。这种二元性在发送和接受电子邮件方面有效,但在生活中也有广泛的应用。
要了解创建地址的好指南,请参见:https://www.jochentopf.com/email/chars.html
要过滤有效的电子邮件,只需传递任何足够清晰以看到下一步的内容。或者开始阅读一堆RFCs,注意,这里可能会有问题。

1
链接已经消失了。那里有什么内容? - ygoe
@ygoe,是的,网站挂了。这里是2012年左右的存档版本:http://web.archive.org/web/20120807105804/https://www.remote.org/jochen/mail/info/chars.html - MilMike
@MilMike 谢谢,我从那里找到了该页面的新URL并编辑了答案。 - ygoe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接