agaridata / spf-ruby Goto Github PK
View Code? Open in Web Editor NEWRuby implementation of the Sender Policy Framework
Ruby implementation of the Sender Policy Framework
Could you add some simple documentation to the readme ?
I'm looking for a lib to verify that a spf record is set up correctly, for example "is our server allowed to send emails for [email protected]"
Look like a small bug in the spec_helper.rb -- it tries to require 'spf-ruby', but it really ought to be require 'spf. I'd offer a pull, but it seems you all aren't interested in contributions.
Cheers!
Hi,
This looks like a really useful gem. Ruby's first and only full SPF implementation!
It's probably difficult for anyone other than hobbyists to make use of it right now, though. Do you think you'd consider opening it up to a more permissive license, like MIT?
When running the below command:
spf_server = SPF::Server.new
spf_server.process(SPF::Request.new(scope: "mfrom", identity: "[email protected]", ip_address: "206.123.2.240"))
I am getting the following error:
NoMethodError: undefined method `new' for #<SPF::MacroString:0x0000564e0fca8830>
from /home/user/.rvm/gems/ruby-2.7.4/gems/spf-0.0.54/lib/spf/model.rb:748:in `process'
Caused by SPF::Result::SoftFail: softfail (SPF::Result::SoftFail)
from /home/user/.rvm/gems/ruby-2.7.4/gems/spf-0.0.54/lib/spf/model.rb:1000:in `block in eval'
According the the error, the gem is trying to parse the exp
modifier.
I tried to validate the ip address/identity using the spf-check package, and it returned a Pass result, so the issue does not seem to be caused by malformed SPF record.
In case the SPF record of the domain gatineau.ca
changes, here are the current SPF records:
gatineau.ca text =
"v=spf1 include:spf.cyberimpact.com include:shops.shopify.com include:servers.mcsv.net include:outgoing1.vircom.com ip4:192.69.1.7/32 ip4:207.115.110.7/32 ip4:207.115.110.252/32 ip4:64.254.21.171/32 ip4:206.123.2.240/32 -all"
spf.cyberimpact.com text =
"v=spf1 ip4:50.56.176.200 ip4:50.56.187.251 ip4:45.61.49.183 ip4:45.61.49.253 ip4:67.212.92.20 ip4:184.149.61.112 ip4:204.154.174.0/23 ~all exp=spfexp.cyberimpact.com"
spfexp.cyberimpact.com text =
"Please see http://www.openspf.org/Why?s=mfrom;id=%{S};ip=%{C};r=%{R}"
shops.shopify.com text =
"v=spf1 ip4:35.203.94.235 ip4:35.203.3.51 ~all"
servers.mcsv.net text =
"v=spf1 ip4:205.201.128.0/20 ip4:198.2.128.0/18 ip4:148.105.8.0/21 -all"
outgoing1.vircom.com text =
"v=spf1 a ip4:207.115.110.0/24 ip4:207.115.106.114 ip4:192.69.1.0/24 ip4:207.96.143.7/32 a:outgoing1.vircom.com a:outgoing2.vircom.com -all"
spf-0.0.41/lib/spf/util.rb:105: invalid multibyte escape: /([\x00-\x1f\x7f-\xff])/ (SyntaxError)
This seems to be fixed by adding # encoding: US-ASCII
to the file, but I haven't reviewed all the implications
I've spent a significant amount of time trying to debug/fix this issue but the further down the rabbit hole I get, the more I'm worried that I don't fully understand how to handle global modifiers.
If you have an spf record that has includes:gmail.com
- Gmail subsequently uses a redirect global modifier redirect=_spf.google.com
(the entire txt record is v=spf1 redirect=_spf.google.com
)
When this gem goes into SPF::Record#eval
there are no @terms
for this subrequest so the .each
block just returns []
and the rescue SPF::Result => result
on line 1001 never gets hit which would break into the processing of the global mods. Result for this subrequest is nil
and when that's being raised (since we never processed the global_mod to get a result) we get TypeError: exception object expected
Even when I modify the conditional to check if there are global_mods present but no terms present and then hit global_mod.process(server, request, result)
for the one global_mod - SPF::Mod::Redirect
seems to incorrectly try and call authority_domain = @domain_spec.new({:server => server, :request => request})
(@domain_spec
is already a SPF::MacroString
and doesn't respond to new
). If SPF::Mod::Redirect
is modified to act like SPF::Mech::Include
and call
authority_domain = self.domain(server, request)
it will try to process all the sub requests for the redirect:_spf.google.com
but eventually returns nil
which bubbles up through the call stack and I'm eventually left in the same place with nil
trying to be raised somewhere along the line which produces TypeError: exception object expected
I would be more than happy to work on this with someone more knowledgeable but at this point I've just followed this so far down the hole to the point that I'm not sure I fully understand what's going on or would be able to without some assistance. ๐ค
Here's what happens if you just call the gem without any of the debugging/fixes that I've tried to put in place:
$ be irb 2.2.2
irb(main):001:0> require 'spf'
=> true
irb(main):002:0> spf_server = SPF::Server.new
=> #<SPF::Server:0x007fbed93910a8 @default_authority_explanation=#<SPF::MacroString:0x007fbed9390fe0 @text="Please see http://www.openspf.org/Why?s=%{_scope};id=%{S};ip=%{C};r=%{R}", @server=#<SPF::Server:0x007fbed93910a8 ...>, @request=nil, @expanded="Please see http://www.openspf.org/Why?s=%{_scope};id=%{S};ip=%{C};r=%{R}">, @hostname="scott-berke-mba.local", @dns_resolver=#<Resolv::DNS:0x007fbed9390bd0 @mutex=#<Mutex:0x007fbed9390b30>, @config=#<Resolv::DNS::Config:0x007fbed9390b08 @mutex=#<Mutex:0x007fbed9390a90>, @config_info=nil, @initialized=nil, @timeouts=nil>, @initialized=nil>, @query_rr_types=1, @max_dns_interactive_terms=10, @max_name_lookups_per_term=10, @max_name_lookups_per_mx_mech=10, @max_name_lookups_per_ptr_mech=10, @max_void_dns_lookups=2, @raise_exceptions=true>
irb(main):003:0> request = SPF::Request.new(
irb(main):004:1* versions: [1],
irb(main):005:1* scope: 'mfrom',
irb(main):006:1* identity: "[email protected]",
irb(main):007:1* ip_address: "167.89.50.131"
irb(main):008:1> )
=> #<SPF::Request:0x007fbed934aef0 @opt={:versions=>[1], :scope=>"mfrom", :identity=>"[email protected]", :ip_address=>"167.89.50.131"}, @state={}, @versions=[1], @scope=:mfrom, @authority_domain=nil, @identity="[email protected]", @ip_address=#<IP::V4 167.89.50.131>, @helo_identity=nil, @root_request=#<SPF::Request:0x007fbed934aef0 ...>, @super_request=#<SPF::Request:0x007fbed934aef0 ...>, @record=nil, @sub_requests=[], @localpart="example", @domain="gmail.com", @ip_address_v6=#<IP::V6 ::ffff:167.89.50.131>>
irb(main):009:0> spf_server.process(request)
TypeError: exception object expected
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:566:in `raise'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:566:in `match'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:989:in `block in eval'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:985:in `each'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:985:in `eval'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/eval.rb:103:in `process'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:799:in `process'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:1020:in `block in process_global_mods'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:1019:in `each'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:1019:in `process_global_mods'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:983:in `eval'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/eval.rb:103:in `process'
from (irb):9
from /Users/scottberke/.rbenv/versions/2.2.2/bin/irb:11:in `<main>'
irb(main):010:0> ```
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.