{"action":"created","issue":{"url":"https://api.github.com/repos/agaridata/spf-ruby/issues/12","labels_url":"https://api.github.com/repos/agaridata/spf-ruby/issues/12/labels{/name}","comments_url":"https://api.github.com/repos/agaridata/spf-ruby/issues/12/comments","events_url":"https://api.github.com/repos/agaridata/spf-ruby/issues/12/events","html_url":"https://github.com/agaridata/spf-ruby/issues/12","id":98447590,"number":12,"title":"Does not process redirect global mod correctly","user":{"login":"scottberke","id":4753728,"avatar_url":"https://avatars.githubusercontent.com/u/4753728?v=3","gravatar_id":"","url":"https://api.github.com/users/scottberke","html_url":"https://github.com/scottberke","followers_url":"https://api.github.com/users/scottberke/followers","following_url":"https://api.github.com/users/scottberke/following{/other_user}","gists_url":"https://api.github.com/users/scottberke/gists{/gist_id}","starred_url":"https://api.github.com/users/scottberke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scottberke/subscriptions","organizations_url":"https://api.github.com/users/scottberke/orgs","repos_url":"https://api.github.com/users/scottberke/repos","events_url":"https://api.github.com/users/scottberke/events{/privacy}","received_events_url":"https://api.github.com/users/scottberke/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-07-31T18:38:34Z","updated_at":"2015-07-31T18:44:43Z","closed_at":null,"body":"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. \r\n\r\nIf 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`) \r\n\r\nWhen 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`\r\n\r\nEven 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 \r\n`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`  \r\n\r\nI 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. :metal:\r\n\r\nHere's what happens if you just call the gem without any of the debugging/fixes that I've tried to put in place: \r\n```\r\n$ be irb                                                                                                                                                                                                 2.2.2\r\nirb(main):001:0> require 'spf'\r\n=> true\r\nirb(main):002:0>  spf_server = SPF::Server.new\r\n=> #<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>\r\nirb(main):003:0> request = SPF::Request.new(\r\nirb(main):004:1*         versions:      [1],\r\nirb(main):005:1*         scope:         'mfrom',\r\nirb(main):006:1*         identity:      \"example@gmail.com\",\r\nirb(main):007:1*         ip_address:    \"167.89.50.131\"\r\nirb(main):008:1>       )\r\n=> #<SPF::Request:0x007fbed934aef0 @opt={:versions=>[1], :scope=>\"mfrom\", :identity=>\"example@gmail.com\", :ip_address=>\"167.89.50.131\"}, @state={}, @versions=[1], @scope=:mfrom, @authority_domain=nil, @identity=\"example@gmail.com\", @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>>\r\nirb(main):009:0>  spf_server.process(request)\r\nTypeError: exception object expected\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom (irb):9\r\n\tfrom /Users/scottberke/.rbenv/versions/2.2.2/bin/irb:11:in `<main>'\r\nirb(main):010:0> ```"},"comment":{"url":"https://api.github.com/repos/agaridata/spf-ruby/issues/comments/126780599","html_url":"https://github.com/agaridata/spf-ruby/issues/12#issuecomment-126780599","issue_url":"https://api.github.com/repos/agaridata/spf-ruby/issues/12","id":126780599,"user":{"login":"scottberke","id":4753728,"avatar_url":"https://avatars.githubusercontent.com/u/4753728?v=3","gravatar_id":"","url":"https://api.github.com/users/scottberke","html_url":"https://github.com/scottberke","followers_url":"https://api.github.com/users/scottberke/followers","following_url":"https://api.github.com/users/scottberke/following{/other_user}","gists_url":"https://api.github.com/users/scottberke/gists{/gist_id}","starred_url":"https://api.github.com/users/scottberke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scottberke/subscriptions","organizations_url":"https://api.github.com/users/scottberke/orgs","repos_url":"https://api.github.com/users/scottberke/repos","events_url":"https://api.github.com/users/scottberke/events{/privacy}","received_events_url":"https://api.github.com/users/scottberke/received_events","type":"User","site_admin":false},"created_at":"2015-07-31T18:44:42Z","updated_at":"2015-07-31T18:44:42Z","body":"I apologize - The output above was actually with some of my attempted fixes. \r\nHere is the output from the unmodified gem:\r\n*sugarloafcut.com has the following txt record: `v=spf1 include:gmail.com ~all`\r\n```\r\n$ be irb                                                                                                                                                       2.2.2\r\nirb(main):001:0>  require 'spf'\r\n=> true\r\nirb(main):002:0> spf_server = SPF::Server.new\r\n=> #<SPF::Server:0x007fe8e28fd568 @default_authority_explanation=#<SPF::MacroString:0x007fe8e28fd4f0 @text=\"Please see http://www.openspf.org/Why?s=%{_scope};id=%{S};ip=%{C};r=%{R}\", @server=#<SPF::Server:0x007fe8e28fd568 ...>, @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:0x007fe8e28fd270 @mutex=#<Mutex:0x007fe8e28fd248>, @config=#<Resolv::DNS::Config:0x007fe8e28fd220 @mutex=#<Mutex:0x007fe8e28fd1f8>, @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>\r\nirb(main):003:0> request = SPF::Request.new(\r\nirb(main):004:1*         versions:      [1],\r\nirb(main):005:1*         scope:         'mfrom',\r\nirb(main):006:1*         identity:      \"example@sugarloafcut.com\",\r\nirb(main):007:1*         ip_address:    \"167.89.50.131\"\r\nirb(main):008:1>       )\r\n=> #<SPF::Request:0x007fe8e28cf7a8 @opt={:versions=>[1], :scope=>\"mfrom\", :identity=>\"example@sugarloafcut.com\", :ip_address=>\"167.89.50.131\"}, @state={}, @versions=[1], @scope=:mfrom, @authority_domain=nil, @identity=\"example@sugarloafcut.com\", @ip_address=#<IP::V4 167.89.50.131>, @helo_identity=nil, @root_request=#<SPF::Request:0x007fe8e28cf7a8 ...>, @super_request=#<SPF::Request:0x007fe8e28cf7a8 ...>, @record=nil, @sub_requests=[], @localpart=\"example\", @domain=\"sugarloafcut.com\", @ip_address_v6=#<IP::V6 ::ffff:167.89.50.131>>\r\nirb(main):009:0> \r\nirb(main):010:0*  spf_server.process(request)\r\nTypeError: exception object expected\r\n\tfrom /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'\r\n\tfrom /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'\r\n\tfrom /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:988:in `block in eval'\r\n\tfrom /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:984:in `each'\r\n\tfrom /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:984:in `eval'\r\n\tfrom /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'\r\n\tfrom (irb):10\r\n\tfrom /Users/scottberke/.rbenv/versions/2.2.2/bin/irb:11:in `<main>'\r\n```"}}