spf-query 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5821a96acdc66745d783eaf3e0bb03653892b421
4
- data.tar.gz: 74c7214b71a9d14616290e4126a721b0a026734a
3
+ metadata.gz: b9a9fddefde5c33a2ad1385bab0d15ca8477ad0a
4
+ data.tar.gz: ed9f792eb99ef6308b07627645efb7aae4eeb695
5
5
  SHA512:
6
- metadata.gz: 71780740178980f74a8ea65be8767e4ce35c3a6158f5c27bff47e1f7bf93a39775914348cb57d84f0f4035190f53a220e362ee020c40e1cd5f73190d85503eeb
7
- data.tar.gz: 76f120cbca0b71028519ccbb20aeb32eb50e707c8f82ac707d272be5ac3593005bd295cb675c25f28e2c910d5a95bdcd51bdd63a2861e66c633f259a62ca0ede
6
+ metadata.gz: 62515f4dd785031a84487205a3f7d85608464798e53b8667f09c69cf230590d398ccebd5aaf09e95951b1630c3a048268db28b59bde3e601afe40db385730817
7
+ data.tar.gz: 4647bd4bc4351b6cb2032a7dac1d6b05d51e93e6cafd308423abb07d9118d5c2655057da7d2068074331e81577ee39d44489f90621fadf9cf26ab21c49ccb6ca
@@ -1,9 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - 2.0
5
- - 2.1
6
- - 2.2
3
+ - 2.1.8
4
+ - 2.2.4
5
+ - 2.3.0
7
6
  - jruby
8
7
  - rbx-2
9
8
  matrix:
@@ -1,3 +1,12 @@
1
+ ### 0.1.5 / 2016-07-10
2
+
3
+ * Fixed a bug in {SPF::Query.query} for when the TXT record is split into
4
+ multiple strings. According to [RFC 7208, Section 3.3], multiple strings
5
+ should be joined together _without_ spaces.
6
+ * Fixed a bug in {SPF::Query::Mechanism#to_s}.
7
+
8
+ [RFC 7208, Section 3.3]: https://tools.ietf.org/html/rfc7208#section-3.3
9
+
1
10
  ### 0.1.4 / 2015-12-10
2
11
 
3
12
  * Prioritize TXT records on `_spf.example.com` and `example.com` over a SPF
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Trail of Bits
3
+ Copyright (c) 2014-2016 Trail of Bits
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
@@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
17
  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
18
  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
19
  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,5 +1,8 @@
1
1
  require 'resolv'
2
2
 
3
+ #
4
+ # Represents a `SPF` type DNS record.
5
+ #
3
6
  class Resolv::DNS::Resource::IN::SPF < Resolv::DNS::Resource::IN::TXT
4
7
  # resolv.rb doesn't define an SPF resource type.
5
8
  TypeValue = 99
@@ -2,9 +2,17 @@ require 'parslet'
2
2
 
3
3
  module SPF
4
4
  module Query
5
+ #
6
+ # Exception for when the SPF record cannot be parsed.
7
+ #
5
8
  class InvalidRecord < Parslet::ParseFailed
6
9
  end
7
10
 
11
+ #
12
+ # Exception for when [SenderID] is found in-place of SPF.
13
+ #
14
+ # [SenderID]: http://www.openspf.org/SPF_vs_Sender_ID
15
+ #
8
16
  class SenderIDFound < InvalidRecord
9
17
  end
10
18
  end
@@ -1,16 +1,39 @@
1
1
  module SPF
2
2
  module Query
3
+ #
4
+ # Represents an IP address in an SPF record.
5
+ #
3
6
  class IP
4
7
 
8
+ # The address.
9
+ #
10
+ # @return [String]
5
11
  attr_reader :address
6
12
 
13
+ # CIDR length.
14
+ #
15
+ # @return [Integer, nil]
7
16
  attr_reader :cidr_length
8
17
 
18
+ #
19
+ # Initializes the IP.
20
+ #
21
+ # @param [String] address
22
+ # The IP address.
23
+ #
24
+ # @param [Integer, nil] cidr_length
25
+ # Optional CIDR length.
26
+ #
9
27
  def initialize(address,cidr_length=nil)
10
28
  @address = address
11
29
  @cidr_length = cidr_length
12
30
  end
13
31
 
32
+ #
33
+ # Converts the IP address to a String.
34
+ #
35
+ # @return [String]
36
+ #
14
37
  def to_s
15
38
  if @cidr_length then "#{@address}/#{@cidr_length}"
16
39
  else "#{@address}"
@@ -1,13 +1,43 @@
1
1
  module SPF
2
2
  module Query
3
+ #
4
+ # Represents an SPF string macro.
5
+ #
3
6
  class Macro
4
7
 
8
+ # The macro letter.
9
+ #
10
+ # @return [Symbol]
5
11
  attr_reader :letter
6
12
 
13
+ # Number of times the macro must be repeated.
14
+ #
15
+ # @return [Integer, nil]
7
16
  attr_reader :digits
8
17
 
18
+ # Macro delimiter character.
19
+ #
20
+ # @return [Array<String>]
9
21
  attr_reader :delimiters
10
22
 
23
+ #
24
+ # Initializes the macro.
25
+ #
26
+ # @param [Symbol] letter
27
+ # The macro letter.
28
+ #
29
+ # @param [Hash] options
30
+ # Additional options.
31
+ #
32
+ # @option options [Integer] :digits
33
+ # Number of times to repeat the macro.
34
+ #
35
+ # @option options [Boolean] :reverse
36
+ # Whether to reverse the value.
37
+ #
38
+ # @option options [Array<String>, String] :delimiters
39
+ # Delimiter characters.
40
+ #
11
41
  def initialize(letter,options={})
12
42
  @letter = letter
13
43
  @digits = options[:digits]
@@ -15,10 +45,20 @@ module SPF
15
45
  @delimiters = Array(options[:delimiters])
16
46
  end
17
47
 
48
+ #
49
+ # Specifies if the macro should be reversed.
50
+ #
51
+ # @return [Boolean]
52
+ #
18
53
  def reverse?
19
54
  @reverse
20
55
  end
21
56
 
57
+ #
58
+ # Converts the macro a String.
59
+ #
60
+ # @return [String]
61
+ #
22
62
  def to_s
23
63
  "%{#{@letter}#{@digits}#{@delimiters.join}}"
24
64
  end
@@ -1,29 +1,65 @@
1
1
  module SPF
2
2
  module Query
3
+ #
4
+ # Represents a string containing SPF macros.
5
+ #
3
6
  class MacroString
4
7
 
5
8
  include Enumerable
6
9
 
10
+ #
11
+ # Initializes the macro string.
12
+ #
13
+ # @param [Array<String, Macro>] elements
14
+ # String literals and String macros.
15
+ #
7
16
  def initialize(elements)
8
17
  @elements = elements
9
18
  end
10
19
 
20
+ #
21
+ # Enumerates over the macro string literals and macros.
22
+ #
23
+ # @yield [element]
24
+ #
25
+ # @yieldparam [String, Macro] element
26
+ #
27
+ # @return [Enumerator]
28
+ # If no block is given, an Enumerator will be returned.
29
+ #
11
30
  def each(&block)
12
31
  @elements.each(&block)
13
32
  end
14
33
 
34
+ #
35
+ # Accesses the String literal or macro at the given index or range.
36
+ #
37
+ # @param [Integer, (Integer, Integer), Range] arguments
38
+ # The index or range to access.
39
+ #
40
+ # @return [Array<String, Macro>, String, Macro]
41
+ # The String literal(s) or macro(s) at the given index or range.
42
+ #
15
43
  def [](*arguments)
16
44
  @elements[*arguments]
17
45
  end
18
46
 
47
+ #
48
+ # Converts the macro string to an Array.
49
+ #
50
+ # @return [Array<String, Macro>]
51
+ #
19
52
  def to_a
20
53
  @elements
21
54
  end
22
55
 
23
- def to_ary
24
- @elements
25
- end
56
+ alias to_ary to_a
26
57
 
58
+ #
59
+ # Converts the macro string to a String.
60
+ #
61
+ # @return [String]
62
+ #
27
63
  def to_s
28
64
  @elements.join
29
65
  end
@@ -1,18 +1,42 @@
1
1
  module SPF
2
2
  module Query
3
+ #
4
+ # Represents an SPF mechanism.
5
+ #
3
6
  class Mechanism
4
7
 
8
+ # Maps qualifier symbols to Symbols
5
9
  QUALIFIERS = {
6
10
  '+' => :pass,
7
11
  '-' => :fail,
8
12
  '~' => :soft_fail,
9
- '?' => :neuatral
13
+ '?' => :neutral
10
14
  }
11
15
 
16
+ # The mechanism name.
17
+ #
18
+ # @return [Symbol]
12
19
  attr_reader :name
13
20
 
21
+ # The mechanism value.
22
+ #
23
+ # @return [String, MacroString, IP, nil]
14
24
  attr_reader :value
15
25
 
26
+ #
27
+ # Initializes the mechanism.
28
+ #
29
+ # @param [Symbol] name
30
+ #
31
+ # @param [Hash] options
32
+ # Additional options.
33
+ #
34
+ # @option options [String, MacroString, IP] :value
35
+ # Optional value.
36
+ #
37
+ # @option options [Symbol] :qualifier
38
+ # Mechanism qualifier.
39
+ #
16
40
  def initialize(name,options={})
17
41
  @name = name
18
42
 
@@ -20,26 +44,57 @@ module SPF
20
44
  @qualifier = options[:qualifier]
21
45
  end
22
46
 
47
+ #
48
+ # The mechanism qualifier.
49
+ #
50
+ # @return [:pass, :fail, :soft_fail, :neutral]
51
+ # The qualifier. Defaults to `:pass`.
52
+ #
23
53
  def qualifier
24
54
  @qualifier || :pass
25
55
  end
26
56
 
57
+ #
58
+ # Determines whether the qualifier is a "pass".
59
+ #
60
+ # @return [Boolean]
61
+ #
27
62
  def pass?
28
63
  @qualifier == :pass || @qualifier.nil?
29
64
  end
30
65
 
66
+ #
67
+ # Determines if the qualifier is a "fail".
68
+ #
69
+ # @return [Boolean]
70
+ #
31
71
  def fail?
32
72
  @qualifier == :fail
33
73
  end
34
74
 
75
+ #
76
+ # Determines whether the qualifier is a "soft_fail".
77
+ #
78
+ # @return [Boolean]
79
+ #
35
80
  def soft_fail?
36
81
  @qualifier == :soft_fail
37
82
  end
38
83
 
84
+ #
85
+ # Determines whether the qualifier is a "neutral".
86
+ #
87
+ # @return [Boolean]
88
+ #
39
89
  def neutral?
40
90
  @qualifier == :neutral
41
91
  end
42
92
 
93
+ #
94
+ # Converts the mechanism to a String.
95
+ #
96
+ # @return [String]
97
+ #
43
98
  def to_s
44
99
  str = "#{QUALIFIERS.invert[@qualifier]}#{@name}"
45
100
  str << ":#{@value}" if value
@@ -1,15 +1,38 @@
1
1
  module SPF
2
2
  module Query
3
+ #
4
+ # Represents SPF record modifiers.
5
+ #
3
6
  class Modifier
4
7
 
8
+ # Modifier name.
9
+ #
10
+ # @return [Symbol]
5
11
  attr_reader :name
6
12
 
13
+ # Modifier value.
14
+ #
15
+ # @return [String, MacroString, IP, nil]
7
16
  attr_reader :value
8
17
 
18
+ #
19
+ # Initializes the modifier.
20
+ #
21
+ # @param [Symbol] name
22
+ # Modifier name.
23
+ #
24
+ # @param [String, nil] value
25
+ # Modifier value.
26
+ #
9
27
  def initialize(name,value=nil)
10
28
  @name, @value = name, value
11
29
  end
12
30
 
31
+ #
32
+ # Converts the modifier to a String.
33
+ #
34
+ # @return [String]
35
+ #
13
36
  def to_s
14
37
  if @value then "#{@name}=#{@value}"
15
38
  else "#{@name}"
@@ -18,6 +41,9 @@ module SPF
18
41
 
19
42
  end
20
43
 
44
+ #
45
+ # Represents non-standard modifier names.
46
+ #
21
47
  class UnknownModifier < Modifier
22
48
  end
23
49
  end
@@ -24,7 +24,7 @@ module SPF
24
24
  records = resolver.getresources(host, Resolv::DNS::Resource::IN::TXT)
25
25
 
26
26
  records.each do |record|
27
- txt = record.strings.join(' ')
27
+ txt = record.strings.join
28
28
 
29
29
  if txt.include?('v=spf1')
30
30
  return txt
@@ -6,6 +6,9 @@ require 'resolv'
6
6
 
7
7
  module SPF
8
8
  module Query
9
+ #
10
+ # Represents a parsed SPF record.
11
+ #
9
12
  class Record
10
13
 
11
14
  include Enumerable
@@ -1,5 +1,6 @@
1
1
  module SPF
2
2
  module Query
3
- VERSION = '0.1.4'
3
+ # spf-query version
4
+ VERSION = '0.1.5'
4
5
  end
5
6
  end
@@ -19,6 +19,22 @@ describe SPF::Query do
19
19
  end
20
20
  end
21
21
 
22
+ context "when the domain.com has a TXT record" do
23
+ let(:domain) { 'yahoo.com' }
24
+
25
+ it "should return the TXT record containing the SPF record" do
26
+ expect(subject.query(domain)).to be == %{v=spf1 redirect=_spf.mail.yahoo.com}
27
+ end
28
+
29
+ context "and when the record is split into multiple strings" do
30
+ let(:domain) { 'fb.com' }
31
+
32
+ it "should join the strings, without spaces" do
33
+ expect(subject.query(domain)).to be == %{v=spf1 ip4:69.171.232.0/24 ip4:199.201.64.23 ip4:192.201.64.23 ip4:69.63.179.25 ip4:69.63.178.128/25 ip4:69.63.184.0/25 ip4:66.220.144.128/25 ip4:66.220.155.128/25 include:spf-00082601.pphosted.com mx -all}
34
+ end
35
+ end
36
+ end
37
+
22
38
  context "when the domain has a SPF type record" do
23
39
  let(:domain) { 'getlua.com' }
24
40
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spf-query
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - nicktitle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-11 00:00:00.000000000 Z
11
+ date: 2016-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet