1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
%%{
# RFC 5322 Internet Message Format
# Section 3.4. Address Specification
# https://tools.ietf.org/html/rfc5322#section-3.4
machine rfc5322_address;
alphtype int;
include rfc5234_abnf_core_rules "rfc5234_abnf_core_rules.rl";
include rfc5322_lexical_tokens "rfc5322_lexical_tokens.rl";
# local_part:
domain_text = (DQUOTE (FWS? qcontent)+ FWS? DQUOTE) | atext+;
local_dot_atom_text = ("."* domain_text "."*)+;
local_dot_atom = CFWS?
(local_dot_atom_text >local_dot_atom_s %local_dot_atom_pre_comment_e)
CFWS?;
obs_local_part = word ("." word)*;
local_part = (local_dot_atom >local_dot_atom_s %local_dot_atom_e |
(quoted_string %local_quoted_string_e) |
obs_local_part);
# Treetop parser behavior was to ignore addresses missing '@' inside of angle
# brackets. This construction preserves that behavior.
local_part_no_capture = (local_dot_atom | quoted_string | obs_local_part);
# domain:
domain_dot_atom_text = "."* domain_text ("."* domain_text)*;
obs_dtext = obs_NO_WS_CTL | quoted_pair;
rfc5322_dtext = 0x21..0x5a | 0x5e..0x7e | obs_dtext;
dtext = rfc5322_dtext | utf8_non_ascii; # RFC6532 for UTF-8
domain_dot_atom = CFWS? domain_dot_atom_text (CFWS? >(comment_after_address,1));
domain_literal = CFWS? "[" (FWS? dtext)* FWS? "]" CFWS?;
obs_domain = atom ("." atom)*;
domain = (domain_dot_atom | domain_literal | obs_domain) >domain_s %domain_e;
# 3.4.1. Addr-Spec Specification
# The %(end_addr,N) priority resolves uncertainty when whitespace
# after an addr_spec could cause it to be interpreted as a
# display name: "bar@example.com ,..."
addr_spec_in_angle_brackets =
(local_part "@" domain) %(end_addr,1) |
local_part_no_capture %(end_addr,0);
addr_spec_no_angle_brackets =
(local_part "@" domain) %(end_addr,1) |
local_part %(end_addr,0);
# angle_addr:
obs_domain_list = (CFWS | ",")* "@" domain ("," CFWS? ("@" domain)?)*;
obs_route = (obs_domain_list ":") >obs_domain_list_s %obs_domain_list_e;
obs_angle_addr = CFWS? "<" obs_route? addr_spec_in_angle_brackets ">" CFWS?;
angle_addr = CFWS? ("<" >angle_addr_s) addr_spec_in_angle_brackets ">" CFWS? |
obs_angle_addr;
# 3.4. Address Specification
display_name = phrase;
name_addr = display_name? %(end_addr,2) angle_addr;
mailbox = (name_addr | addr_spec_no_angle_brackets) >address_s %address_e;
obs_mbox_list = (CFWS? ",")* mailbox ("," (mailbox | CFWS)?)*;
mailbox_list = (mailbox (("," | ";") mailbox)*) | obs_mbox_list;
obs_group_list = (CFWS? ",")+ CFWS?;
group_list = mailbox_list | CFWS | obs_group_list;
group = (display_name >group_name_s %group_name_e) ":"
(group_list?) ";" CFWS?;
address = group | mailbox;
#obs_addr_list = (CFWS? ",")* address ("," (address | CFWS)?)*;
address_lists = address? %(comment_after_address,0)
(FWS* ("," | ";") FWS* address?)*;
}%%
|