Giter Club home page Giter Club logo

spf-ruby's Introduction

SPF

The spf Ruby gem, also known as spf-ruby, is an implementation of the Sender Policy Framework (SPF) e-mail sender authentication system. It is closely based on the Mail::SPF Perl library at <search.cpan.org/~jmehnle/Mail-SPF-v2.005/>, so most of Mail::SPF’s documentation is applicable.

See <www.openspf.org> for more information about SPF.

Note: This gem is currently very early in its lifecycle. The API is not guaranteed to be stable.

Usage

require 'spf'

spf_server = SPF::Server.new

request = SPF::Request.new(
  versions:      [1, 2],             # optional
  scope:         'mfrom',            # or 'helo', 'pra'
  identity:      '[email protected]',
  ip_address:    '192.168.0.1',
  helo_identity: 'mta.example.com'   # optional
)

result = spf_server.process(request)

puts result

result_code   = result.code # :pass, :fail, etc.

Copyright 2016 Agari Data, Inc.

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this software except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

spf-ruby's People

Contributors

aflury avatar agarian-alex avatar attang avatar jcamenisch avatar jhakkinen avatar jmehnle avatar scottberke avatar snyk-bot avatar tweltz avatar valentin215 avatar vzctl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spf-ruby's Issues

Does not process redirect global mod correctly

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> ```

Licensing?

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?

How does this work ?

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]"

@aflury

invalid multibyte escape with ruby 2.x

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

Getting unexpected error when trying to validate SPF containing an "exp" modifier

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"

Incorrect require in spec_helper.rb

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!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.