Module: MailAuth::Spf::Macro
- Defined in:
- lib/mailauth/spf/macro.rb
Overview
RFC 7208 §7. The little templating language a record uses to build a name
out of the message in front of it — exists:%{ir}.%{d} asks a question
about this particular client rather than about the domain in general.
Constant Summary collapse
- DELIMITERS =
Whatever a transformer splits on, the pieces are rejoined with dots — the result is going into a domain name.
".-+,/_="- EXPANSION =
The expansion form, plus the three escapes, ordered so a lone
%only matches once nothing legal does — exactly when it's a syntax error. /%\{([^}]*)\}|%%|%_|%-|%/- BODY =
macro-letter transformers *delimiter
/\A([a-z])(\d*)([r]?)([#{Regexp.escape(DELIMITERS)}]*)\z/i- RESERVED =
RFC 3986's unreserved set. An uppercase macro letter expands the same as its lowercase twin and then URL-escapes everything outside this.
/[^A-Za-z0-9\-._~]/- TOPLABEL =
toplabel = ( *alphanum ALPHA alphanum ) / ( 1alphanum "-" *( alphanum / "-" ) alphanum )
/(?:[a-z0-9]*[a-z][a-z0-9]*|[a-z0-9]+-[a-z0-9\-]*[a-z0-9])/i- DOMAIN_END =
The tail of a domain-spec must be a real label rather than something a macro happened to produce, or a macro expansion standing alone.
/\.#{TOPLABEL}\.?\z/o
Class Method Summary collapse
-
.domain_spec(string, context) ⇒ Object
Checked before expansion, not after — a macro may expand into something no resolver will answer for, but that fails the mechanism, not the record.
-
.expand(string, context) ⇒ Object
Raises PermError on anything the ABNF doesn't allow: a record that can't be parsed can't be obeyed.
Class Method Details
.domain_spec(string, context) ⇒ Object
Checked before expansion, not after — a macro may expand into something no resolver will answer for, but that fails the mechanism, not the record.
47 48 49 50 51 52 53 54 55 |
# File 'lib/mailauth/spf/macro.rb', line 47 def domain_spec(string, context) if string.to_s.empty? raise PermError, "empty domain-spec" elsif !ends_well?(string) raise PermError, "domain-spec #{string} does not end in a macro or a top-level label" else (string, context).downcase.chomp(".") end end |
.expand(string, context) ⇒ Object
Raises PermError on anything the ABNF doesn't allow: a record that can't be parsed can't be obeyed.
32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/mailauth/spf/macro.rb', line 32 def (string, context) string.to_s.gsub(EXPANSION) do |match| case match when "%%" then "%" when "%_" then " " when "%-" then "%20" when "%" then raise PermError, "stray % in #{string}" else expansion(Regexp.last_match(1), context) end end end |