mail-gpg 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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