dkim 0.2.0 → 1.0.0

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.
data/CHANGELOG.md CHANGED
@@ -1,18 +1,24 @@
1
1
  # dkim Changelog
2
2
 
3
- ## 2012.04.15, Version 0.2.0
3
+ ## 1.0.0 (2012-01-15)
4
+ * DKIM-Signature header is now prepended rather than appended
5
+ * Headers are signed in the order they appear
6
+ * Correct signing of repeated headers
7
+ * Correct signing of missing headers
8
+
9
+ ## 0.2.0 (2012-04-15)
4
10
  * Warn and strip existing signatures in Dkim::Interceptor
5
11
  * Dkim options can be accessed and modified using new Dkim.options or signed_mail.options hash
6
12
  * Refactoring and better testing
7
13
  * Improved documentation
8
14
 
9
- ## 2011.12.10, Version 0.1.0
15
+ ## 0.1.0 (2011-12-10)
10
16
  * Ensure header lines are not folded using Dkim::Interceptor
11
17
 
12
- ## 2011.07.25, Version 0.0.3
18
+ ## 0.0.3 (2011-07-25)
13
19
  * add Dkim::Interceptor class for integration with rails and [mail](https://github.com/mikel/mail)
14
20
 
15
- ## 2011.06.01, Version 0.0.2
21
+ ## 0.0.2 (2011-06-01)
16
22
 
17
23
  * add convenience method Dkim.sign
18
24
  * support for the simple canonicalization algorithm
@@ -20,7 +26,7 @@
20
26
  * correct handling of an empty message body
21
27
 
22
28
 
23
- ## 2011.05.10, Version 0.0.1
29
+ ## 0.0.1 (2011-05-10)
24
30
 
25
31
  * Initial release
26
32
 
@@ -0,0 +1,26 @@
1
+ module Dkim
2
+ class CanonicalizedHeaders
3
+ include Enumerable
4
+ def initialize header_list, signed_headers
5
+ @header_list = header_list
6
+ @signed_headers = signed_headers.map(&:downcase)
7
+ end
8
+ def each(&block)
9
+ header_hash = Hash.new {|h,k| h[k] = []}
10
+ @header_list.each do |header|
11
+ header_hash[header.relaxed_key] << header
12
+ end
13
+
14
+ @signed_headers.each do |key|
15
+ if header = header_hash[key].pop
16
+ yield header
17
+ end
18
+ end
19
+ end
20
+ def to_s(canonicalization)
21
+ map do |header|
22
+ header.to_s(canonicalization) + "\r\n"
23
+ end.join
24
+ end
25
+ end
26
+ end
@@ -1,28 +1,37 @@
1
1
 
2
2
  require 'dkim/header'
3
+ require 'dkim/tag_value_list'
4
+ require 'dkim/encodings'
3
5
 
4
6
  module Dkim
5
7
  class DkimHeader < Header
8
+ attr_reader :list
6
9
  def initialize values={}
7
10
  self.key = 'DKIM-Signature'
8
- @values = values.to_a.flatten.each_slice(2).to_a
11
+ @list = TagValueList.new values
9
12
  end
10
13
  def value
11
- @values.map do |(k, v)|
12
- " #{k}=#{v}"
13
- end.join(';')
14
+ " #{@list}"
14
15
  end
15
16
  def [] k
16
- value = @values.detect {|(a,b)| a == k }
17
- value && value[1]
17
+ encoder_for(k).decode(@list[k])
18
18
  end
19
19
  def []= k, v
20
- value = @values.detect {|(a,b)| a == k }
21
- if !value
22
- value = [k, nil]
23
- @values << value
24
- end
25
- value[1] = v
20
+ @list[k] = encoder_for(k).encode(v)
21
+ end
22
+
23
+ private
24
+ def encoder_for key
25
+ case key
26
+ when *%w{v a c d h l q s t x}
27
+ Encodings::PlainText
28
+ when *%w{i z}
29
+ Encodings::DkimQuotedPrintable
30
+ when *%w{b bh}
31
+ Encodings::Base64
32
+ else
33
+ raise "unknown key: #{key}"
34
+ end.new
26
35
  end
27
36
  end
28
37
  end
@@ -0,0 +1,3 @@
1
+ require 'dkim/encodings/base64.rb'
2
+ require 'dkim/encodings/dkim_quoted_printable.rb'
3
+ require 'dkim/encodings/plain_text.rb'
@@ -0,0 +1,12 @@
1
+ module Dkim
2
+ module Encodings
3
+ class Base64
4
+ def decode data
5
+ data.gsub(/\s/, '').unpack('m0')[0]
6
+ end
7
+ def encode data
8
+ [data].pack('m0').gsub("\n", '')
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+
2
+ module Dkim
3
+ module Encodings
4
+ # Implements DKIM-Quoted-Printable as described in rfc6376 section 2.11
5
+ class DkimQuotedPrintable
6
+ DkimUnafeChar = /[^\x21-\x3A\x3C\x3E-\x7E]/
7
+ def encode string
8
+ string.gsub(DkimUnafeChar) do |char|
9
+ "=%.2x" % char.unpack('C')
10
+ end
11
+ end
12
+ def decode string
13
+ string.gsub(/=([0-9A-F]{2})/) do
14
+ $1.hex.chr
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ module Dkim
2
+ module Encodings
3
+ class PlainText
4
+ def encode v; v; end
5
+ alias_method :decode, :encode
6
+ end
7
+ end
8
+ end
data/lib/dkim/header.rb CHANGED
@@ -38,5 +38,12 @@ module Dkim
38
38
  def canonical_simple
39
39
  "#{key}:#{value}"
40
40
  end
41
+
42
+ def self.parse header_string
43
+ header_string.split(/\r?\n(?!([ \t]))/).map do |header|
44
+ key, value = header.split(':', 2)
45
+ new(key, value)
46
+ end
47
+ end
41
48
  end
42
49
  end
@@ -14,8 +14,8 @@ module Dkim
14
14
  # generate new signature
15
15
  dkim_signature = SignedMail.new(message.encoded).dkim_header.value
16
16
 
17
- # append signature to message
18
- message.header.fields << Mail::DkimField.new(dkim_signature)
17
+ # prepend signature to message
18
+ message.header.fields.unshift Mail::DkimField.new(dkim_signature)
19
19
  message
20
20
  end
21
21
  end
@@ -3,8 +3,8 @@ require 'openssl'
3
3
  require 'dkim/body'
4
4
  require 'dkim/dkim_header'
5
5
  require 'dkim/header'
6
- require 'dkim/header_list'
7
6
  require 'dkim/options'
7
+ require 'dkim/canonicalized_headers'
8
8
 
9
9
  module Dkim
10
10
  class SignedMail
@@ -17,23 +17,28 @@ module Dkim
17
17
  def initialize message, options={}
18
18
  message = message.to_s.gsub(/\r?\n/, "\r\n")
19
19
  headers, body = message.split(/\r?\n\r?\n/, 2)
20
- @headers = HeaderList.new headers
20
+ @original_message = message
21
+ @headers = Header.parse headers
21
22
  @body = Body.new body
22
23
 
23
24
  # default options from Dkim.options
24
25
  @options = Dkim.options.merge(options)
25
26
  end
26
27
 
27
- # @return [Array<String>] Signed headers of message in their canonical forms
28
+ def canonicalized_headers
29
+ CanonicalizedHeaders.new(@headers, signed_headers)
30
+ end
31
+
32
+ # @return [Array<String>] lowercased names of headers in the order they are signed
28
33
  def signed_headers
29
- (@headers.map(&:relaxed_key) & signable_headers.map(&:downcase)).sort
34
+ @headers.map(&:relaxed_key).select do |key|
35
+ signable_headers.map(&:downcase).include?(key)
36
+ end
30
37
  end
31
38
 
32
39
  # @return [String] Signed headers of message in their canonical forms
33
40
  def canonical_header
34
- headers = signed_headers.map do |key|
35
- @headers[key].to_s(header_canonicalization) + "\r\n"
36
- end.join
41
+ canonicalized_headers.to_s(header_canonicalization)
37
42
  end
38
43
 
39
44
  # @return [String] Body of message in its canonical form
@@ -59,31 +64,24 @@ module Dkim
59
64
  dkim_header['t'] = (time || Time.now).to_i
60
65
 
61
66
  # Add body hash and blank signature
62
- dkim_header['bh']= base64_encode digest_alg.digest(canonical_body)
67
+ dkim_header['bh']= digest_alg.digest(canonical_body)
63
68
  dkim_header['h'] = signed_headers.join(':')
64
69
  dkim_header['b'] = ''
65
70
 
66
71
  # Calculate signature based on intermediate signature header
67
72
  headers = canonical_header
68
73
  headers << dkim_header.to_s(header_canonicalization)
69
- signature = base64_encode private_key.sign(digest_alg, headers)
70
- dkim_header['b'] = signature
74
+ dkim_header['b'] = private_key.sign(digest_alg, headers)
71
75
 
72
76
  dkim_header
73
77
  end
74
78
 
75
79
  # @return [String] Message combined with calculated dkim header signature
76
80
  def to_s
77
- headers = @headers.to_a + [dkim_header]
78
- headers.map(&:to_s).join("\r\n") +
79
- "\r\n\r\n" +
80
- @body.to_s
81
+ dkim_header.to_s + "\r\n" + @original_message
81
82
  end
82
83
 
83
84
  private
84
- def base64_encode data
85
- [data].pack('m0').gsub("\n",'')
86
- end
87
85
  def digest_alg
88
86
  case signing_algorithm
89
87
  when 'rsa-sha1'
@@ -0,0 +1,28 @@
1
+ module Dkim
2
+ class TagValueList
3
+ def initialize values={}
4
+ @keys = values.keys
5
+ @values = values.dup
6
+ end
7
+ def to_s
8
+ @keys.map do |k|
9
+ "#{k}=#{@values[k]}"
10
+ end.join('; ')
11
+ end
12
+ def [] k
13
+ @values[k]
14
+ end
15
+ def []= k, v
16
+ @keys << k unless self[k]
17
+ @values[k] = v
18
+ end
19
+ def self.parse string
20
+ list = new
21
+ string.split(';').each do |keyval|
22
+ key, value = keyval.split('=', 2)
23
+ list[key.strip] = value.strip
24
+ end
25
+ list
26
+ end
27
+ end
28
+ end
data/lib/dkim/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Dkim
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -14,11 +14,11 @@ module Mail
14
14
  end
15
15
 
16
16
  def encoded
17
- "#{name}:#{value}\n"
17
+ "#{name}:#{value}\r\n"
18
18
  end
19
19
 
20
20
  def decoded
21
- "#{name}:#{value}\n"
21
+ "#{name}:#{value}\r\n"
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,51 @@
1
+
2
+ require 'test_helper'
3
+
4
+ module Dkim
5
+ class CanonicalizedHeadersTest < MiniTest::Unit::TestCase
6
+ def test_maintains_order
7
+ headers = "ABCD".chars.map {|c| Header.new(c, c) }
8
+ header_keys = headers.map &:relaxed_key
9
+ header_keys.permutation.each do |signed_headers|
10
+ ch = CanonicalizedHeaders.new(headers, signed_headers)
11
+ assert_equal signed_headers, ch.map(&:relaxed_key)
12
+ end
13
+ end
14
+
15
+ def test_repeated_headers
16
+ headers = [
17
+ Header.new('A', '1'),
18
+ Header.new('B', '2'),
19
+ Header.new('C', '3'),
20
+ Header.new('A', '4'),
21
+ Header.new('D', '5')
22
+ ]
23
+ ch = CanonicalizedHeaders.new(headers, %w{A A B C D})
24
+ assert_equal %w{4 1 2 3 5}, ch.map(&:value)
25
+ assert_equal <<-eos.rfc_format, ch.to_s('simple')
26
+ A:4<CRLF>
27
+ A:1<CRLF>
28
+ B:2<CRLF>
29
+ C:3<CRLF>
30
+ D:5<CRLF>
31
+ eos
32
+ end
33
+
34
+ # missing headers should be ignored
35
+ def test_missing_headers
36
+ headers = [
37
+ Header.new('A', '1'),
38
+ Header.new('B', '2'),
39
+ Header.new('C', '3'),
40
+ ]
41
+ ch = CanonicalizedHeaders.new(headers, %w{A A B C})
42
+ assert_equal %w{a b c}, ch.map(&:relaxed_key)
43
+ assert_equal <<-eos.rfc_format, ch.to_s('simple')
44
+ A:1<CRLF>
45
+ B:2<CRLF>
46
+ C:3<CRLF>
47
+ eos
48
+ end
49
+ end
50
+ end
51
+
@@ -1,5 +1,6 @@
1
1
 
2
2
  require 'test_helper'
3
+ require 'base64'
3
4
 
4
5
  module Dkim
5
6
  class DkimHeaderTest < MiniTest::Unit::TestCase
@@ -15,8 +16,8 @@ module Dkim
15
16
  @header['q'] = 'dns/txt'
16
17
  @header['i'] = '[email protected]'
17
18
  @header['h'] = 'Received : From : To : Subject : Date : Message-ID'
18
- @header['bh']= '2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8='
19
- @header['b'] = 'AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHutKVdkLLkpVaVVQPzeRDI009SO2Il5Lu7rDNH6mZckBdrIx0orEtZV4bmp/YzhwvcubU4='
19
+ @header['bh']= Base64.decode64 '2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8='
20
+ @header['b'] = Base64.decode64 'AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHutKVdkLLkpVaVVQPzeRDI009SO2Il5Lu7rDNH6mZckBdrIx0orEtZV4bmp/YzhwvcubU4='
20
21
  end
21
22
 
22
23
  def test_correct_format
@@ -0,0 +1,24 @@
1
+ module Dkim
2
+ class EncodingsTest < MiniTest::Unit::TestCase
3
+ def test_plain_text
4
+ @encoder = Encodings::PlainText.new
5
+ assert_equal 'testing123', @encoder.encode('testing123')
6
+ assert_equal 'testing123', @encoder.decode('testing123')
7
+ end
8
+ def test_base64
9
+ @encoder = Encodings::Base64.new
10
+ assert_equal 'dGVzdGluZzEyMw==', @encoder.encode('testing123')
11
+ assert_equal 'testing123', @encoder.decode('dGVzdGluZzEyMw==')
12
+ end
13
+ def test_quoted_printable
14
+ @encoder = Encodings::DkimQuotedPrintable.new
15
+ assert_equal 'testing123', @encoder.encode('testing123')
16
+ assert_equal 'testing123', @encoder.decode('testing123')
17
+
18
+ encoded = 'From:[email protected]|To:[email protected]|Subject:demo=20run|Date:July=205,=202005=203:44:08=20PM=20-0700'
19
+ decoded = 'From:[email protected]|To:[email protected]|Subject:demo run|Date:July 5, 2005 3:44:08 PM -0700'
20
+ assert_equal encoded, @encoder.encode(decoded)
21
+ assert_equal decoded, @encoder.decode(encoded)
22
+ end
23
+ end
24
+ end
@@ -40,6 +40,9 @@ Joe.
40
40
  def setup
41
41
  @original_options = Dkim.options.dup
42
42
 
43
+ # ensure time does not change
44
+ Dkim.time = Time.now
45
+
43
46
  mail = EXAMPLEEMAIL.dup
44
47
 
45
48
  @mail = Mail.new(mail)
@@ -103,6 +106,20 @@ Joe.
103
106
  assert_equal 1, @mail.header.fields.count { |field| field.name =~ /^DKIM-Signature$/i }
104
107
  assert_equal 1, @mail.encoded.scan('DKIM-Signature').count
105
108
  end
109
+
110
+ def test_same_output_as_direct_usage
111
+ dkim_header = @mail['DKIM-Signature']
112
+
113
+ # Most necessary under simple
114
+ Dkim.header_canonicalization = 'simple'
115
+ Dkim.body_canonicalization = 'simple'
116
+
117
+ expected = Dkim.sign @mail.to_s
118
+
119
+ Interceptor.delivering_email(@mail)
120
+
121
+ assert_equal expected, @mail.to_s
122
+ end
106
123
  end
107
124
  end
108
125
 
@@ -1,3 +1,5 @@
1
+ require 'test_helper'
2
+
1
3
  module Dkim
2
4
  class OptionsTest < MiniTest::Unit::TestCase
3
5
  def setup
@@ -9,17 +9,18 @@ module Dkim
9
9
 
10
10
  def test_defaults
11
11
  signed_mail = SignedMail.new(@mail, :time => Time.at(1234567890))
12
- dkim_header = signed_mail.dkim_header
12
+ dkim_header = signed_mail.dkim_header.list
13
13
 
14
14
  assert_equal 'rsa-sha256', dkim_header['a']
15
15
  assert_equal 'brisbane', dkim_header['s']
16
16
  assert_equal 'example.com', dkim_header['d']
17
17
  assert_equal 'relaxed/relaxed', dkim_header['c']
18
18
  assert_equal 'dns/txt', dkim_header['q']
19
+ assert_equal 'from:to:subject:date:message-id', dkim_header['h']
19
20
 
20
21
  # bh value from RFC 6376
21
22
  assert_equal '2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=', dkim_header['bh']
22
- assert_equal 'mamSUb17FQSZY2lfkeAsH/DvmpHsXdaFAu6BfbVblGBQ5+2yIPCx+clF5wClVBj97utSZb1WwOM0iup1JL37FI/UG+bxHo+MdGLqbLR63THGEdVF8FVeST4o4EQTWe0H3P/sU2rRZ61+M2SrTS94QkKAgj89QNOG48xSAO9xdfs=', dkim_header['b']
23
+ assert_equal 'dQOeSpGJTfSbX4hPGGsy4ipcNAzC/33K7XaEXkjBneJJhv6MczHkJNsfmXeYESNIh5WVTuvE5IbnDPBVFrL+b3GKiLiyp/vlKO2NJViX4dLnKT/GdxjJh06ljZcYjUA+PorHvMwdu+cDsCffN8A7IhfVdsFruQr3vFPD0JyJ9XU=', dkim_header['b']
23
24
  end
24
25
 
25
26
  def test_overrides
@@ -33,15 +34,16 @@ module Dkim
33
34
  :time => Time.at(1234567890)
34
35
  }
35
36
  signed_mail = SignedMail.new(@mail, options)
36
- dkim_header = signed_mail.dkim_header
37
-
38
- assert_equal 'rsa-sha1', dkim_header['a']
39
- assert_equal 'sidney', dkim_header['s']
40
- assert_equal 'example.org', dkim_header['d']
41
- assert_equal 'simple/simple', dkim_header['c']
42
- assert_equal 'dns/txt', dkim_header['q']
43
- assert_equal 'yk6W9pJJilr5MMgeEdSd7J3IaJI=', dkim_header['bh']
44
- assert_equal 'sqYGmen+fouyIj83HuJ1v+1x40xp481bLxxcgAWMFsWYEwG05KYl+o0ZWn8jqgd1coKlX29o9iFjcMtZHudT8KpOdcLVYpY3gxzNfEgH79eRz32/ieGgroSK2GoMA/aV1QkxfUZexLUdj9oOX8uaMYXDkj8RGmlEGi+NDz/e4sE=', dkim_header['b']
37
+ dkim_header = signed_mail.dkim_header.list
38
+
39
+ assert_equal 'rsa-sha1', dkim_header['a']
40
+ assert_equal 'sidney', dkim_header['s']
41
+ assert_equal 'example.org', dkim_header['d']
42
+ assert_equal 'simple/simple', dkim_header['c']
43
+ assert_equal 'dns/txt', dkim_header['q']
44
+ assert_equal "from:to:subject:date:message-id", dkim_header['h']
45
+ assert_equal 'yk6W9pJJilr5MMgeEdSd7J3IaJI=', dkim_header['bh']
46
+ assert_equal 't+dk4yxTI2ByZxxRzkwhZhM4WzTZjGWHiWnS2t4pg7oT7fAIlMrfihJ/CIvGmYqYv4lbq4LStHqHx9TmEgxrkjLevHtuqhxkN55xJ2vA2QzTzFi2fMDZ4fFqWy4QtvlLjBAhevG+LXpmjPYec1cyeMlHlPAthq5+RNi6NHErJiM=', dkim_header['b']
45
47
  end
46
48
 
47
49
  def test_empty_body_hashes
@@ -56,11 +58,27 @@ module Dkim
56
58
  ['47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=', {:body_canonicalization => 'relaxed', :signing_algorithm => 'rsa-sha256'}],
57
59
  ].each do |body_hash, options|
58
60
  signed_mail = SignedMail.new(@mail, options)
59
- dkim_header = signed_mail.dkim_header
61
+ dkim_header = signed_mail.dkim_header.list
60
62
 
61
63
  assert_equal body_hash, dkim_header['bh']
62
64
  end
63
65
  end
66
+
67
+ def test_multiple_instances_of_header
68
+ @mail = <<-eos
69
+ Received: <A>
70
+ Received: <B>
71
+ Received: <C>
72
+
73
+ eos
74
+
75
+ signed_mail = SignedMail.new(@mail, :header_canonicalization => 'simple', :signable_headers => Dkim::DefaultHeaders + ['Received'])
76
+
77
+ assert_equal "received:received:received", signed_mail.dkim_header['h']
78
+
79
+ headers = signed_mail.canonical_header
80
+ assert_equal "Received: <C>\r\nReceived: <B>\r\nReceived: <A>\r\n", headers.to_s
81
+ end
64
82
  end
65
83
  end
66
84
 
@@ -0,0 +1,28 @@
1
+
2
+ require 'test_helper'
3
+
4
+ module Dkim
5
+ class TagValueListTest < MiniTest::Unit::TestCase
6
+ def test_replacement
7
+ @list = TagValueList.new
8
+
9
+ @list['a'] = '1'
10
+ @list['b'] = '2'
11
+ @list['c'] = '3'
12
+ assert_equal 'a=1; b=2; c=3', @list.to_s
13
+
14
+ @list['b'] = '4'
15
+ assert_equal 'a=1; b=4; c=3', @list.to_s
16
+ end
17
+ def test_correct_format
18
+ @list = TagValueList.new
19
+
20
+ @list['b'] = '2'
21
+ @list['a'] = '1'
22
+ @list['c'] = '!@#$%^'
23
+
24
+ assert_equal 'b=2; a=1; c=!@#$%^', @list.to_s
25
+ end
26
+ end
27
+ end
28
+
data/test/test_helper.rb CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ $LOAD_PATH << File.expand_path('../../lib', __FILE__)
3
+
2
4
  require 'minitest/autorun'
3
5
  require 'dkim'
4
6
 
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dkim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
5
4
  prerelease:
5
+ version: 1.0.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - John Hawthorn
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-16 00:00:00.000000000 Z
12
+ date: 2013-01-15 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: gem for adding DKIM signatures to email messages
15
15
  email:
@@ -31,19 +31,27 @@ files:
31
31
  - lib/dkim.rb
32
32
  - lib/dkim/body.rb
33
33
  - lib/dkim/canonicalizable.rb
34
+ - lib/dkim/canonicalized_headers.rb
34
35
  - lib/dkim/dkim_header.rb
36
+ - lib/dkim/encodings.rb
37
+ - lib/dkim/encodings/base64.rb
38
+ - lib/dkim/encodings/dkim_quoted_printable.rb
39
+ - lib/dkim/encodings/plain_text.rb
35
40
  - lib/dkim/header.rb
36
- - lib/dkim/header_list.rb
37
41
  - lib/dkim/interceptor.rb
38
42
  - lib/dkim/options.rb
39
43
  - lib/dkim/signed_mail.rb
44
+ - lib/dkim/tag_value_list.rb
40
45
  - lib/dkim/version.rb
41
46
  - lib/mail/dkim_field.rb
42
47
  - test/dkim/canonicalization_test.rb
48
+ - test/dkim/canonicalized_headers_test.rb
43
49
  - test/dkim/dkim_header_test.rb
50
+ - test/dkim/encodings_test.rb
44
51
  - test/dkim/interceptor_test.rb
45
52
  - test/dkim/options_test.rb
46
53
  - test/dkim/signed_mail_test.rb
54
+ - test/dkim/tag_value_list_test.rb
47
55
  - test/test_helper.rb
48
56
  homepage: https://github.com/jhawthorn/dkim
49
57
  licenses: []
@@ -57,28 +65,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
65
  - - ! '>='
58
66
  - !ruby/object:Gem::Version
59
67
  version: '0'
60
- segments:
61
- - 0
62
- hash: -2701069676603955611
63
68
  required_rubygems_version: !ruby/object:Gem::Requirement
64
69
  none: false
65
70
  requirements:
66
71
  - - ! '>='
67
72
  - !ruby/object:Gem::Version
68
73
  version: '0'
69
- segments:
70
- - 0
71
- hash: -2701069676603955611
72
74
  requirements: []
73
75
  rubyforge_project: dkim
74
- rubygems_version: 1.8.17
76
+ rubygems_version: 1.8.24
75
77
  signing_key:
76
78
  specification_version: 3
77
79
  summary: DKIM library in ruby
78
80
  test_files:
79
81
  - test/dkim/canonicalization_test.rb
82
+ - test/dkim/canonicalized_headers_test.rb
80
83
  - test/dkim/dkim_header_test.rb
84
+ - test/dkim/encodings_test.rb
81
85
  - test/dkim/interceptor_test.rb
82
86
  - test/dkim/options_test.rb
83
87
  - test/dkim/signed_mail_test.rb
88
+ - test/dkim/tag_value_list_test.rb
84
89
  - test/test_helper.rb
@@ -1,19 +0,0 @@
1
- module Dkim
2
- class HeaderList
3
- include Enumerable
4
- def initialize headers
5
- @headers = headers.split(/\r?\n(?!([ \t]))/).map do |header|
6
- key, value = header.split(':', 2)
7
- Header.new(key, value)
8
- end
9
- end
10
- def [](key)
11
- @headers.detect do |header|
12
- header.relaxed_key == key
13
- end
14
- end
15
- def each(&block)
16
- @headers.each(&block)
17
- end
18
- end
19
- end
OSZAR »