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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
-- Email Addresses
-- RFC 5322 Section 3.4.1
local lpeg = require "lpeg"
local P = lpeg.P
local R = lpeg.R
local S = lpeg.S
local V = lpeg.V
local C = lpeg.C
local Cg = lpeg.Cg
local Ct = lpeg.Ct
local Cs = lpeg.Cs
local core = require "lpeg_patterns.core"
local CHAR = core.CHAR
local CRLF = core.CRLF
local CTL = core.CTL
local DQUOTE = core.DQUOTE
local WSP = core.WSP
local VCHAR = core.VCHAR
local obs_NO_WS_CTL = R("\1\8", "\11\12", "\14\31") + P"\127"
local obs_qp = Cg(P"\\" * C(P"\0" + obs_NO_WS_CTL + core.LF + core.CR))
local quoted_pair = Cg(P"\\" * C(VCHAR + WSP)) + obs_qp
-- Folding White Space
local FWS = (WSP^0 * CRLF)^-1 * WSP^1 / " " -- Fold whitespace into a single " "
-- Comments
local ctext = R"\33\39" + R"\42\91" + R"\93\126"
local comment = P {
V"comment" ;
ccontent = ctext + quoted_pair + V"comment" ;
comment = P"("* (FWS^-1 * V"ccontent")^0 * FWS^-1 * P")";
}
local CFWS = ((FWS^-1 * comment)^1 * FWS^-1 + FWS ) / function() end
-- Atom
local specials = S[=[()<>@,;:\".[]]=]
local atext = CHAR-specials-P" "-CTL
local atom = CFWS^-1 * C(atext^1) * CFWS^-1
local dot_atom_text = C(atext^1 * ( P"." * atext^1 )^0)
local dot_atom = CFWS^-1 * dot_atom_text * CFWS^-1
-- Quoted Strings
local qtext = S"\33"+R("\35\91","\93\126")
local qcontent = qtext + quoted_pair
local quoted_string_text = DQUOTE * Cs((FWS^-1 * qcontent)^0 * FWS^-1) * DQUOTE
local quoted_string = CFWS^-1 * quoted_string_text * CFWS^-1
-- Miscellaneous Tokens
local word = atom + quoted_string
local obs_phrase = C(word * (word + P"." + CFWS)^0 / function() end)
local phrase = obs_phrase -- obs_phrase is more broad than `word^1`, it's really the same but allows "."
-- Addr-spec
local obs_dtext = obs_NO_WS_CTL + quoted_pair
local dtext = R("\33\90", "\94\126") + obs_dtext
local domain_literal_text = P"[" * Cs((FWS^-1 * dtext)^0 * FWS^-1) * P"]"
local domain_text = dot_atom_text + domain_literal_text
local local_part_text = dot_atom_text + quoted_string_text
local addr_spec_text = local_part_text * P"@" * domain_text
local domain_literal = CFWS^-1 * domain_literal_text * CFWS^-1
local obs_domain = Ct(atom * (C"." * atom)^0) / table.concat
local domain = obs_domain + dot_atom + domain_literal
local obs_local_part = Ct(word * (C"." * word)^0) / table.concat
local local_part = obs_local_part + dot_atom + quoted_string
local addr_spec = local_part * P"@" * domain
local display_name = phrase
local obs_domain_list = (CFWS + P",")^0 * P"@" * domain
* (P"," * CFWS^-1 * (P"@" * domain)^-1)^0
local obs_route = Cg(Ct(obs_domain_list) * P":", "route")
local obs_angle_addr = CFWS^-1 * P"<" * obs_route * addr_spec * P">" * CFWS^-1
local angle_addr = CFWS^-1 * P"<" * addr_spec * P">" * CFWS^-1
+ obs_angle_addr
local name_addr = Cg(display_name, "display")^-1 * angle_addr
local mailbox = name_addr + addr_spec
return {
local_part = local_part;
domain = domain;
email = addr_spec;
name_addr = name_addr;
mailbox = mailbox;
-- A variant that does not allow comments or folding whitespace
local_part_nocfws = local_part_text;
domain_nocfws = domain_text;
email_nocfws = addr_spec_text;
}
|