coppertone 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/LICENSE +1 -1
  4. data/Rakefile +2 -2
  5. data/coppertone.gemspec +1 -0
  6. data/lib/coppertone/directive.rb +14 -7
  7. data/lib/coppertone/error.rb +24 -5
  8. data/lib/coppertone/ip_address_wrapper.rb +9 -6
  9. data/lib/coppertone/macro_context.rb +7 -13
  10. data/lib/coppertone/macro_string/macro_expand.rb +3 -2
  11. data/lib/coppertone/macro_string.rb +12 -5
  12. data/lib/coppertone/mechanism/a.rb +5 -1
  13. data/lib/coppertone/mechanism/all.rb +11 -4
  14. data/lib/coppertone/mechanism/cidr_parser.rb +1 -1
  15. data/lib/coppertone/mechanism/domain_spec_mechanism.rb +9 -0
  16. data/lib/coppertone/mechanism/domain_spec_optional.rb +1 -0
  17. data/lib/coppertone/mechanism/domain_spec_required.rb +1 -0
  18. data/lib/coppertone/mechanism/domain_spec_with_dual_cidr.rb +1 -0
  19. data/lib/coppertone/mechanism/exists.rb +5 -1
  20. data/lib/coppertone/mechanism/include.rb +17 -5
  21. data/lib/coppertone/mechanism/ip4.rb +5 -1
  22. data/lib/coppertone/mechanism/ip6.rb +5 -1
  23. data/lib/coppertone/mechanism/ip_mechanism.rb +9 -1
  24. data/lib/coppertone/mechanism/mx.rb +5 -1
  25. data/lib/coppertone/mechanism/ptr.rb +5 -1
  26. data/lib/coppertone/mechanism.rb +25 -2
  27. data/lib/coppertone/modifier/base.rb +1 -0
  28. data/lib/coppertone/modifier/exp.rb +6 -2
  29. data/lib/coppertone/modifier/redirect.rb +5 -1
  30. data/lib/coppertone/modifier/unknown.rb +6 -1
  31. data/lib/coppertone/modifier.rb +11 -2
  32. data/lib/coppertone/null_macro_context.rb +23 -0
  33. data/lib/coppertone/qualifier.rb +8 -0
  34. data/lib/coppertone/record.rb +33 -41
  35. data/lib/coppertone/record_finder.rb +3 -1
  36. data/lib/coppertone/record_term_parser.rb +30 -0
  37. data/lib/coppertone/request.rb +3 -1
  38. data/lib/coppertone/request_context.rb +1 -2
  39. data/lib/coppertone/result.rb +6 -2
  40. data/lib/coppertone/utils/validated_domain_finder.rb +6 -4
  41. data/lib/coppertone/version.rb +1 -1
  42. data/lib/coppertone.rb +3 -1
  43. data/spec/directive_spec.rb +13 -0
  44. data/spec/ip_address_wrapper_spec.rb +3 -0
  45. data/spec/macro_string_spec.rb +20 -0
  46. data/spec/mechanism/a_spec.rb +22 -7
  47. data/spec/mechanism/all_spec.rb +8 -0
  48. data/spec/mechanism/exists_spec.rb +14 -6
  49. data/spec/mechanism/include_spec.rb +13 -1
  50. data/spec/mechanism/ip4_spec.rb +15 -5
  51. data/spec/mechanism/ip6_spec.rb +18 -11
  52. data/spec/mechanism/mx_spec.rb +56 -0
  53. data/spec/mechanism/ptr_spec.rb +7 -0
  54. data/spec/modifier/exp_spec.rb +10 -0
  55. data/spec/modifier/redirect_spec.rb +10 -0
  56. data/spec/open_spf/ALL_mechanism_syntax_spec.rb +6 -6
  57. data/spec/open_spf/A_mechanism_syntax_spec.rb +30 -30
  58. data/spec/open_spf/EXISTS_mechanism_syntax_spec.rb +8 -8
  59. data/spec/open_spf/IP4_mechanism_syntax_spec.rb +10 -10
  60. data/spec/open_spf/IP6_mechanism_syntax_spec.rb +10 -10
  61. data/spec/open_spf/Include_mechanism_semantics_and_syntax_spec.rb +10 -10
  62. data/spec/open_spf/Initial_processing_spec.rb +21 -14
  63. data/spec/open_spf/MX_mechanism_syntax_spec.rb +22 -22
  64. data/spec/open_spf/Macro_expansion_rules_spec.rb +26 -30
  65. data/spec/open_spf/PTR_mechanism_syntax_spec.rb +7 -7
  66. data/spec/open_spf/Processing_limits_spec.rb +12 -12
  67. data/spec/open_spf/Record_evaluation_spec.rb +13 -13
  68. data/spec/open_spf/Record_lookup_spec.rb +8 -8
  69. data/spec/open_spf/Selecting_records_spec.rb +11 -11
  70. data/spec/open_spf/Semantics_of_exp_and_other_modifiers_spec.rb +27 -25
  71. data/spec/open_spf/Test_cases_from_implementation_bugs_spec.rb +2 -2
  72. data/spec/record_spec.rb +34 -13
  73. data/spec/request_context_spec.rb +1 -1
  74. data/spec/rfc7208-tests.yml +10 -0
  75. metadata +59 -48
  76. data/lib/coppertone/dns/error.rb +0 -9
  77. data/lib/coppertone/dns/mock_client.rb +0 -106
  78. data/lib/coppertone/dns/resolv_client.rb +0 -110
  79. data/lib/coppertone/dns.rb +0 -3
  80. data/lib/resolv/dns/resource/in/spf.rb +0 -15
  81. data/spec/dns/resolv_client_spec.rb +0 -307
@@ -5,52 +5,52 @@ describe 'Include mechanism semantics and syntax' do
5
5
  { 'mail.example.com' => [{ 'A' => '1.2.3.4' }], 'ip5.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.2.3.5 -all' }], 'ip6.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.2.3.6 ~all' }], 'ip7.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.2.3.7 ?all' }], 'ip8.example.com' => ['TIMEOUT'], 'erehwon.example.com' => [{ 'TXT' => 'v=spfl am not an SPF record' }], 'e1.example.com' => [{ 'TXT' => 'v=spf1 include:ip5.example.com ~all' }], 'e2.example.com' => [{ 'TXT' => 'v=spf1 include:ip6.example.com all' }], 'e3.example.com' => [{ 'TXT' => 'v=spf1 include:ip7.example.com -all' }], 'e4.example.com' => [{ 'TXT' => 'v=spf1 include:ip8.example.com -all' }], 'e5.example.com' => [{ 'TXT' => 'v=spf1 include:e6.example.com -all' }], 'e6.example.com' => [{ 'TXT' => 'v=spf1 include +all' }], 'e7.example.com' => [{ 'TXT' => 'v=spf1 include:erehwon.example.com -all' }], 'e8.example.com' => [{ 'TXT' => 'v=spf1 include: -all' }], 'e9.example.com' => [{ 'TXT' => 'v=spf1 include:ip5.example.com/24 -all' }] }
6
6
  end
7
7
 
8
- let(:dns_client) { Coppertone::DNS::MockClient.new(zonefile) }
8
+ let(:dns_client) { DNSAdapter::MockClient.new(zonefile) }
9
9
  let(:options) { { dns_client: dns_client } }
10
10
 
11
11
  it 'recursive check_host() result of fail causes include to not match.' do
12
12
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e1.example.com', 'mail.example.com', options)
13
- expect(%i(softfail)).to include(result.code)
13
+ expect([:softfail]).to include(result.code)
14
14
  end
15
15
 
16
16
  it 'recursive check_host() result of softfail causes include to not match.' do
17
17
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e2.example.com', 'mail.example.com', options)
18
- expect(%i(pass)).to include(result.code)
18
+ expect([:pass]).to include(result.code)
19
19
  end
20
20
 
21
21
  it 'recursive check_host() result of neutral causes include to not match.' do
22
22
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e3.example.com', 'mail.example.com', options)
23
- expect(%i(fail)).to include(result.code)
23
+ expect([:fail]).to include(result.code)
24
24
  end
25
25
 
26
26
  it 'recursive check_host() result of temperror causes include to temperror' do
27
27
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e4.example.com', 'mail.example.com', options)
28
- expect(%i(temperror)).to include(result.code)
28
+ expect([:temperror]).to include(result.code)
29
29
  end
30
30
 
31
31
  it 'recursive check_host() result of permerror causes include to permerror' do
32
32
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e5.example.com', 'mail.example.com', options)
33
- expect(%i(permerror)).to include(result.code)
33
+ expect([:permerror]).to include(result.code)
34
34
  end
35
35
 
36
36
  it 'include = "include" ":" domain-spec' do
37
37
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e6.example.com', 'mail.example.com', options)
38
- expect(%i(permerror)).to include(result.code)
38
+ expect([:permerror]).to include(result.code)
39
39
  end
40
40
 
41
41
  it 'include = "include" ":" domain-spec' do
42
42
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e9.example.com', 'mail.example.com', options)
43
- expect(%i(permerror)).to include(result.code)
43
+ expect([:permerror]).to include(result.code)
44
44
  end
45
45
 
46
46
  it 'recursive check_host() result of none causes include to permerror' do
47
47
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e7.example.com', 'mail.example.com', options)
48
- expect(%i(permerror)).to include(result.code)
48
+ expect([:permerror]).to include(result.code)
49
49
  end
50
50
 
51
51
  it 'domain-spec cannot be empty.' do
52
52
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e8.example.com', 'mail.example.com', options)
53
- expect(%i(permerror)).to include(result.code)
53
+ expect([:permerror]).to include(result.code)
54
54
  end
55
55
 
56
56
  end
@@ -1,77 +1,84 @@
1
+ # -- encoding : utf-8 --
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe 'Initial processing' do
4
6
  let(:zonefile) do
5
- { 'example.com' => ['TIMEOUT'], 'example.net' => [{ 'TXT' => 'v=spf1 -all exp=exp.example.net' }], 'a.example.net' => [{ 'TXT' => 'v=spf1 -all exp=exp.example.net' }], 'exp.example.net' => [{ 'TXT' => '%{l}' }], 'a12345678901234567890123456789012345678901234567890123456789012.example.com' => [{ 'TXT' => 'v=spf1 -all' }], 'hosed.example.com' => [{ 'TXT' => 'v=spf1 a:garbage.example.net -all' }], 'hosed2.example.com' => [{ 'TXT' => "v=spf1 \u0080a:example.net -all" }], 'hosed3.example.com' => [{ 'TXT' => "v=spf1 a:example.net \u0096all" }], 'nothosed.example.com' => [{ 'TXT' => 'v=spf1 a:example.net -all' }, { 'TXT' => "\u0096" }], 'ctrl.example.com' => [{ 'TXT' => "v=spf1 a:ctrl.example.com\rptr -all" }, { 'A' => '192.0.2.3' }] }
7
+ { 'example.com' => ['TIMEOUT'], 'example.net' => [{ 'TXT' => 'v=spf1 -all exp=exp.example.net' }], 'a.example.net' => [{ 'TXT' => 'v=spf1 -all exp=exp.example.net' }], 'exp.example.net' => [{ 'TXT' => '%{l}' }], 'a12345678901234567890123456789012345678901234567890123456789012.example.com' => [{ 'TXT' => 'v=spf1 -all' }], 'hosed.example.com' => [{ 'TXT' => 'v=spf1 a:garbage.example.net -all' }], 'hosed2.example.com' => [{ 'TXT' => "v=spf1 \u0080a:example.net -all" }], 'hosed3.example.com' => [{ 'TXT' => "v=spf1 a:example.net \u0096all" }], 'nothosed.example.com' => [{ 'TXT' => 'v=spf1 a:example.net -all' }, { 'TXT' => "\u0096" }], 'ctrl.example.com' => [{ 'TXT' => "v=spf1 a:ctrl.example.com\rptr -all" }, { 'A' => '192.0.2.3' }], 'fine.example.com' => [{ 'TXT' => 'v=spf1 a -all' }] }
6
8
  end
7
9
 
8
- let(:dns_client) { Coppertone::DNS::MockClient.new(zonefile) }
10
+ let(:dns_client) { DNSAdapter::MockClient.new(zonefile) }
9
11
  let(:options) { { dns_client: dns_client } }
10
12
 
11
13
  it 'DNS labels limited to 63 chars.' do
12
14
  # For initial processing, a long label results in None, not TempError
13
15
  result = Coppertone::SpfService.authenticate_email('1.2.3.5', 'lyme.eater@A123456789012345678901234567890123456789012345678901234567890123.example.com', 'mail.example.net', options)
14
- expect(%i(none)).to include(result.code)
16
+ expect([:none]).to include(result.code)
15
17
  end
16
18
 
17
19
  it 'DNS labels limited to 63 chars.' do
18
20
  result = Coppertone::SpfService.authenticate_email('1.2.3.5', 'lyme.eater@A12345678901234567890123456789012345678901234567890123456789012.example.com', 'mail.example.net', options)
19
- expect(%i(fail)).to include(result.code)
21
+ expect([:fail]).to include(result.code)
20
22
  end
21
23
 
22
24
  it 'emptylabel' do
23
25
  result = Coppertone::SpfService.authenticate_email('1.2.3.5', 'lyme.eater@A...example.com', 'mail.example.net', options)
24
- expect(%i(none)).to include(result.code)
26
+ expect([:none]).to include(result.code)
25
27
  end
26
28
 
27
29
  it 'helo-not-fqdn' do
28
30
  result = Coppertone::SpfService.authenticate_email('1.2.3.5', '', 'A2345678', options)
29
- expect(%i(none)).to include(result.code)
31
+ expect([:none]).to include(result.code)
30
32
  end
31
33
 
32
34
  it 'helo-domain-literal' do
33
35
  result = Coppertone::SpfService.authenticate_email('1.2.3.5', '', '[1.2.3.5]', options)
34
- expect(%i(none)).to include(result.code)
36
+ expect([:none]).to include(result.code)
35
37
  end
36
38
 
37
39
  it 'nolocalpart' do
38
40
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', '@example.net', 'mail.example.net', options)
39
- expect(%i(fail)).to include(result.code)
41
+ expect([:fail]).to include(result.code)
40
42
  expect(result.explanation).to eq('postmaster')
41
43
  end
42
44
 
43
45
  it 'domain-literal' do
44
46
  result = Coppertone::SpfService.authenticate_email('1.2.3.5', 'foo@[1.2.3.5]', 'OEMCOMPUTER', options)
45
- expect(%i(none)).to include(result.code)
47
+ expect([:none]).to include(result.code)
46
48
  end
47
49
 
48
50
  it 'SPF policies are restricted to 7-bit ascii.' do
49
51
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foobar@hosed.example.com', 'hosed', options)
50
- expect(%i(permerror)).to include(result.code)
52
+ expect([:permerror]).to include(result.code)
51
53
  end
52
54
 
53
55
  it 'SPF policies are restricted to 7-bit ascii.' do
54
56
  # Checking a possibly different code path for non-ascii chars.
55
57
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foobar@hosed2.example.com', 'hosed', options)
56
- expect(%i(permerror)).to include(result.code)
58
+ expect([:permerror]).to include(result.code)
57
59
  end
58
60
 
59
61
  it 'SPF policies are restricted to 7-bit ascii.' do
60
62
  # Checking yet another code path for non-ascii chars.
61
63
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foobar@hosed3.example.com', 'hosed', options)
62
- expect(%i(permerror)).to include(result.code)
64
+ expect([:permerror]).to include(result.code)
63
65
  end
64
66
 
65
67
  it 'Non-ascii content in non-SPF related records.' do
66
68
  # Non-SPF related TXT records are none of our business.
67
69
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foobar@nothosed.example.com', 'hosed', options)
68
- expect(%i(fail)).to include(result.code)
70
+ expect([:fail]).to include(result.code)
69
71
  expect(result.explanation).to eq('DEFAULT')
70
72
  end
71
73
 
72
74
  it 'Mechanisms are separated by spaces only, not any control char.' do
73
75
  result = Coppertone::SpfService.authenticate_email('192.0.2.3', 'foobar@ctrl.example.com', 'hosed', options)
74
- expect(%i(permerror)).to include(result.code)
76
+ expect([:permerror]).to include(result.code)
77
+ end
78
+
79
+ it 'ABNF for term separation is one or more spaces, not just one.' do
80
+ result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'actually@fine.example.com', 'hosed', options)
81
+ expect([:fail]).to include(result.code)
75
82
  end
76
83
 
77
84
  end
@@ -5,115 +5,115 @@ describe 'MX mechanism syntax' do
5
5
  { 'mail.example.com' => [{ 'A' => '1.2.3.4' }, { 'MX' => [0, ''] }, { 'TXT' => 'v=spf1 mx' }], 'e1.example.com' => [{ 'TXT' => 'v=spf1 mx/0 -all' }, { 'MX' => [0, 'e1.example.com'] }], 'e2.example.com' => [{ 'A' => '1.1.1.1' }, { 'AAAA' => '1234::2' }, { 'MX' => [0, 'e2.example.com'] }, { 'TXT' => 'v=spf1 mx/0 -all' }], 'e2a.example.com' => [{ 'AAAA' => '1234::1' }, { 'MX' => [0, 'e2a.example.com'] }, { 'TXT' => 'v=spf1 mx//0 -all' }], 'e2b.example.com' => [{ 'A' => '1.1.1.1' }, { 'MX' => [0, 'e2b.example.com'] }, { 'TXT' => 'v=spf1 mx//0 -all' }], 'e3.example.com' => [{ 'TXT' => "v=spf1 mx:foo.example.com\u0000" }], 'e4.example.com' => [{ 'TXT' => 'v=spf1 mx' }, { 'A' => '1.2.3.4' }], 'e5.example.com' => [{ 'TXT' => 'v=spf1 mx:abc.123' }], 'e6.example.com' => [{ 'TXT' => 'v=spf1 mx//33 -all' }], 'e6a.example.com' => [{ 'TXT' => 'v=spf1 mx/33 -all' }], 'e7.example.com' => [{ 'TXT' => 'v=spf1 mx//129 -all' }], 'e9.example.com' => [{ 'TXT' => 'v=spf1 mx:example.com:8080' }], 'e10.example.com' => [{ 'TXT' => 'v=spf1 mx:foo.example.com/24' }], 'foo.example.com' => [{ 'MX' => [0, 'foo1.example.com'] }], 'foo1.example.com' => [{ 'A' => '1.1.1.1' }, { 'A' => '1.2.3.5' }], 'e11.example.com' => [{ 'TXT' => 'v=spf1 mx:foo:bar/baz.example.com' }], 'foo:bar/baz.example.com' => [{ 'MX' => [0, 'foo:bar/baz.example.com'] }, { 'A' => '1.2.3.4' }], 'e12.example.com' => [{ 'TXT' => 'v=spf1 mx:example.-com' }], 'e13.example.com' => [{ 'TXT' => 'v=spf1 mx: -all' }] }
6
6
  end
7
7
 
8
- let(:dns_client) { Coppertone::DNS::MockClient.new(zonefile) }
8
+ let(:dns_client) { DNSAdapter::MockClient.new(zonefile) }
9
9
  let(:options) { { dns_client: dns_client } }
10
10
 
11
11
  it 'MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] ' do
12
12
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e6.example.com', 'mail.example.com', options)
13
- expect(%i(fail)).to include(result.code)
13
+ expect([:fail]).to include(result.code)
14
14
  end
15
15
 
16
16
  it 'MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] ' do
17
17
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e6a.example.com', 'mail.example.com', options)
18
- expect(%i(permerror)).to include(result.code)
18
+ expect([:permerror]).to include(result.code)
19
19
  end
20
20
 
21
21
  it 'MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] ' do
22
22
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e7.example.com', 'mail.example.com', options)
23
- expect(%i(permerror)).to include(result.code)
23
+ expect([:permerror]).to include(result.code)
24
24
  end
25
25
 
26
26
  it 'MX matches any returned IP.' do
27
27
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e10.example.com', 'mail.example.com', options)
28
- expect(%i(pass)).to include(result.code)
28
+ expect([:pass]).to include(result.code)
29
29
  end
30
30
 
31
31
  it 'MX matches any returned IP.' do
32
32
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e10.example.com', 'mail.example.com', options)
33
- expect(%i(pass)).to include(result.code)
33
+ expect([:pass]).to include(result.code)
34
34
  end
35
35
 
36
36
  it 'domain-spec must pass basic syntax checks' do
37
37
  # A \':\' may appear in domain-spec, but not in top-label.
38
38
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e9.example.com', 'mail.example.com', options)
39
- expect(%i(permerror)).to include(result.code)
39
+ expect([:permerror]).to include(result.code)
40
40
  end
41
41
 
42
42
  it 'If no ips are returned, MX mechanism does not match, even with /0.' do
43
43
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e1.example.com', 'mail.example.com', options)
44
- expect(%i(fail)).to include(result.code)
44
+ expect([:fail]).to include(result.code)
45
45
  end
46
46
 
47
47
  it 'Matches if any A records for any MX records are present in DNS.' do
48
48
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e2.example.com', 'mail.example.com', options)
49
- expect(%i(pass)).to include(result.code)
49
+ expect([:pass]).to include(result.code)
50
50
  end
51
51
 
52
52
  it 'cidr4 doesnt apply to IP6 connections.' do
53
53
  # The IP6 CIDR starts with a double slash.
54
54
  result = Coppertone::SpfService.authenticate_email('1234::1', 'foo@e2.example.com', 'mail.example.com', options)
55
- expect(%i(fail)).to include(result.code)
55
+ expect([:fail]).to include(result.code)
56
56
  end
57
57
 
58
58
  it 'Would match if any AAAA records for MX records are present in DNS, but not for an IP4 connection.' do
59
59
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e2a.example.com', 'mail.example.com', options)
60
- expect(%i(fail)).to include(result.code)
60
+ expect([:fail]).to include(result.code)
61
61
  end
62
62
 
63
63
  it 'Would match if any AAAA records for MX records are present in DNS, but not for an IP4 connection.' do
64
64
  result = Coppertone::SpfService.authenticate_email('::FFFF:1.2.3.4', 'foo@e2a.example.com', 'mail.example.com', options)
65
- expect(%i(fail)).to include(result.code)
65
+ expect([:fail]).to include(result.code)
66
66
  end
67
67
 
68
68
  it 'Matches if any AAAA records for any MX records are present in DNS.' do
69
69
  result = Coppertone::SpfService.authenticate_email('1234::1', 'foo@e2a.example.com', 'mail.example.com', options)
70
- expect(%i(pass)).to include(result.code)
70
+ expect([:pass]).to include(result.code)
71
71
  end
72
72
 
73
73
  it 'No match if no AAAA records for any MX records are present in DNS.' do
74
74
  result = Coppertone::SpfService.authenticate_email('1234::1', 'foo@e2b.example.com', 'mail.example.com', options)
75
- expect(%i(fail)).to include(result.code)
75
+ expect([:fail]).to include(result.code)
76
76
  end
77
77
 
78
78
  it 'Null not allowed in top-label.' do
79
79
  result = Coppertone::SpfService.authenticate_email('1.2.3.5', 'foo@e3.example.com', 'mail.example.com', options)
80
- expect(%i(permerror)).to include(result.code)
80
+ expect([:permerror]).to include(result.code)
81
81
  end
82
82
 
83
83
  it 'Top-label may not be all numeric' do
84
84
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e5.example.com', 'mail.example.com', options)
85
- expect(%i(permerror)).to include(result.code)
85
+ expect([:permerror]).to include(result.code)
86
86
  end
87
87
 
88
88
  it 'Domain-spec may contain any visible char except %' do
89
89
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e11.example.com', 'mail.example.com', options)
90
- expect(%i(pass)).to include(result.code)
90
+ expect([:pass]).to include(result.code)
91
91
  end
92
92
 
93
93
  it 'Domain-spec may contain any visible char except %' do
94
94
  result = Coppertone::SpfService.authenticate_email('::FFFF:1.2.3.4', 'foo@e11.example.com', 'mail.example.com', options)
95
- expect(%i(pass)).to include(result.code)
95
+ expect([:pass]).to include(result.code)
96
96
  end
97
97
 
98
98
  it 'Toplabel may not begin with -' do
99
99
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e12.example.com', 'mail.example.com', options)
100
- expect(%i(permerror)).to include(result.code)
100
+ expect([:permerror]).to include(result.code)
101
101
  end
102
102
 
103
103
  it 'test null MX' do
104
104
  # Some implementations have had trouble with null MX
105
105
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', '', 'mail.example.com', options)
106
- expect(%i(neutral)).to include(result.code)
106
+ expect([:neutral]).to include(result.code)
107
107
  end
108
108
 
109
109
  it 'If the target name has no MX records, check_host() MUST NOT pretend the target is its single MX, and MUST NOT default to an A lookup on the target-name directly.' do
110
110
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e4.example.com', 'mail.example.com', options)
111
- expect(%i(neutral)).to include(result.code)
111
+ expect([:neutral]).to include(result.code)
112
112
  end
113
113
 
114
114
  it 'domain-spec cannot be empty.' do
115
115
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e13.example.com', 'mail.example.com', options)
116
- expect(%i(permerror)).to include(result.code)
116
+ expect([:permerror]).to include(result.code)
117
117
  end
118
118
 
119
119
  end
@@ -5,150 +5,146 @@ describe 'Macro expansion rules' do
5
5
  { 'example.com.d.spf.example.com' => [{ 'TXT' => 'v=spf1 redirect=a.spf.example.com' }], 'a.spf.example.com' => [{ 'TXT' => 'v=spf1 include:o.spf.example.com. ~all' }], 'o.spf.example.com' => [{ 'TXT' => 'v=spf1 ip4:192.168.218.40' }], 'msgbas2x.cos.example.com' => [{ 'A' => '192.168.218.40' }], 'example.com' => [{ 'A' => '192.168.90.76' }, { 'TXT' => 'v=spf1 redirect=%{d}.d.spf.example.com.' }], 'exp.example.com' => [{ 'TXT' => 'v=spf1 exp=msg.example.com. -all' }], 'msg.example.com' => [{ 'TXT' => 'This is a test.' }], 'e1.example.com' => [{ 'TXT' => 'v=spf1 -exists:%(ir).sbl.example.com ?all' }], 'e1e.example.com' => [{ 'TXT' => 'v=spf1 exists:foo%(ir).sbl.example.com ?all' }], 'e1t.example.com' => [{ 'TXT' => 'v=spf1 exists:foo%.sbl.example.com ?all' }], 'e1a.example.com' => [{ 'TXT' => 'v=spf1 a:macro%%percent%_%_space%-url-space.example.com -all' }], 'macro%percent space%20url-space.example.com' => [{ 'A' => '1.2.3.4' }], 'e2.example.com' => [{ 'TXT' => 'v=spf1 -all exp=%{r}.example.com' }], 'e3.example.com' => [{ 'TXT' => 'v=spf1 -all exp=%{ir}.example.com' }], '40.218.168.192.example.com' => [{ 'TXT' => 'Connections from %{c} not authorized.' }], 'somewhat.long.exp.example.com' => [{ 'TXT' => 'v=spf1 -all exp=foobar.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.example.com' }], 'somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.example.com' => [{ 'TXT' => 'Congratulations! That was tricky.' }], 'e4.example.com' => [{ 'TXT' => 'v=spf1 -all exp=e4msg.example.com' }], 'e4msg.example.com' => [{ 'TXT' => '%{c} is queried as %{ir}.%{v}.arpa' }], 'e5.example.com' => [{ 'TXT' => 'v=spf1 a:%{a}.example.com -all' }], 'e6.example.com' => [{ 'TXT' => 'v=spf1 -all exp=e6msg.example.com' }], 'e6msg.example.com' => [{ 'TXT' => 'connect from %{p}' }], 'mx.example.com' => [{ 'A' => '192.168.218.41' }, { 'A' => '192.168.218.42' }, { 'AAAA' => 'CAFE:BABE::2' }, { 'AAAA' => 'CAFE:BABE::3' }], '40.218.168.192.in-addr.arpa' => [{ 'PTR' => 'mx.example.com' }], '41.218.168.192.in-addr.arpa' => [{ 'PTR' => 'mx.example.com' }], '42.218.168.192.in-addr.arpa' => [{ 'PTR' => 'mx.example.com' }, { 'PTR' => 'mx.e7.example.com' }], '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa' => [{ 'PTR' => 'mx.example.com' }], '3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa' => [{ 'PTR' => 'mx.example.com' }], 'mx.e7.example.com' => [{ 'A' => '192.168.218.42' }], 'mx.e7.example.com.should.example.com' => [{ 'A' => '127.0.0.2' }], 'mx.example.com.ok.example.com' => [{ 'A' => '127.0.0.2' }], 'e7.example.com' => [{ 'TXT' => 'v=spf1 exists:%{p}.should.example.com ~exists:%{p}.ok.example.com' }], 'e8.example.com' => [{ 'TXT' => 'v=spf1 -all exp=msg8.%{D2}' }], 'msg8.example.com' => [{ 'TXT' => 'http://example.com/why.html?l=%{L}' }], 'e9.example.com' => [{ 'TXT' => 'v=spf1 a:%{H} -all' }], 'e10.example.com' => [{ 'TXT' => 'v=spf1 -include:_spfh.%{d2} ip4:1.2.3.0/24 -all' }], '_spfh.example.com' => [{ 'TXT' => 'v=spf1 -a:%{h} +all' }], 'e11.example.com' => [{ 'TXT' => 'v=spf1 exists:%{i}.%{l2r-}.user.%{d2}' }], '1.2.3.4.gladstone.philip.user.example.com' => [{ 'A' => '127.0.0.2' }], 'e12.example.com' => [{ 'TXT' => 'v=spf1 exists:%{l2r+-}.user.%{d2}' }], 'bar.foo.user.example.com' => [{ 'A' => '127.0.0.2' }] }
6
6
  end
7
7
 
8
- let(:dns_client) { Coppertone::DNS::MockClient.new(zonefile) }
8
+ let(:dns_client) { DNSAdapter::MockClient.new(zonefile) }
9
9
  let(:options) { { dns_client: dns_client } }
10
10
 
11
11
  it 'trailing dot is ignored for domains' do
12
12
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@example.com', 'msgbas2x.cos.example.com', options)
13
- expect(%i(pass)).to include(result.code)
13
+ expect([:pass]).to include(result.code)
14
14
  end
15
15
 
16
16
  it 'trailing dot is not removed from explanation' do
17
17
  # A simple way for an implementation to ignore trailing dots on domains is to remove it when present. But be careful not to remove it for explanation text.
18
18
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@exp.example.com', 'msgbas2x.cos.example.com', options)
19
- expect(%i(fail)).to include(result.code)
19
+ expect([:fail]).to include(result.code)
20
20
  expect(result.explanation).to eq('This is a test.')
21
21
  end
22
22
 
23
23
  it 'The following macro letters are allowed only in "exp" text: c, r, t' do
24
24
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e2.example.com', 'msgbas2x.cos.example.com', options)
25
- expect(%i(permerror)).to include(result.code)
25
+ expect([:permerror]).to include(result.code)
26
26
  end
27
27
 
28
28
  it 'A % character not followed by a {, %, -, or _ character is a syntax error.' do
29
29
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e1.example.com', 'msgbas2x.cos.example.com', options)
30
- expect(%i(permerror)).to include(result.code)
30
+ expect([:permerror]).to include(result.code)
31
31
  end
32
32
 
33
33
  it 'A % character not followed by a {, %, -, or _ character is a syntax error.' do
34
34
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e1e.example.com', 'msgbas2x.cos.example.com', options)
35
- expect(%i(permerror)).to include(result.code)
35
+ expect([:permerror]).to include(result.code)
36
36
  end
37
37
 
38
38
  it 'A % character not followed by a {, %, -, or _ character is a syntax error.' do
39
39
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e1t.example.com', 'msgbas2x.cos.example.com', options)
40
- expect(%i(permerror)).to include(result.code)
40
+ expect([:permerror]).to include(result.code)
41
41
  end
42
42
 
43
43
  it 'macro-encoded percents (%%), spaces (%_), and URL-percent-encoded spaces (%-)' do
44
44
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'test@e1a.example.com', 'mail.example.com', options)
45
- expect(%i(pass)).to include(result.code)
45
+ expect([:pass]).to include(result.code)
46
46
  end
47
47
 
48
48
  it 'For IPv4 addresses, both the "i" and "c" macros expand to the standard dotted-quad format.' do
49
49
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e3.example.com', 'msgbas2x.cos.example.com', options)
50
- expect(%i(fail)).to include(result.code)
50
+ expect([:fail]).to include(result.code)
51
51
  expect(result.explanation).to eq('Connections from 192.168.218.40 not authorized.')
52
52
  end
53
53
 
54
54
  it 'When the result of macro expansion is used in a domain name query, if the expanded domain name exceeds 253 characters, the left side is truncated to fit, by removing successive domain labels until the total length does not exceed 253 characters.' do
55
55
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@somewhat.long.exp.example.com', 'msgbas2x.cos.example.com', options)
56
- expect(%i(fail)).to include(result.code)
56
+ expect([:fail]).to include(result.code)
57
57
  expect(result.explanation).to eq('Congratulations! That was tricky.')
58
58
  end
59
59
 
60
60
  it 'v = the string "in-addr" if <ip> is ipv4, or "ip6" if <ip> is ipv6' do
61
61
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e4.example.com', 'msgbas2x.cos.example.com', options)
62
- expect(%i(fail)).to include(result.code)
62
+ expect([:fail]).to include(result.code)
63
63
  expect(result.explanation).to eq('192.168.218.40 is queried as 40.218.168.192.in-addr.arpa')
64
64
  end
65
65
 
66
66
  it 'v = the string "in-addr" if <ip> is ipv4, or "ip6" if <ip> is ipv6' do
67
67
  result = Coppertone::SpfService.authenticate_email('CAFE:BABE::1', 'test@e4.example.com', 'msgbas2x.cos.example.com', options)
68
- expect(%i(fail)).to include(result.code)
68
+ expect([:fail]).to include(result.code)
69
69
  expect(result.explanation).to eq('cafe:babe::1 is queried as 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa')
70
70
  end
71
71
 
72
72
  it 'Allowed macros chars are slodipvh plus crt in explanation.' do
73
73
  result = Coppertone::SpfService.authenticate_email('CAFE:BABE::192.168.218.40', 'test@e5.example.com', 'msgbas2x.cos.example.com', options)
74
- expect(%i(permerror)).to include(result.code)
74
+ expect([:permerror]).to include(result.code)
75
75
  end
76
76
 
77
77
  it 'p = the validated domain name of <ip>' do
78
78
  # The PTR in this example does not validate.
79
79
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e6.example.com', 'msgbas2x.cos.example.com', options)
80
- expect(%i(fail)).to include(result.code)
80
+ expect([:fail]).to include(result.code)
81
81
  expect(result.explanation).to eq('connect from unknown')
82
82
  end
83
83
 
84
84
  it 'p = the validated domain name of <ip>' do
85
- pending 'It is currently unclear, based on RFC 7208, why this spec should pass.'
86
85
  # If a subdomain of the <domain> is present, it SHOULD be used.
87
- result = Coppertone::SpfService.authenticate_email('192.168.218.41',
88
- 'test@e6.example.com',
89
- 'msgbas2x.cos.example.com', options)
90
- expect(%i(fail)).to include(result.code)
86
+ result = Coppertone::SpfService.authenticate_email('192.168.218.41', 'test@e6.example.com', 'msgbas2x.cos.example.com', options)
87
+ expect([:fail]).to include(result.code)
91
88
  expect(result.explanation).to eq('connect from mx.example.com')
92
89
  end
93
90
 
94
91
  it 'p = the validated domain name of <ip>' do
95
92
  # The PTR in this example does not validate.
96
93
  result = Coppertone::SpfService.authenticate_email('CAFE:BABE::1', 'test@e6.example.com', 'msgbas2x.cos.example.com', options)
97
- expect(%i(fail)).to include(result.code)
94
+ expect([:fail]).to include(result.code)
98
95
  expect(result.explanation).to eq('connect from unknown')
99
96
  end
100
97
 
101
98
  it 'p = the validated domain name of <ip>' do
102
- pending 'It is currently unclear, based on RFC 7208, why this spec should pass.'
103
99
  # If a subdomain of the <domain> is present, it SHOULD be used.
104
100
  result = Coppertone::SpfService.authenticate_email('CAFE:BABE::3', 'test@e6.example.com', 'msgbas2x.cos.example.com', options)
105
- expect(%i(fail)).to include(result.code)
101
+ expect([:fail]).to include(result.code)
106
102
  expect(result.explanation).to eq('connect from mx.example.com')
107
103
  end
108
104
 
109
105
  it 'p = the validated domain name of <ip>' do
110
106
  # If a subdomain of the <domain> is present, it SHOULD be used.
111
107
  result = Coppertone::SpfService.authenticate_email('192.168.218.42', 'test@e7.example.com', 'msgbas2x.cos.example.com', options)
112
- expect(%i(pass softfail)).to include(result.code)
108
+ expect([:pass, :softfail]).to include(result.code)
113
109
  end
114
110
 
115
111
  it 'Uppercased macros expand exactly as their lowercased equivalents, and are then URL escaped. All chars not in the unreserved set MUST be escaped.' do
116
112
  # unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
117
113
  result = Coppertone::SpfService.authenticate_email('192.168.218.42', '~jack&jill=up-a_b3.c@e8.example.com', 'msgbas2x.cos.example.com', options)
118
- expect(%i(fail)).to include(result.code)
114
+ expect([:fail]).to include(result.code)
119
115
  expect(result.explanation).to eq('http://example.com/why.html?l=~jack%26jill%3Dup-a_b3.c')
120
116
  end
121
117
 
122
118
  it 'h = HELO/EHLO domain' do
123
119
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e9.example.com', 'msgbas2x.cos.example.com', options)
124
- expect(%i(pass)).to include(result.code)
120
+ expect([:pass]).to include(result.code)
125
121
  end
126
122
 
127
123
  it 'h = HELO/EHLO domain, but HELO is invalid' do
128
124
  # Domain-spec must end in either a macro, or a valid toplabel. It is not correct to check syntax after macro expansion.
129
125
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e9.example.com', 'JUMPIN\' JUPITER', options)
130
- expect(%i(fail)).to include(result.code)
126
+ expect([:fail]).to include(result.code)
131
127
  end
132
128
 
133
129
  it 'h = HELO/EHLO domain, but HELO is a domain literal' do
134
130
  # Domain-spec must end in either a macro, or a valid toplabel. It is not correct to check syntax after macro expansion.
135
131
  result = Coppertone::SpfService.authenticate_email('192.168.218.40', 'test@e9.example.com', '[192.168.218.40]', options)
136
- expect(%i(fail)).to include(result.code)
132
+ expect([:fail]).to include(result.code)
137
133
  end
138
134
 
139
135
  it 'Example of requiring valid helo in sender policy. This is a complex policy testing several points at once.' do
140
136
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'test@e10.example.com', 'OEMCOMPUTER', options)
141
- expect(%i(fail)).to include(result.code)
137
+ expect([:fail]).to include(result.code)
142
138
  end
143
139
 
144
140
  it 'Macro value transformation (splitting on arbitrary characters, reversal, number of right-hand parts to use)' do
145
141
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'philip-gladstone-test@e11.example.com', 'mail.example.com', options)
146
- expect(%i(pass)).to include(result.code)
142
+ expect([:pass]).to include(result.code)
147
143
  end
148
144
 
149
145
  it 'Multiple delimiters may be specified in a macro expression. macro-expand = ( "%{" macro-letter transformers *delimiter "}" ) / "%%" / "%_" / "%-"' do
150
146
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo-bar+zip+quux@e12.example.com', 'mail.example.com', options)
151
- expect(%i(pass)).to include(result.code)
147
+ expect([:pass]).to include(result.code)
152
148
  end
153
149
 
154
150
  end
@@ -5,38 +5,38 @@ describe 'PTR mechanism syntax' do
5
5
  { 'mail.example.com' => [{ 'A' => '1.2.3.4' }], 'e1.example.com' => [{ 'TXT' => 'v=spf1 ptr/0 -all' }], 'e2.example.com' => [{ 'TXT' => 'v=spf1 ptr:example.com -all' }], '4.3.2.1.in-addr.arpa' => [{ 'PTR' => 'e3.example.com' }, { 'PTR' => 'e4.example.com' }, { 'PTR' => 'mail.example.com' }], '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa' => [{ 'PTR' => 'e3.example.com' }], 'e3.example.com' => [{ 'TXT' => 'v=spf1 ptr -all' }, { 'A' => '1.2.3.4' }, { 'AAAA' => 'CAFE:BABE::1' }], 'e4.example.com' => [{ 'TXT' => 'v=spf1 ptr -all' }], 'e5.example.com' => [{ 'TXT' => 'v=spf1 ptr:' }] }
6
6
  end
7
7
 
8
- let(:dns_client) { Coppertone::DNS::MockClient.new(zonefile) }
8
+ let(:dns_client) { DNSAdapter::MockClient.new(zonefile) }
9
9
  let(:options) { { dns_client: dns_client } }
10
10
 
11
11
  it 'PTR = "ptr" [ ":" domain-spec ]' do
12
12
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e1.example.com', 'mail.example.com', options)
13
- expect(%i(permerror)).to include(result.code)
13
+ expect([:permerror]).to include(result.code)
14
14
  end
15
15
 
16
16
  it 'Check all validated domain names to see if they end in the <target-name> domain.' do
17
17
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e2.example.com', 'mail.example.com', options)
18
- expect(%i(pass)).to include(result.code)
18
+ expect([:pass]).to include(result.code)
19
19
  end
20
20
 
21
21
  it 'Check all validated domain names to see if they end in the <target-name> domain.' do
22
22
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e3.example.com', 'mail.example.com', options)
23
- expect(%i(pass)).to include(result.code)
23
+ expect([:pass]).to include(result.code)
24
24
  end
25
25
 
26
26
  it 'Check all validated domain names to see if they end in the <target-name> domain.' do
27
27
  # This PTR record does not validate
28
28
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e4.example.com', 'mail.example.com', options)
29
- expect(%i(fail)).to include(result.code)
29
+ expect([:fail]).to include(result.code)
30
30
  end
31
31
 
32
32
  it 'Check all validated domain names to see if they end in the <target-name> domain.' do
33
33
  result = Coppertone::SpfService.authenticate_email('CAFE:BABE::1', 'foo@e3.example.com', 'mail.example.com', options)
34
- expect(%i(pass)).to include(result.code)
34
+ expect([:pass]).to include(result.code)
35
35
  end
36
36
 
37
37
  it 'domain-spec cannot be empty.' do
38
38
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e5.example.com', 'mail.example.com', options)
39
- expect(%i(permerror)).to include(result.code)
39
+ expect([:permerror]).to include(result.code)
40
40
  end
41
41
 
42
42
  end