百度下邮箱格式的正则表示,能够搜索到各式各样,五花八门的表示。如果没有仔细甄别,错误使用其中的一些代码,则很可能造成在遇到一些特殊的邮箱格式时无法识别。这里就分析下邮件相关的RFC标准,可详见RFC 5322,Internet Message Format或[2-RFC5322],但在此之前需要先学习下[1-RFC5234]中关于ABNF的核心规则。
[1-RFC5234] 中Appendix B. Core ABNF of ABNF
B.1. Core Rules
ALPHA=%x41-5A/%x61-7A;A-Z/a-z BIT="0"/"1" CHAR=%x01-7F;any7-bitUS-ASCIIcharacter,excludingNUL CR=%x0D;carriagereturn CRLF=CRLF;Internetstandardnewline CTL=%x00-1F/%x7F;controls DIGIT=%x30-39;0-9 DQUOTE=%x22;"(DoubleQuote) HEXDIG=DIGIT/"A"/"B"/"C"/"D"/"E"/"F" HTAB=%x09;horizontaltab LF=%x0A;lineFeed LWSP=*(WSP/CRLFWSP) ;USEOfthislinear-white-spacerule ;permitslinescontainingonlywhite ;spacethatarenolongerlegalin ;mailheadersandhavecaused ;interoperabilityproblemsinother ;contexts. ;Donotusewhendefiningmail ;headersandusewithcautionin ;othercontexts. OCTET=%x00-FF;8bitsofdata SP=%x20;space VCHAR=%x21-7E;visible(printing)characters WSP=SP/HTAB;whitespace
以下内容见[2-RFC5322],章节编号与原文保持一致。
2 Message词法分析(Lexical Analysis of Messages)
取值范围在1-127的字符被称为US-ASCII字符.
Messages可分为许多行字符,一行是用两个相连的字符carriage-return(CR: ASCII码值13)与line-Feed(LF: ASCII码值10)分隔, 通常写作CRLF.
Message是由header字段,可选的body字段组成。
header section是由一些特定语法的许多行组成, header section后面是一个空行,接下来是body字段。
本规范中使用header field描述单个字段,用header section描述所有header字段。
每一行字符数务必(MUST)不能超过998个,不包括CRLF以外通常不应当超过78个字符。
998加上CRLF达到1000个字符,有许多接收方实现限定一行不能超过1000个字符。
78加上CRLF达到80个字符,有许多显示界面一行超过80个字符后被截断或显示到下一行。
Header Fields先是一个field name,接下来是一个冒号,接下来是一个field body,后面是CLRF.
field name必须是可打印US-ASCII字符组成,即值为[33,126]之间除冒号以外的字符。
field body必须是可打印US-ASCII字符,空格(SP:ASCII码值32),horizontal tab(HTAB:
ASCII码值9)字符组成。SP与HTAB组合即为WSP(white space characters).
field body务必不能(MUST NOT)包含CRLF,除了用于"folding"与"unfolding"以外。
一些field body被称为"unstructured",表示无需进一步处理的单行字符。
一些field body被称为"structured",由一些特殊token组成,这些token后面可以有comments与空格字符.
每个header field通常是由一行字符,由field name,冒号和field body组成。
考虑到需要处理每行有998/78字符,header field中的field body部分可用多行来表示,这被称为"folding".
例如下面header field:
Subject: This is a test
可以被表示为
Subject: This
is a test
从folded多行变为单行的过程被称为"unfolding",即去掉CRLF并立即跟一个WSP.
每个header field应当用其unfolded格式来做进一步的语法与此法分析。
unfolded header field没有长度限制。
3. 语法(Syntax)
3.2 词法(Lexical)tokens
3.2.1. Quoted characters
quoted-pair=("\"(VCHAR/WSP))/obs-qp
3.2.2. Folding White Space and Comments
header字段bodies中,许多elements之间可以存在空白字符(White space characters),这里的字符包含用于folding的空格;
圆括号(parentheses)中的字符串被视为comments。
下面定义了folding white space (FWS)和comment结构。
圆括号(parentheses)中的字符串只要不是在引号串内就被视为comments,Comments可以嵌套(nest).
有一些地方可随意插入comments与FWS,为此新定义一个"CFWS" token.
但是,在一个folded header字段的任意一行,不能都是由WSP字符组成。
FWS=([*WSPCRLF]1*WSP)/obs-FWS ;Foldingwhitespace ctext=%d33-39/;可打印US-ASCII字符,%d42-91/;取值在[33-126]范围内但不包含 %d93-126/;40="(",41=")",or92="\" obs-ctext %d33-39: 33:"!" 34:""" 35:"#" 36:"$" 37:"%" 38:"&" 39:"'" 42"*" 43"+" 44"、" 45"-" 46"." 47"/" 48-57:"0"-"9" 58:":" 59:";" 60:"<" 61:"=" 62:">" 63:"?" 64:"@" 65-90:"A-Z" 91:"[" 93:"]" 94:"^" 95:"-" 96:"'" 97-122:"a-z" 123:"{" 124:"|" 125:"}" 126:"~" ccontent=ctext/quoted-pair/comment comment="("*([FWS]ccontent)[FWS]")" CFWS=(1*([FWS]comment)[FWS])/FWS
3.2.3. Atom
在structured header field bodies中有一些productions是由一些基本字符组成的简单串,
这些productions被称为atoms.
但有一些productions允许句点字符(".",ASCII值为46),因此引入"dot-atom" token来表示这种情况。
atext=ALPHA/DIGIT/;不包含specials的可打印US-ASCII字符 "!"/"#"/;用于atoms. "$"/"%"/ "&"/"'"/ "*"/"+"/ "-"/"/"/ "="/"?"/ "^"/"_"/ "`"/"{"/ "|"/"}"/ "~" atom=[CFWS]1*atext[CFWS] dot-atom-text=1*atext*("."1*atext) dot-atom=[CFWS]dot-atom-text[CFWS] specials="("/")"/;atext中未出现的特殊字符 "<"/">"/ "["/"]"/ ":"/";"/ "@"/"\"/ ","/"."/ DQUOTE
3.2.4. Quoted Strings
用双引号(DQUOTE,ASCII值34)包含的串.
qtext=%d33/;不包含双引号"""与反斜杠"\"的可打印字符。 %d35-91/ %d93-126/ obs-qtext qcontent=qtext/quoted-pair quoted-string=[CFWS] DQUOTE*([FWS]qcontent)[FWS]DQUOTE [CFWS]
用双引号包含的串被称为一个unit,即双引号串在语法上与atom一致。
因为双引号串可包含FWS,即允许folding.
而且注意双引号串中可以有双引号串,引起可以有双引号字符与反斜杠(backslash)字符。
从语法上讲,双引号串中的"\"与FWS/CFWS中的CRLF都是不可见的,因此它们不是双引号串的一部分。
3.2.5. 其他Tokens
定义三个token: word与phrase用于atoms和/或双引号串的组合,unstructured 用于
unstructured header字段,以及structured header字段中的一些地方.
word=atom/quoted-string phrase=1*word/obs-phrase unstructured=(*([FWS]VCHAR)*WSP)/obs-unstruct
3.3. Date与Time规范
date-time=[day-of-week","]datetime[CFWS] day-of-week=([FWS]day-name)/obs-day-of-week day-name="Mon"/"Tue"/"Wed"/"Thu"/"Fri"/"Sat"/"Sun" date=daymonthyear;应当表示本地时间 day=([FWS]1*2DIGITFWS)/obs-day;一个月的第几天 month="Jan"/"Feb"/"Mar"/"Apr"/ "May"/"Jun"/"Jul"/"Aug"/ "Sep"/"Oct"/"Nov"/"Dec" year=(FWS4*DIGITFWS)/obs-year;四位数字 time=time-of-dayzone time-of-day=hour":"minute[":"second];应当表示本地时间,一天中的时:分[:秒],;范围00:00:00-23:59:60 hour=2DIGIT/obs-hour minute=2DIGIT/obs-minute second=2DIGIT/obs-second zone=(FWS("+"/"-")4DIGIT)/obs-zone ;date与time-of-day偏离UTC或GMT的偏差\ ;+表示aheadof(即eastof)UTC,-表示behind(即westof)UTC ;前两个数字表示hours偏差,后两个数字表示minutes偏差 ;+hhmm表示+(hh*60+mm)分钟,-hhmm表示-(hh*60+mm)分钟 ;"+0000"用于表示UTC的时区 ;"-0000"用于表示本地时区生成的时间,date-time不包含本地时区的信息
3.4. Address规范
Addresses表示messages的接收与发送方.
一个address可以是单个邮箱,也可以是一组邮箱。
address=mailBox/group mailBox=name-addr/addr-spec name-addr=[display-name]angle-addr angle-addr=[CFWS]"<"addr-spec">"[CFWS]/ obs-angle-addr group=display-name":"[group-list]";"[CFWS] display-name=phrase mailBox-list=(mailBox*(","mailBox))/obs-mBox-list address-list=(address*(","address))/obs-addr-list group-list=mailBox-list/CFWS/obs-group-list
一个mailBox通常由两部分组成:(1) 一个可选的display-name,(2) 用<>封装的addr-spec地址。
mailBox的一岁简化形式是只有addr-spec地址,没有接收方名称,也没有<>。
3.4.1. Addr-Spec规范
addr-spec=local-part"@"domain local-part=dot-atom/quoted-string/obs-local-part domain=dot-atom/domain-literal/obs-domain domain-literal=[CFWS]"["*([FWS]dtext)[FWS]"]"[CFWS] dtext=%d33-90/;可打印US-ASCII字符,%d94-126/;不包含"[","]",or"\" obs-dtext
3.5. Overall Message Syntax
message由header fields,接下来是一个可选的message body.
message中的一行最大998个字符,推荐最大为78个字符,这里都不包含CRLF.
在message body中,虽然在text rule中列出的所有字符都可以用,但不鼓励使用US-ASCII控制字符(值1到8,11,12,14-31),
因为无法保证接收方如何来显示它们。
message=(fields/obs-fields) [CRLFbody] body=(*(*998textCRLF)*998text)/obs-body text=%d1-9/;CharactersexcludingCR %d11/;andLF %d12/ %d14-127
其他略。。。
邮箱地址格式主要参见上面的3.4.1. Addr-Spec规范,建议参照这里的规范来编写正则表达式,如果自己没有能力编写正则表达式则建议直接采用PHP、JAVA、C#、C++、C等语言中现成的库来判断。
参考资料:
[1-RFC5234] RFC 5234,Augmented BNF for Syntax Specifications: ABNF,Standards Track,January 2008,http://www.rfc-editor.org/rfc/rfc5234.txt
[2-RFC5322]RFC 5322,Internet Message Format,October 2008,http://www.rfc-editor.org/rfc/rfc5322.txt