mail-gpg 0.1.4 → 0.1.5

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.
@@ -1,3 +1,8 @@
1
+ == 0.1.5 2014-05-28
2
+
3
+ * signing refactoring so the signed part only contains the necessary headers
4
+ * preserve Auto-Submitted header
5
+
1
6
  == 0.1.4 2014-05-26
2
7
 
3
8
  * preserve return path headers and message id
@@ -10,7 +10,7 @@ require 'mail/gpg/inline_decrypted_message'
10
10
  require 'mail/gpg/gpgme_helper'
11
11
  require 'mail/gpg/message_patch'
12
12
  require 'mail/gpg/rails'
13
- require 'mail/gpg/sign_part'
13
+ require 'mail/gpg/signed_part'
14
14
 
15
15
  module Mail
16
16
  module Gpg
@@ -45,10 +45,11 @@ module Mail
45
45
  end
46
46
 
47
47
  def self.sign(cleartext_mail, options = {})
48
+ options[:sign_as] ||= cleartext_mail.from
48
49
  construct_mail(cleartext_mail, options) do
49
- options[:sign_as] ||= cleartext_mail.from
50
- add_part Mail::Part.new(cleartext_mail)
51
- add_part SignPart.new(cleartext_mail, options)
50
+ to_be_signed = SignedPart.build(cleartext_mail)
51
+ add_part to_be_signed
52
+ add_part to_be_signed.sign(options)
52
53
 
53
54
  content_type "multipart/signed; micalg=pgp-sha1; protocol=\"application/pgp-signature\"; boundary=#{boundary}"
54
55
  body.preamble = options[:preamble] || "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)"
@@ -94,16 +95,21 @@ module Mail
94
95
  false
95
96
  end
96
97
 
98
+ STANDARD_HEADERS = %w(from to cc bcc subject reply_to in_reply_to return_path message_id)
99
+ CUSTOM_HEADERS = %w(Auto-Submitted)
100
+
97
101
  private
98
102
 
99
103
  def self.construct_mail(cleartext_mail, options, &block)
100
104
  Mail.new do
101
105
  self.perform_deliveries = cleartext_mail.perform_deliveries
102
- %w(from to cc bcc subject reply_to in_reply_to return_path message_id).each do |field|
106
+ STANDARD_HEADERS.each do |field|
103
107
  send field, cleartext_mail.send(field)
104
108
  end
105
109
  cleartext_mail.header.fields.each do |field|
106
- header[field.name] = field.value if field.name =~ /^X-/
110
+ if CUSTOM_HEADERS.include?(field.name) or field.name =~ /^X-/
111
+ header[field.name] = field.value
112
+ end
107
113
  end
108
114
  instance_eval &block
109
115
  end
@@ -0,0 +1,37 @@
1
+ require 'mail/part'
2
+ require 'mail/gpg/sign_part'
3
+
4
+ module Mail
5
+ module Gpg
6
+
7
+ class SignedPart < Mail::Part
8
+
9
+ def self.build(cleartext_mail)
10
+ new do
11
+ if cleartext_mail.body.multipart?
12
+ if cleartext_mail.content_type =~ /^(multipart[^;]+)/
13
+ # preserve multipart/alternative etc
14
+ content_type $1
15
+ else
16
+ content_type 'multipart/mixed'
17
+ end
18
+ cleartext_mail.body.parts.each do |p|
19
+ add_part p
20
+ end
21
+ else
22
+ content_type cleartext_mail.content_type
23
+ body cleartext_mail.body.raw_source
24
+ end
25
+ end
26
+ end
27
+
28
+ def sign(options)
29
+ SignPart.new(self, options)
30
+ end
31
+
32
+
33
+ end
34
+
35
+
36
+ end
37
+ end
@@ -1,5 +1,5 @@
1
1
  module Mail
2
2
  module Gpg
3
- VERSION = "0.1.4"
3
+ VERSION = "0.1.5"
4
4
  end
5
5
  end
@@ -69,8 +69,9 @@ class ActionMailerTest < Test::Unit::TestCase
69
69
  assert_equal 'signed', delivered.subject
70
70
  assert_equal 2, delivered.parts.size
71
71
  assert sign_part = delivered.parts.detect{|p| p.content_type =~ /signature\.asc/}
72
- GPGME::Crypto.new.verify(sign_part.body.to_s, signed_text: m.encoded) do |sig|
73
- assert true == sig.valid?
72
+ assert signed_part = delivered.parts.detect{|p| p.content_type !~ /signature\.asc/}
73
+ GPGME::Crypto.new.verify(sign_part.body.to_s, signed_text: signed_part.encoded) do |sig|
74
+ assert sig.valid?
74
75
  end
75
76
  end
76
77
  end
@@ -115,8 +116,9 @@ class ActionMailerTest < Test::Unit::TestCase
115
116
  assert_equal 'signed', delivered.subject
116
117
  assert_equal 2, delivered.parts.size
117
118
  assert sign_part = delivered.parts.detect{|p| p.content_type =~ /signature\.asc/}
118
- GPGME::Crypto.new.verify(sign_part.body.to_s, signed_text: m.encoded) do |sig|
119
- assert true == sig.valid?
119
+ assert signed_part = delivered.parts.detect{|p| p.content_type !~ /signature\.asc/}
120
+ GPGME::Crypto.new.verify(sign_part.body.to_s, signed_text: signed_part.encoded) do |sig|
121
+ assert sig.valid?
120
122
  end
121
123
  end
122
124
  end
@@ -30,18 +30,24 @@ class GpgTest < Test::Unit::TestCase
30
30
  def check_signature(mail = @mail, signed = @signed)
31
31
  assert signed.signed?
32
32
  assert signature = signed.parts.detect{|p| p.content_type =~ /signature\.asc/}.body.to_s
33
- GPGME::Crypto.new.verify(signature, signed_text: mail.encoded) do |sig|
34
- assert true == sig.valid?
33
+ assert signed_part = signed.parts.detect{|p| p.content_type !~ /signature\.asc/}
34
+ assert_equal mail.parts.size, signed_part.parts.size
35
+ GPGME::Crypto.new.verify(signature, signed_text: signed_part.encoded) do |sig|
36
+ assert sig.valid?
35
37
  end
36
38
  assert Mail::Gpg.signature_valid?(signed)
37
39
  end
38
40
 
39
41
  def check_mime_structure_signed(mail = @mail, signed = @signed)
42
+ assert_match /multipart\/signed/, signed.content_type
40
43
  assert_equal 2, signed.parts.size
41
44
  orig_part, sign_part = signed.parts
42
45
 
43
46
  assert_equal 'application/pgp-signature; name=signature.asc', sign_part.content_type
44
- assert_equal orig_part.content_type, @mail.content_type
47
+ assert_equal mail.parts.size, orig_part.parts.size
48
+ assert_nil orig_part.to
49
+ assert_nil orig_part.from
50
+ assert_nil orig_part.subject
45
51
  end
46
52
 
47
53
  def check_headers_signed(mail = @mail, signed = @signed)
@@ -73,6 +79,7 @@ class GpgTest < Test::Unit::TestCase
73
79
  from 'jane@foo.bar'
74
80
  subject 'test test'
75
81
  body 'sign me!'
82
+ content_type 'text/plain; charset=UTF-8'
76
83
  end
77
84
  end
78
85
 
@@ -138,9 +145,19 @@ class GpgTest < Test::Unit::TestCase
138
145
  end
139
146
  end
140
147
 
141
- context 'multipart mail' do
148
+ context 'multipart alternative mail' do
142
149
  setup do
143
- @mail.add_file 'Rakefile'
150
+ @mail = Mail.new do
151
+ to 'joe@foo.bar'
152
+ from 'jane@foo.bar'
153
+ subject 'test test'
154
+ text_part do
155
+ body 'sign me!'
156
+ end
157
+ html_part do
158
+ body '<h1>H1</h1>'
159
+ end
160
+ end
144
161
  @signed = Mail::Gpg.sign(@mail, password: 'abc')
145
162
  end
146
163
 
@@ -158,10 +175,12 @@ class GpgTest < Test::Unit::TestCase
158
175
 
159
176
  should 'have multiple parts in original content' do
160
177
  assert original_part = @signed.parts.first
161
- assert original_part.multipart?
162
- assert_equal 2, original_part.parts.size
178
+ assert @mail.multipart?
179
+ assert_match /alternative/, @mail.content_type
180
+ assert_match /alternative/, original_part.content_type
181
+ assert_equal original_part.parts.size, @mail.parts.size
163
182
  assert_match /sign me!/, original_part.parts.first.body.to_s
164
- assert_match /Rakefile/, original_part.parts.last.content_disposition
183
+ assert_match /H1/, original_part.parts.last.body.to_s
165
184
  end
166
185
  end
167
186
  end
@@ -44,9 +44,14 @@ class MessageTest < Test::Unit::TestCase
44
44
 
45
45
  context "" do
46
46
  setup do
47
+ @mail.header['Auto-Submitted'] = 'foo'
47
48
  @mail.deliver
48
49
  end
49
50
 
51
+ should 'keep custom header value' do
52
+ assert_equal 'foo', @mails.first.header['Auto-Submitted'].value
53
+ end
54
+
50
55
  should "deliver signed mail" do
51
56
  assert_equal 1, @mails.size
52
57
  assert m = @mails.first
@@ -56,12 +61,12 @@ class MessageTest < Test::Unit::TestCase
56
61
  assert m.multipart?
57
62
  assert m.signature_valid?
58
63
  assert sign_part = m.parts.last
59
- assert m = Mail::Message.new(m.parts.first)
60
- assert !m.multipart?
61
- GPGME::Crypto.new.verify(sign_part.body.to_s, signed_text: m.encoded) do |sig|
62
- assert true == sig.valid?
64
+ #assert m = Mail::Message.new(m.parts.first)
65
+ #assert !m.multipart?
66
+ GPGME::Crypto.new.verify(sign_part.body.to_s, signed_text: m.parts.first.encoded) do |sig|
67
+ assert sig.valid?
63
68
  end
64
- assert_equal 'i am unencrypted', m.body.to_s
69
+ assert_equal 'i am unencrypted', m.parts.first.body.to_s
65
70
  end
66
71
 
67
72
  should "fail signature on tampered body" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mail-gpg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-27 00:00:00.000000000 Z
12
+ date: 2014-05-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mail
@@ -168,6 +168,7 @@ files:
168
168
  - lib/mail/gpg/rails.rb
169
169
  - lib/mail/gpg/rails/action_mailer_base_patch.rb
170
170
  - lib/mail/gpg/sign_part.rb
171
+ - lib/mail/gpg/signed_part.rb
171
172
  - lib/mail/gpg/version.rb
172
173
  - lib/mail/gpg/version_part.rb
173
174
  - mail-gpg.gemspec