Module: MailerToGo::SPF
- Defined in:
- lib/mailertogo/spf.rb,
lib/mailertogo/spf/plan.rb,
lib/mailertogo/spf/record.rb,
lib/mailertogo/spf/result.rb,
lib/mailertogo/spf/sender.rb,
lib/mailertogo/spf/version.rb,
lib/mailertogo/spf/resolver.rb,
lib/mailertogo/spf/merge_plan.rb,
lib/mailertogo/spf/authorization.rb
Overview
An SPF engine that reads a record the way a receiving MTA does: it resolves the include chain, stops where the receiver stops, and counts DNS lookups against the RFC 7208 §4.6.4 cap.
Two questions, two entry points:
MailerToGo::SPF.authorize("example.com")
→ does this domain's published SPF authorize me?
MailerToGo::SPF.merge_plan("example.com")
→ what should I tell them to publish, given what is already there?
Both take include: (the mechanism you want authorized) and aliases:
(other names that mean the same sender). Both default to MailerToGo's own
names, so the zero-argument form is the useful one for MailerToGo customers
and one keyword makes it work for anybody else:
MailerToGo::SPF.("example.com", include: "spf.example.net")
Defined Under Namespace
Modules: Record Classes: Authorization, CachingResolver, MergePlan, Plan, Resolver, Result, Sender
Constant Summary collapse
- DEFAULT_INCLUDE =
MailerToGo publishes an outer alias and a leaf. Customers are told to include the leaf, but either one authorizes us, so both count as "me".
"_spf.mailertogo.net"- DEFAULT_ALIASES =
["mailertogo.net"].freeze
- VERSION =
"0.1.0"
Class Attribute Summary collapse
- .aliases ⇒ Object
-
.include ⇒ Object
writeonly
Sets the attribute include.
-
.logger ⇒ Object
Process-wide defaults.
-
.resolver ⇒ Object
Resolving is I/O, so the default is built once and shared.
Class Method Summary collapse
-
.authorize(hostname, include: nil, aliases: nil, resolver: nil, sender: nil, published: nil, logger: nil) ⇒ Object
Does
's published SPF authorize the sender? Returns a Result (see result.rb) — never raises for a DNS failure. - .configure {|_self| ... } ⇒ Object
- .include_name ⇒ Object
-
.merge_plan(name, record: nil, include: nil, aliases: nil, resolver: nil, sender: nil, authorization: nil, logger: nil) ⇒ Object
What should this domain publish, given what is already at that name? Returns a Plan (see plan.rb).
-
.sender(include: nil, aliases: nil) ⇒ Object
The names that mean "me".
Class Attribute Details
.aliases ⇒ Object
53 54 55 |
# File 'lib/mailertogo/spf.rb', line 53 def aliases defined?(@aliases) && @aliases ? @aliases : DEFAULT_ALIASES end |
.include=(value) ⇒ Object (writeonly)
Sets the attribute include
47 48 49 |
# File 'lib/mailertogo/spf.rb', line 47 def include=(value) @include = value end |
.logger ⇒ Object
Process-wide defaults. Everything here can also be passed per call.
MailerToGo::SPF.configure do |c|
c.include = "spf.example.net"
c.aliases = ["example.net"]
c.resolver = MailerToGo::SPF::CachingResolver.new(MailerToGo::SPF::Resolver.new)
c.logger = Logger.new($stdout)
end
46 47 48 |
# File 'lib/mailertogo/spf.rb', line 46 def logger @logger end |
Class Method Details
.authorize(hostname, include: nil, aliases: nil, resolver: nil, sender: nil, published: nil, logger: nil) ⇒ Object
Does
published: evaluates a supplied record as if it were published at
73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/mailertogo/spf.rb', line 73 def (hostname, include: nil, aliases: nil, resolver: nil, sender: nil, published: nil, logger: nil) sender ||= sender_for(include || include_name, aliases) raise ArgumentError, "no include name given or configured" if sender.nil? Authorization.call( hostname, sender: sender, resolver: resolver || self.resolver, published: published, logger: logger || self.logger ) end |
.configure {|_self| ... } ⇒ Object
63 64 65 66 |
# File 'lib/mailertogo/spf.rb', line 63 def configure yield self self end |
.include_name ⇒ Object
49 50 51 |
# File 'lib/mailertogo/spf.rb', line 49 def include_name defined?(@include) && @include ? @include : DEFAULT_INCLUDE end |
.merge_plan(name, record: nil, include: nil, aliases: nil, resolver: nil, sender: nil, authorization: nil, logger: nil) ⇒ Object
What should this domain publish, given what is already at that name? Returns a Plan (see plan.rb).
record: the standalone record you would otherwise hand them; defaults to
the sender's own v=spf1 include:… ~all.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/mailertogo/spf.rb', line 92 def merge_plan(name, record: nil, include: nil, aliases: nil, resolver: nil, sender: nil, authorization: nil, logger: nil) # A record with no include mechanism gives us no identity to merge in — # hand back a null plan rather than inventing one. sender ||= sender_for(include || (record.nil? ? include_name : Record.include_target(record)), aliases) return Plan.none(name: name, record: record) if sender.nil? MergePlan.call( name, record: record || sender.record, sender: sender, resolver: resolver || self.resolver, authorization: , logger: logger || self.logger ) end |
.sender(include: nil, aliases: nil) ⇒ Object
The names that mean "me". Public because a caller that asks both questions about the same sender should build it once.
111 112 113 |
# File 'lib/mailertogo/spf.rb', line 111 def sender(include: nil, aliases: nil) sender_for(include || include_name, aliases) end |