coppertone 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -16,30 +16,30 @@ describe Coppertone::Mechanism::IP6 do
16
16
 
17
17
  it 'should fail if called with an invalid IP' do
18
18
  expect do
19
- Coppertone::Mechanism::IP6.new('not_an_ip')
19
+ Coppertone::Mechanism::IP6.new(':not_an_ip')
20
20
  end.to raise_error(Coppertone::InvalidMechanismError)
21
21
  end
22
22
 
23
23
  it 'should not fail if called with an IP v4' do
24
- mech = Coppertone::Mechanism::IP6.new('1.2.3.4')
24
+ mech = Coppertone::Mechanism::IP6.new(':1.2.3.4')
25
25
  expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
26
26
  end
27
27
 
28
28
  it 'should work if called with an IP6' do
29
- mech = Coppertone::Mechanism::IP6.new('fe80::202:b3ff:fe1e:8329')
29
+ mech = Coppertone::Mechanism::IP6.new(':fe80::202:b3ff:fe1e:8329')
30
30
  expect(mech.ip_network)
31
31
  .to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
32
32
  end
33
33
 
34
34
  it 'should work if called with an IP6 with a pfxlen' do
35
- mech = Coppertone::Mechanism::IP6.new('fe80::202:b3ff:fe1e:8329/64')
35
+ mech = Coppertone::Mechanism::IP6.new(':fe80::202:b3ff:fe1e:8329/64')
36
36
  expect(mech.ip_network)
37
37
  .to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329/64'))
38
38
  end
39
39
 
40
40
  it 'should fail if called with an invalid pfxlen' do
41
41
  expect do
42
- Coppertone::Mechanism::IP6.new('fe80::202:b3ff:fe1e:8329/384')
42
+ Coppertone::Mechanism::IP6.new(':fe80::202:b3ff:fe1e:8329/384')
43
43
  end.to raise_error(Coppertone::InvalidMechanismError)
44
44
  end
45
45
 
@@ -60,23 +60,23 @@ describe Coppertone::Mechanism::IP6 do
60
60
 
61
61
  it 'should fail if called with an invalid IP' do
62
62
  expect do
63
- Coppertone::Mechanism::IP6.create('not_an_ip')
63
+ Coppertone::Mechanism::IP6.create(':not_an_ip')
64
64
  end.to raise_error(Coppertone::InvalidMechanismError)
65
65
  end
66
66
 
67
67
  it 'should not fail if called with an IP v4' do
68
- mech = Coppertone::Mechanism::IP6.create('1.2.3.4')
68
+ mech = Coppertone::Mechanism::IP6.create(':1.2.3.4')
69
69
  expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
70
70
  end
71
71
 
72
72
  it 'should work if called with an IP6' do
73
- mech = Coppertone::Mechanism::IP6.create('fe80::202:b3ff:fe1e:8329')
73
+ mech = Coppertone::Mechanism::IP6.create(':fe80::202:b3ff:fe1e:8329')
74
74
  expect(mech.ip_network)
75
75
  .to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
76
76
  end
77
77
 
78
78
  it 'should work if called with an IP6 with a pfxlen' do
79
- mech = Coppertone::Mechanism::IP6.create('fe80::202:b3ff:fe1e:8329/64')
79
+ mech = Coppertone::Mechanism::IP6.create(':fe80::202:b3ff:fe1e:8329/64')
80
80
  expect(mech.ip_network)
81
81
  .to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329/64'))
82
82
  end
@@ -92,13 +92,20 @@ describe Coppertone::Mechanism::IP6 do
92
92
  end
93
93
 
94
94
  it 'should return true if the client IP is in the network' do
95
- mech = Coppertone::Mechanism::IP6.create('fe80:0:0:0:202:b3ff:fe1e:8300/120')
95
+ mech = Coppertone::Mechanism::IP6.create(':fe80:0:0:0:202:b3ff:fe1e:8300/120')
96
96
  expect(mech.match?(macro_context, double)).to eq(true)
97
97
  end
98
98
 
99
99
  it 'should return false if the client IP is not in the network' do
100
- mech = Coppertone::Mechanism::IP6.create('fe80:0:0:0:202:b3ff:fe1e:8300/126')
100
+ mech = Coppertone::Mechanism::IP6.create(':fe80:0:0:0:202:b3ff:fe1e:8300/126')
101
101
  expect(mech.match?(macro_context, double)).to eq(false)
102
102
  end
103
103
  end
104
+
105
+ context 'dns_lookup_term?' do
106
+ it 'should be false' do
107
+ expect(Coppertone::Mechanism::IP6).not_to be_dns_lookup_term
108
+ expect(Coppertone::Mechanism::IP6.create(':fe80::202:b3ff:fe1e:8329')).not_to be_dns_lookup_term
109
+ end
110
+ end
104
111
  end
@@ -8,6 +8,7 @@ describe Coppertone::Mechanism::MX do
8
8
  expect(mech.domain_spec).to be_nil
9
9
  expect(mech.ip_v4_cidr_length).to eq(32)
10
10
  expect(mech.ip_v6_cidr_length).to eq(128)
11
+ expect(mech.to_s).to eq('mx')
11
12
  end
12
13
 
13
14
  it 'should not fail if called with a blank argument' do
@@ -16,6 +17,7 @@ describe Coppertone::Mechanism::MX do
16
17
  expect(mech.domain_spec).to be_nil
17
18
  expect(mech.ip_v4_cidr_length).to eq(32)
18
19
  expect(mech.ip_v6_cidr_length).to eq(128)
20
+ expect(mech.to_s).to eq('mx')
19
21
  end
20
22
 
21
23
  it 'should fail if called with an invalid macrostring' do
@@ -23,6 +25,53 @@ describe Coppertone::Mechanism::MX do
23
25
  Coppertone::Mechanism::MX.new('abc%:def')
24
26
  end.to raise_error(Coppertone::InvalidMechanismError)
25
27
  end
28
+
29
+ it 'should process the domain spec if it includes a IP v4 CIDR' do
30
+ mech = Coppertone::Mechanism::MX.new('/24')
31
+ expect(mech).not_to be_nil
32
+ expect(mech.domain_spec).to be_nil
33
+ expect(mech.ip_v4_cidr_length).to eq(24)
34
+ expect(mech.ip_v6_cidr_length).to eq(128)
35
+ expect(mech.to_s).to eq('mx/24')
36
+ end
37
+
38
+ it 'should process the domain spec if it includes a IP v6 CIDR' do
39
+ mech = Coppertone::Mechanism::MX.new('//96')
40
+ expect(mech).not_to be_nil
41
+ expect(mech.domain_spec).to be_nil
42
+ expect(mech.ip_v4_cidr_length).to eq(32)
43
+ expect(mech.ip_v6_cidr_length).to eq(96)
44
+ expect(mech.to_s).to eq('mx//96')
45
+ end
46
+
47
+ it 'should process the domain spec if it includes an IP v4 CIDR and an IP v6 CIDR' do
48
+ mech = Coppertone::Mechanism::MX.new('/28//96')
49
+ expect(mech).not_to be_nil
50
+ expect(mech.domain_spec).to be_nil
51
+ expect(mech.ip_v4_cidr_length).to eq(28)
52
+ expect(mech.ip_v6_cidr_length).to eq(96)
53
+ expect(mech.to_s).to eq('mx/28//96')
54
+ end
55
+
56
+ it 'should not fail if called with a blank argument' do
57
+ mech = Coppertone::Mechanism::MX.new(':mx.example.com')
58
+ expect(mech).not_to be_nil
59
+ expect(mech.domain_spec)
60
+ .to eq(Coppertone::DomainSpec.new('mx.example.com'))
61
+ expect(mech.ip_v4_cidr_length).to eq(32)
62
+ expect(mech.ip_v6_cidr_length).to eq(128)
63
+ expect(mech.to_s).to eq('mx:mx.example.com')
64
+ end
65
+
66
+ it 'should not fail if called with a blank argument' do
67
+ mech = Coppertone::Mechanism::MX.new(':mx.example.com/28//96')
68
+ expect(mech).not_to be_nil
69
+ expect(mech.domain_spec)
70
+ .to eq(Coppertone::DomainSpec.new('mx.example.com'))
71
+ expect(mech.ip_v4_cidr_length).to eq(28)
72
+ expect(mech.ip_v6_cidr_length).to eq(96)
73
+ expect(mech.to_s).to eq('mx:mx.example.com/28//96')
74
+ end
26
75
  end
27
76
 
28
77
  context '#create' do
@@ -48,4 +97,11 @@ describe Coppertone::Mechanism::MX do
48
97
  end.to raise_error(Coppertone::InvalidMechanismError)
49
98
  end
50
99
  end
100
+
101
+ context 'dns_lookup_term?' do
102
+ it 'should be true' do
103
+ expect(Coppertone::Mechanism::MX).to be_dns_lookup_term
104
+ expect(Coppertone::Mechanism::MX.new(':example.com')).to be_dns_lookup_term
105
+ end
106
+ end
51
107
  end
@@ -40,4 +40,11 @@ describe Coppertone::Mechanism::Ptr do
40
40
  end.to raise_error(Coppertone::InvalidMechanismError)
41
41
  end
42
42
  end
43
+
44
+ context 'dns_lookup_term?' do
45
+ it 'should be true' do
46
+ expect(Coppertone::Mechanism::Ptr).to be_dns_lookup_term
47
+ expect(Coppertone::Mechanism::Ptr.new(':example.com')).to be_dns_lookup_term
48
+ end
49
+ end
43
50
  end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::Modifier::Exp do
4
+ context 'to_s' do
5
+ it 'should result in the expected string' do
6
+ expect(Coppertone::Modifier::Exp.new('test.example.com').to_s)
7
+ .to eq('exp=test.example.com')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coppertone::Modifier::Redirect do
4
+ context 'to_s' do
5
+ it 'should result in the expected string' do
6
+ expect(Coppertone::Modifier::Redirect.new('test.example.com').to_s)
7
+ .to eq('redirect=test.example.com')
8
+ end
9
+ end
10
+ end
@@ -5,34 +5,34 @@ describe 'ALL mechanism syntax' do
5
5
  { 'mail.example.com' => [{ 'A' => '1.2.3.4' }], 'e1.example.com' => [{ 'TXT' => 'v=spf1 -all.' }], 'e2.example.com' => [{ 'TXT' => 'v=spf1 -all:foobar' }], 'e3.example.com' => [{ 'TXT' => 'v=spf1 -all/8' }], 'e4.example.com' => [{ 'TXT' => 'v=spf1 ?all' }], 'e5.example.com' => [{ 'TXT' => 'v=spf1 all -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 'all = "all" ' do
12
12
  # At least one implementation got this wrong
13
13
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e1.example.com', 'mail.example.com', options)
14
- expect(%i(permerror)).to include(result.code)
14
+ expect([:permerror]).to include(result.code)
15
15
  end
16
16
 
17
17
  it 'all = "all" ' do
18
18
  # At least one implementation got this wrong
19
19
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e2.example.com', 'mail.example.com', options)
20
- expect(%i(permerror)).to include(result.code)
20
+ expect([:permerror]).to include(result.code)
21
21
  end
22
22
 
23
23
  it 'all = "all" ' do
24
24
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e3.example.com', 'mail.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 'all = "all" ' do
29
29
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e4.example.com', 'mail.example.com', options)
30
- expect(%i(neutral)).to include(result.code)
30
+ expect([:neutral]).to include(result.code)
31
31
  end
32
32
 
33
33
  it 'all = "all" ' do
34
34
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e5.example.com', 'mail.example.com', options)
35
- expect(%i(pass)).to include(result.code)
35
+ expect([:pass]).to include(result.code)
36
36
  end
37
37
 
38
38
  end
@@ -5,155 +5,155 @@ describe 'A mechanism syntax' do
5
5
  { 'mail.example.com' => [{ 'A' => '1.2.3.4' }], 'e1.example.com' => [{ 'TXT' => 'v=spf1 a/0 -all' }], 'e2.example.com' => [{ 'A' => '1.1.1.1' }, { 'AAAA' => '1234::2' }, { 'TXT' => 'v=spf1 a/0 -all' }], 'e2a.example.com' => [{ 'AAAA' => '1234::1' }, { 'TXT' => 'v=spf1 a//0 -all' }], 'e2b.example.com' => [{ 'A' => '1.1.1.1' }, { 'TXT' => 'v=spf1 a//0 -all' }], 'ipv6.example.com' => [{ 'AAAA' => '1234::1' }, { 'A' => '1.1.1.1' }, { 'TXT' => 'v=spf1 a -all' }], 'e3.example.com' => [{ 'TXT' => "v=spf1 a:foo.example.com\u0000" }], 'e4.example.com' => [{ 'TXT' => 'v=spf1 a:111.222.33.44' }], 'e5.example.com' => [{ 'TXT' => 'v=spf1 a:abc.123' }], 'e5a.example.com' => [{ 'TXT' => 'v=spf1 a:museum' }], 'e5b.example.com' => [{ 'TXT' => 'v=spf1 a:museum.' }], 'e6.example.com' => [{ 'TXT' => 'v=spf1 a//33 -all' }], 'e6a.example.com' => [{ 'TXT' => 'v=spf1 a/33 -all' }], 'e7.example.com' => [{ 'TXT' => 'v=spf1 a//129 -all' }], 'e8.example.com' => [{ 'A' => '1.2.3.5' }, { 'AAAA' => '2001:db8:1234::dead:beef' }, { 'TXT' => 'v=spf1 a/24//64 -all' }], 'e8e.example.com' => [{ 'A' => '1.2.3.5' }, { 'AAAA' => '2001:db8:1234::dead:beef' }, { 'TXT' => 'v=spf1 a/24/64 -all' }], 'e8a.example.com' => [{ 'A' => '1.2.3.5' }, { 'AAAA' => '2001:db8:1234::dead:beef' }, { 'TXT' => 'v=spf1 a/24 -all' }], 'e8b.example.com' => [{ 'A' => '1.2.3.5' }, { 'AAAA' => '2001:db8:1234::dead:beef' }, { 'TXT' => 'v=spf1 a//64 -all' }], 'e9.example.com' => [{ 'TXT' => 'v=spf1 a:example.com:8080' }], 'e10.example.com' => [{ 'TXT' => 'v=spf1 a:foo.example.com/24' }], 'foo.example.com' => [{ 'A' => '1.1.1.1' }, { 'A' => '1.2.3.5' }], 'e11.example.com' => [{ 'TXT' => 'v=spf1 a:foo:bar/baz.example.com' }], 'foo:bar/baz.example.com' => [{ 'A' => '1.2.3.4' }], 'e12.example.com' => [{ 'TXT' => 'v=spf1 a:example.-com' }], 'e13.example.com' => [{ 'TXT' => 'v=spf1 a:' }], 'e14.example.com' => [{ 'TXT' => 'v=spf1 a:foo.example.xn--zckzah -all' }], 'foo.example.xn--zckzah' => [{ 'A' => '1.2.3.4' }] }
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 'A = "a" [ ":" 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 'A = "a" [ ":" 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 'A = "a" [ ":" 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 'A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] ' do
27
27
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e8.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 'A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] ' do
32
32
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e8e.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 'A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] ' do
37
37
  result = Coppertone::SpfService.authenticate_email('2001:db8:1234::cafe:babe', 'foo@e8.example.com', 'mail.example.com', options)
38
- expect(%i(pass)).to include(result.code)
38
+ expect([:pass]).to include(result.code)
39
39
  end
40
40
 
41
41
  it 'A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] ' do
42
42
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e8b.example.com', 'mail.example.com', options)
43
- expect(%i(fail)).to include(result.code)
43
+ expect([:fail]).to include(result.code)
44
44
  end
45
45
 
46
46
  it 'A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] ' do
47
47
  result = Coppertone::SpfService.authenticate_email('2001:db8:1234::cafe:babe', 'foo@e8a.example.com', 'mail.example.com', options)
48
- expect(%i(fail)).to include(result.code)
48
+ expect([:fail]).to include(result.code)
49
49
  end
50
50
 
51
51
  it 'A matches any returned IP.' do
52
52
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e10.example.com', 'mail.example.com', options)
53
- expect(%i(pass)).to include(result.code)
53
+ expect([:pass]).to include(result.code)
54
54
  end
55
55
 
56
56
  it 'A matches any returned IP.' do
57
57
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e10.example.com', 'mail.example.com', options)
58
- expect(%i(pass)).to include(result.code)
58
+ expect([:pass]).to include(result.code)
59
59
  end
60
60
 
61
61
  it 'domain-spec must pass basic syntax checks; a : may appear in domain-spec, but not in top-label' do
62
62
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e9.example.com', 'mail.example.com', options)
63
- expect(%i(permerror)).to include(result.code)
63
+ expect([:permerror]).to include(result.code)
64
64
  end
65
65
 
66
66
  it 'If no ips are returned, A mechanism does not match, even with /0.' do
67
67
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e1.example.com', 'mail.example.com', options)
68
- expect(%i(fail)).to include(result.code)
68
+ expect([:fail]).to include(result.code)
69
69
  end
70
70
 
71
71
  it 'Matches if any A records are present in DNS.' do
72
72
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e2.example.com', 'mail.example.com', options)
73
- expect(%i(pass)).to include(result.code)
73
+ expect([:pass]).to include(result.code)
74
74
  end
75
75
 
76
76
  it 'Matches if any A records are present in DNS.' do
77
77
  result = Coppertone::SpfService.authenticate_email('1234::1', 'foo@e2.example.com', 'mail.example.com', options)
78
- expect(%i(fail)).to include(result.code)
78
+ expect([:fail]).to include(result.code)
79
79
  end
80
80
 
81
81
  it 'Would match if any AAAA records are present in DNS, but not for an IP4 connection.' do
82
82
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e2a.example.com', 'mail.example.com', options)
83
- expect(%i(fail)).to include(result.code)
83
+ expect([:fail]).to include(result.code)
84
84
  end
85
85
 
86
86
  it 'Would match if any AAAA records are present in DNS, but not for an IP4 connection.' do
87
87
  result = Coppertone::SpfService.authenticate_email('::FFFF:1.2.3.4', 'foo@e2a.example.com', 'mail.example.com', options)
88
- expect(%i(fail)).to include(result.code)
88
+ expect([:fail]).to include(result.code)
89
89
  end
90
90
 
91
91
  it 'Matches if any AAAA records are present in DNS.' do
92
92
  result = Coppertone::SpfService.authenticate_email('1234::1', 'foo@e2a.example.com', 'mail.example.com', options)
93
- expect(%i(pass)).to include(result.code)
93
+ expect([:pass]).to include(result.code)
94
94
  end
95
95
 
96
96
  it 'Simple IP6 Address match with dual stack.' do
97
97
  result = Coppertone::SpfService.authenticate_email('1234::1', 'foo@ipv6.example.com', 'mail.example.com', options)
98
- expect(%i(pass)).to include(result.code)
98
+ expect([:pass]).to include(result.code)
99
99
  end
100
100
 
101
101
  it 'No match if no AAAA records are present in DNS.' do
102
102
  result = Coppertone::SpfService.authenticate_email('1234::1', 'foo@e2b.example.com', 'mail.example.com', options)
103
- expect(%i(fail)).to include(result.code)
103
+ expect([:fail]).to include(result.code)
104
104
  end
105
105
 
106
106
  it 'Null octets not allowed in toplabel' do
107
107
  result = Coppertone::SpfService.authenticate_email('1.2.3.5', 'foo@e3.example.com', 'mail.example.com', options)
108
- expect(%i(permerror)).to include(result.code)
108
+ expect([:permerror]).to include(result.code)
109
109
  end
110
110
 
111
111
  it 'toplabel may not be all numeric' do
112
112
  # A common publishing mistake is using ip4 addresses with A mechanism. This should receive special diagnostic attention in the permerror.
113
113
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e4.example.com', 'mail.example.com', options)
114
- expect(%i(permerror)).to include(result.code)
114
+ expect([:permerror]).to include(result.code)
115
115
  end
116
116
 
117
117
  it 'toplabel may not be all numeric' do
118
118
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e5.example.com', 'mail.example.com', options)
119
- expect(%i(permerror)).to include(result.code)
119
+ expect([:permerror]).to include(result.code)
120
120
  end
121
121
 
122
122
  it 'toplabel may contain dashes' do
123
123
  # Going from the "toplabel" grammar definition, an implementation using regular expressions in incrementally parsing SPF records might erroneously try to match a TLD such as ".xn--zckzah" (cf. IDN TLDs!) to \'( *alphanum ALPHA *alphanum )\' first before trying the alternative \'( 1*alphanum "-" *( alphanum / "-" ) alphanum )\', essentially causing a non-greedy, and thus, incomplete match. Make sure a greedy match is performed!
124
124
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e14.example.com', 'mail.example.com', options)
125
- expect(%i(pass)).to include(result.code)
125
+ expect([:pass]).to include(result.code)
126
126
  end
127
127
 
128
128
  it 'toplabel may not begin with a dash' do
129
129
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e12.example.com', 'mail.example.com', options)
130
- expect(%i(permerror)).to include(result.code)
130
+ expect([:permerror]).to include(result.code)
131
131
  end
132
132
 
133
133
  it 'domain-spec may not consist of only a toplabel.' do
134
134
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e5a.example.com', 'mail.example.com', options)
135
- expect(%i(permerror)).to include(result.code)
135
+ expect([:permerror]).to include(result.code)
136
136
  end
137
137
 
138
138
  it 'domain-spec may not consist of only a toplabel.' do
139
139
  # "A trailing dot doesn\'t help."
140
140
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e5b.example.com', 'mail.example.com', options)
141
- expect(%i(permerror)).to include(result.code)
141
+ expect([:permerror]).to include(result.code)
142
142
  end
143
143
 
144
144
  it 'domain-spec may contain any visible char except %' do
145
145
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e11.example.com', 'mail.example.com', options)
146
- expect(%i(pass)).to include(result.code)
146
+ expect([:pass]).to include(result.code)
147
147
  end
148
148
 
149
149
  it 'domain-spec may contain any visible char except %' do
150
150
  result = Coppertone::SpfService.authenticate_email('::FFFF:1.2.3.4', 'foo@e11.example.com', 'mail.example.com', options)
151
- expect(%i(pass)).to include(result.code)
151
+ expect([:pass]).to include(result.code)
152
152
  end
153
153
 
154
154
  it 'domain-spec cannot be empty.' do
155
155
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e13.example.com', 'mail.example.com', options)
156
- expect(%i(permerror)).to include(result.code)
156
+ expect([:permerror]).to include(result.code)
157
157
  end
158
158
 
159
159
  end
@@ -5,42 +5,42 @@ describe 'EXISTS mechanism syntax' do
5
5
  { 'mail.example.com' => [{ 'A' => '1.2.3.4' }], 'mail6.example.com' => [{ 'AAAA' => 'CAFE:BABE::4' }], 'err.example.com' => ['TIMEOUT'], 'e1.example.com' => [{ 'TXT' => 'v=spf1 exists:' }], 'e2.example.com' => [{ 'TXT' => 'v=spf1 exists' }], 'e3.example.com' => [{ 'TXT' => 'v=spf1 exists:mail.example.com/24' }], 'e4.example.com' => [{ 'TXT' => 'v=spf1 exists:mail.example.com' }], 'e5.example.com' => [{ 'TXT' => 'v=spf1 exists:mail6.example.com -all' }], 'e6.example.com' => [{ 'TXT' => 'v=spf1 exists:err.example.com -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 'domain-spec cannot be empty.' 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 'exists = "exists" ":" domain-spec' do
17
17
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e2.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 'exists = "exists" ":" domain-spec' do
22
22
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e3.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 'mechanism matches if any DNS A RR exists' do
27
27
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e4.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 'The lookup type is A even when the connection is ip6' do
32
32
  result = Coppertone::SpfService.authenticate_email('CAFE:BABE::3', 'foo@e4.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 'The lookup type is A even when the connection is ip6' do
37
37
  result = Coppertone::SpfService.authenticate_email('CAFE:BABE::3', 'foo@e5.example.com', 'mail.example.com', options)
38
- expect(%i(fail)).to include(result.code)
38
+ expect([:fail]).to include(result.code)
39
39
  end
40
40
 
41
41
  it 'Result for DNS error clarified in RFC7208: MTAs or other processors SHOULD impose a limit on the maximum amount of elapsed time to evaluate check_host(). Such a limit SHOULD allow at least 20 seconds. If such a limit is exceeded, the result of authorization SHOULD be "temperror".' do
42
42
  result = Coppertone::SpfService.authenticate_email('CAFE:BABE::3', 'foo@e6.example.com', 'mail.example.com', options)
43
- expect(%i(temperror)).to include(result.code)
43
+ expect([:temperror]).to include(result.code)
44
44
  end
45
45
 
46
46
  end
@@ -5,55 +5,55 @@ describe 'IP4 mechanism syntax' do
5
5
  { 'mail.example.com' => [{ 'A' => '1.2.3.4' }], 'e1.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.1.1.1/0 -all' }], 'e2.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.2.3.4/32 -all' }], 'e3.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.2.3.4/33 -all' }], 'e4.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.2.3.4/032 -all' }], 'e5.example.com' => [{ 'TXT' => 'v=spf1 ip4' }], 'e6.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.2.3.4//32' }], 'e7.example.com' => [{ 'TXT' => 'v=spf1 -ip4:1.2.3.4 ip6:::FFFF:1.2.3.4' }], 'e8.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.2.3.4:8080' }], 'e9.example.com' => [{ 'TXT' => 'v=spf1 ip4:1.2.3' }] }
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 'ip4-cidr-length = "/" 1*DIGIT' do
12
12
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e1.example.com', 'mail.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 'ip4-cidr-length = "/" 1*DIGIT' 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 'Invalid CIDR should get permerror.' do
22
22
  # The RFC4408 was silent on ip4 CIDR > 32 or ip6 CIDR > 128, but RFC7208 is explicit. Invalid CIDR is prohibited.
23
23
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e3.example.com', 'mail.example.com', options)
24
- expect(%i(permerror)).to include(result.code)
24
+ expect([:permerror]).to include(result.code)
25
25
  end
26
26
 
27
27
  it 'Invalid CIDR should get permerror.' do
28
28
  # Leading zeros are not explicitly prohibited by the RFC. However, since the RFC explicity prohibits leading zeros in ip4-network, our interpretation is that CIDR should be also.
29
29
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e4.example.com', 'mail.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 'IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ]' do
34
34
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e5.example.com', 'mail.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 'IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ]' do
39
39
  # This has actually been published in SPF records.
40
40
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e8.example.com', 'mail.example.com', options)
41
- expect(%i(permerror)).to include(result.code)
41
+ expect([:permerror]).to include(result.code)
42
42
  end
43
43
 
44
44
  it 'It is not permitted to omit parts of the IP address instead of using CIDR notations.' do
45
45
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e9.example.com', 'mail.example.com', options)
46
- expect(%i(permerror)).to include(result.code)
46
+ expect([:permerror]).to include(result.code)
47
47
  end
48
48
 
49
49
  it 'dual-cidr-length not permitted on ip4' do
50
50
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e6.example.com', 'mail.example.com', options)
51
- expect(%i(permerror)).to include(result.code)
51
+ expect([:permerror]).to include(result.code)
52
52
  end
53
53
 
54
54
  it 'IP4 mapped IP6 connections MUST be treated as IP4' do
55
55
  result = Coppertone::SpfService.authenticate_email('::FFFF:1.2.3.4', 'foo@e7.example.com', 'mail.example.com', options)
56
- expect(%i(fail)).to include(result.code)
56
+ expect([:fail]).to include(result.code)
57
57
  end
58
58
 
59
59
  end
@@ -5,56 +5,56 @@ describe 'IP6 mechanism syntax' do
5
5
  { 'mail.example.com' => [{ 'A' => '1.2.3.4' }], 'e1.example.com' => [{ 'TXT' => 'v=spf1 -all ip6' }], 'e2.example.com' => [{ 'TXT' => 'v=spf1 ip6:::1.1.1.1/0' }], 'e3.example.com' => [{ 'TXT' => 'v=spf1 ip6:::1.1.1.1/129' }], 'e4.example.com' => [{ 'TXT' => 'v=spf1 ip6:::1.1.1.1//33' }], 'e5.example.com' => [{ 'TXT' => 'v=spf1 ip6:CAFE:BABE:8000::/33' }], 'e6.example.com' => [{ 'TXT' => 'v=spf1 ip6::CAFE::BABE' }] }
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 'IP6 = "ip6" ":" ip6-network [ ip6-cidr-length ]' 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 'IP4 connections do not match ip6.' do
17
17
  # There was controversy over IPv4 mapped connections. RFC7208 clearly states IPv4 mapped addresses only match ip4: mechanisms.
18
18
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e2.example.com', 'mail.example.com', options)
19
- expect(%i(neutral)).to include(result.code)
19
+ expect([:neutral]).to include(result.code)
20
20
  end
21
21
 
22
22
  it 'Even if the SMTP connection is via IPv6, an IPv4-mapped IPv6 IP address (see RFC 3513, Section 2.5.5) MUST still be considered an IPv4 address.' do
23
23
  # There was controversy over ip4 mapped connections. RFC7208 clearly requires such connections to be considered as ip4 only.
24
24
  result = Coppertone::SpfService.authenticate_email('::FFFF:1.2.3.4', 'foo@e2.example.com', 'mail.example.com', options)
25
- expect(%i(neutral)).to include(result.code)
25
+ expect([:neutral]).to include(result.code)
26
26
  end
27
27
 
28
28
  it 'Match any IP6' do
29
29
  result = Coppertone::SpfService.authenticate_email('DEAF:BABE::CAB:FEE', 'foo@e2.example.com', 'mail.example.com', options)
30
- expect(%i(pass)).to include(result.code)
30
+ expect([:pass]).to include(result.code)
31
31
  end
32
32
 
33
33
  it 'Invalid CIDR' do
34
34
  # IP4 only implementations MUST fully syntax check all mechanisms, even if they otherwise ignore them.
35
35
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e3.example.com', 'mail.example.com', options)
36
- expect(%i(permerror)).to include(result.code)
36
+ expect([:permerror]).to include(result.code)
37
37
  end
38
38
 
39
39
  it 'dual-cidr syntax not used for ip6' do
40
40
  # IP4 only implementations MUST fully syntax check all mechanisms, even if they otherwise ignore them.
41
41
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e4.example.com', 'mail.example.com', options)
42
- expect(%i(permerror)).to include(result.code)
42
+ expect([:permerror]).to include(result.code)
43
43
  end
44
44
 
45
45
  it 'make sure ip4 cidr restriction are not used for ip6' do
46
46
  result = Coppertone::SpfService.authenticate_email('CAFE:BABE:8000::', 'foo@e5.example.com', 'mail.example.com', options)
47
- expect(%i(pass)).to include(result.code)
47
+ expect([:pass]).to include(result.code)
48
48
  end
49
49
 
50
50
  it 'make sure ip4 cidr restriction are not used for ip6' do
51
51
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e5.example.com', 'mail.example.com', options)
52
- expect(%i(neutral)).to include(result.code)
52
+ expect([:neutral]).to include(result.code)
53
53
  end
54
54
 
55
55
  it '' do
56
56
  result = Coppertone::SpfService.authenticate_email('1.2.3.4', 'foo@e6.example.com', 'mail.example.com', options)
57
- expect(%i(permerror)).to include(result.code)
57
+ expect([:permerror]).to include(result.code)
58
58
  end
59
59
 
60
60
  end