邮箱格式的正则表达式与RFC 5322 Internet Message Format

百度下邮箱格式的正则表示,能够搜索到各式各样,五花八门的表示。如果没有仔细甄别,错误使用其中的一些代码,则很可能造成在遇到一些特殊的邮箱格式时无法识别。这里就分析下邮件相关的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

相关文章

正则替换html代码中img标签的src值在开发富文本信息在移动端...
正则表达式
AWK是一种处理文本文件的语言,是一个强大的文件分析工具。它...
正则表达式是特殊的字符序列,利用事先定义好的特定字符以及...
Python界一名小学生,热心分享编程学习。
收集整理每周优质开发者内容,包括、、等方面。每周五定期发...