郵箱格式的正則表達式與RFC 5322 Internet Message Format

    百度下郵箱格式的正則表示,可以搜索到各式各樣,五花八門的表示。若是沒有仔細甄別,錯誤使用其中的一些代碼,則極可能形成在遇到一些特殊的郵箱格式時沒法識別。這裏就分析下郵件相關的RFC標準,可詳見RFC 5322,  Internet Message Format或[2-RFC5322], 但在此以前須要先學習下[1-RFC5234]中關於ABNF的核心規則。正則表達式

 

[1-RFC5234] 中Appendix B.  Core ABNF of ABNFshell

B.1.  Core Rulesdom

         ALPHA          =  %x41-5A / %x61-7A   ; A-Z / a-z
         BIT            =  "0" / "1"
         CHAR           =  %x01-7F         ; any 7-bit US-ASCII character, excluding NUL
         CR             =  %x0D            ; carriage return
         CRLF           =  CR LF           ; Internet standard newline
         CTL            =  %x00-1F / %x7F  ; controls
         DIGIT          =  %x30-39         ; 0-9
         DQUOTE         =  %x22            ; " (Double Quote)
         HEXDIG         =  DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
         HTAB           =  %x09            ; horizontal tab
         LF             =  %x0A            ; linefeed
         LWSP           =  *(WSP / CRLF WSP)
                                ; Use of this linear-white-space rule
                                ;  permits lines containing only white
                                ;  space that are no longer legal in
                                ;  mail headers and have caused
                                ;  interoperability problems in other
                                ;  contexts.
                                ; Do not use when defining mail
                                ;  headers and use with caution in
                                ;  other contexts.
         OCTET          =  %x00-FF       ; 8 bits of data
         SP             =  %x20          ; space 
         VCHAR          =  %x21-7E       ; visible (printing) characters
         WSP            =  SP / HTAB     ; white space

         

如下內容見[2-RFC5322], 章節編號與原文保持一致。 學習

2 Message詞法分析(Lexical Analysis of Messages) 
this

   取值範圍在1-127的字符被稱爲US-ASCII字符.atom

   

   Messages可分爲許多行字符,一行是用兩個相連的字符carriage-return(CR: ASCII碼值13)與line-feed(LF: ASCII碼值10)分隔, 一般寫做CRLF.spa

   

   Message是由header字段, 可選的body字段組成。code

   header section是由一些特定語法的許多行組成, header section後面是一個空行,接下來是body字段。orm

   本規範中使用header field描述單個字段,用header section描述全部header字段。token

   

   每一行字符數務必(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             =   ([*WSP CRLF] 1*WSP) /  obs-FWS
                                          ; Folding white space

   ctext           =   %d33-39 /          ; 可打印US-ASCII字符,
                       %d42-91 /          ; 取值在[33-126]範圍內但不包含
                       %d93-126 /         ; 40="(", 41=")", or 92="\"
                       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 "," ] date time [CFWS]

   day-of-week     =   ([FWS] day-name) / obs-day-of-week

   day-name        =   "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"

   date            =   day month year                 ; 應當表示本地時間

   day             =   ([FWS] 1*2DIGIT FWS) / obs-day ; 一個月的第幾天

   month           =   "Jan" / "Feb" / "Mar" / "Apr" /
                       "May" / "Jun" / "Jul" / "Aug" /
                       "Sep" / "Oct" / "Nov" / "Dec"

   year            =   (FWS 4*DIGIT FWS) / obs-year  ; 四位數字

   time            =   time-of-day zone

   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的誤差\
                       ; +表示ahead of(即east of)UTC, -表示behind(即west of) 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)
                       [CRLF body]

   body            =   (*(*998text CRLF) *998text) / obs-body

   text            =   %d1-9 /            ; Characters excluding CR
                       %d11 /             ;  and LF
                       %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, Standards Track, October 2008, http://www.rfc-editor.org/rfc/rfc5322.txt

相關文章
相關標籤/搜索