mail-gpg 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/mail/gpg.rb CHANGED
@@ -23,18 +23,18 @@ module Mail
23
23
  # local keychain before sending the mail.
24
24
  # :always_trust : send encrypted mail to untrusted receivers, true by default
25
25
  def self.encrypt(cleartext_mail, options = {})
26
- construct_mail(cleartext_mail, options) do
27
- receivers = []
28
- receivers += cleartext_mail.to if cleartext_mail.to
29
- receivers += cleartext_mail.cc if cleartext_mail.cc
30
- receivers += cleartext_mail.bcc if cleartext_mail.bcc
26
+ construct_mail(cleartext_mail, options) do
27
+ receivers = []
28
+ receivers += cleartext_mail.to if cleartext_mail.to
29
+ receivers += cleartext_mail.cc if cleartext_mail.cc
30
+ receivers += cleartext_mail.bcc if cleartext_mail.bcc
31
31
 
32
- if options[:sign_as]
33
- options[:sign] = true
34
- options[:signers] = options.delete(:sign_as)
35
- elsif options[:sign]
36
- options[:signers] = cleartext_mail.from
37
- end
32
+ if options[:sign_as]
33
+ options[:sign] = true
34
+ options[:signers] = options.delete(:sign_as)
35
+ elsif options[:sign]
36
+ options[:signers] = cleartext_mail.from
37
+ end
38
38
 
39
39
  add_part VersionPart.new
40
40
  add_part EncryptedPart.new(cleartext_mail,
@@ -44,16 +44,16 @@ module Mail
44
44
  end
45
45
  end
46
46
 
47
- def self.sign(cleartext_mail, options = {})
48
- construct_mail(cleartext_mail, options) do
49
- options[:sign_as] ||= cleartext_mail.from
50
- add_part SignPart.new(cleartext_mail, options)
51
- add_part Mail::Part.new(cleartext_mail)
47
+ def self.sign(cleartext_mail, options = {})
48
+ construct_mail(cleartext_mail, options) do
49
+ options[:sign_as] ||= cleartext_mail.from
50
+ add_part SignPart.new(cleartext_mail, options)
51
+ add_part Mail::Part.new(cleartext_mail)
52
52
 
53
- content_type "multipart/signed; micalg=pgp-sha1; protocol=\"application/pgp-signature\"; boundary=#{boundary}"
54
- body.preamble = options[:preamble] || "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)"
55
- end
56
- end
53
+ content_type "multipart/signed; micalg=pgp-sha1; protocol=\"application/pgp-signature\"; boundary=#{boundary}"
54
+ body.preamble = options[:preamble] || "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)"
55
+ end
56
+ end
57
57
 
58
58
  def self.decrypt(encrypted_mail, options = {})
59
59
  if encrypted_mime?(encrypted_mail)
@@ -64,7 +64,7 @@ module Mail
64
64
  raise EncodingError, "Unsupported encryption format '#{encrypted_mail.content_type}'"
65
65
  end
66
66
  end
67
-
67
+
68
68
  def self.encrypted?(mail)
69
69
  return true if encrypted_mime?(mail)
70
70
  return true if encrypted_inline?(mail)
@@ -73,7 +73,7 @@ module Mail
73
73
 
74
74
  private
75
75
 
76
- def self.construct_mail(cleartext_mail, options, &block)
76
+ def self.construct_mail(cleartext_mail, options, &block)
77
77
  Mail.new do
78
78
  self.perform_deliveries = cleartext_mail.perform_deliveries
79
79
  %w(from to cc bcc subject reply_to in_reply_to).each do |field|
@@ -82,9 +82,9 @@ module Mail
82
82
  cleartext_mail.header.fields.each do |field|
83
83
  header[field.name] = field.value if field.name =~ /^X-/
84
84
  end
85
- instance_eval &block
86
- end
87
- end
85
+ instance_eval &block
86
+ end
87
+ end
88
88
 
89
89
  # decrypts PGP/MIME (RFC 3156, section 4) encrypted mail
90
90
  def self.decrypt_pgp_mime(encrypted_mail, options)
@@ -95,7 +95,17 @@ module Mail
95
95
  if !VersionPart.isVersionPart? encrypted_mail.parts[0]
96
96
  raise EncodingError, "RFC 3136 first part not a valid version part '#{encrypted_mail.parts[0]}'"
97
97
  end
98
- Mail.new(DecryptedPart.new(encrypted_mail.parts[1], options))
98
+ Mail.new(DecryptedPart.new(encrypted_mail.parts[1], options)) do
99
+ %w(from to cc bcc subject reply_to in_reply_to).each do |field|
100
+ send field, encrypted_mail.send(field)
101
+ end
102
+ # copy header fields
103
+ # headers from the encrypted part (which are already set by Mail.new
104
+ # above) will be preserved.
105
+ encrypted_mail.header.fields.each do |field|
106
+ header[field.name] = field.value if field.name =~ /^X-/ && header[field.name].nil?
107
+ end
108
+ end
99
109
  end
100
110
 
101
111
  # decrypts inline PGP encrypted mail
@@ -7,9 +7,9 @@ module Mail
7
7
  # :verify: decrypt and verify
8
8
  def initialize(cipher_part, options = {})
9
9
  if cipher_part.mime_type != EncryptedPart::CONTENT_TYPE
10
- raise EncodingError, "RFC 3136 incorrect mime type for encrypted part '#{cipher_part.mime_type}'"
10
+ raise EncodingError, "RFC 3156 incorrect mime type for encrypted part '#{cipher_part.mime_type}'"
11
11
  end
12
-
12
+
13
13
  decrypted = GpgmeHelper.decrypt(cipher_part.body.decoded, options)
14
14
  super(decrypted)
15
15
  end
@@ -10,7 +10,7 @@ module Mail
10
10
  if options.delete(:encrypt)
11
11
  encrypted_mail = Mail::Gpg.encrypt(mail, options)
12
12
  elsif options[:sign] || options[:sign_as]
13
- encrypted_mail = Mail::Gpg.sign(mail, options)
13
+ encrypted_mail = Mail::Gpg.sign(mail, options)
14
14
  else
15
15
  # encrypt and sign are off -> do not encrypt or sign
16
16
  yield
@@ -1,5 +1,5 @@
1
1
  module Mail
2
2
  module Gpg
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
5
5
  end
@@ -20,18 +20,18 @@ class DecryptedPartTest < Test::Unit::TestCase
20
20
  assert mail.message_id == @mail.message_id
21
21
  assert mail.message_id != @part.message_id
22
22
  end
23
-
23
+
24
24
  should 'decrypt and verify' do
25
25
  assert mail = Mail::Gpg::DecryptedPart.new(@part, { :verify => true, :password => 'abc' })
26
26
  assert mail == @mail
27
27
  assert mail.message_id == @mail.message_id
28
28
  assert mail.message_id != @part.message_id
29
29
  end
30
-
30
+
31
31
  should 'raise encoding error for non gpg mime type' do
32
32
  part = Mail::Part.new(@part)
33
33
  part.content_type = 'text/plain'
34
34
  assert_raise(EncodingError) { Mail::Gpg::DecryptedPart.new(part) }
35
- end
35
+ end
36
36
  end
37
37
  end
data/test/gpg_test.rb CHANGED
@@ -28,20 +28,20 @@ class GpgTest < Test::Unit::TestCase
28
28
  assert_equal mail.to_s, clear
29
29
  end
30
30
 
31
- def check_signature(mail = @mail, signed = @signed)
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?
35
- end
36
- end
31
+ def check_signature(mail = @mail, signed = @signed)
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?
35
+ end
36
+ end
37
37
 
38
- def check_mime_structure_signed(mail = @mail, signed = @signed)
39
- assert_equal 2, signed.parts.size
40
- sign_part, orig_part = signed.parts
38
+ def check_mime_structure_signed(mail = @mail, signed = @signed)
39
+ assert_equal 2, signed.parts.size
40
+ sign_part, orig_part = signed.parts
41
41
 
42
- assert_equal 'application/pgp-signature; name=signature.asc', sign_part.content_type
43
- assert_equal orig_part.content_type, @mail.content_type
44
- end
42
+ assert_equal 'application/pgp-signature; name=signature.asc', sign_part.content_type
43
+ assert_equal orig_part.content_type, @mail.content_type
44
+ end
45
45
 
46
46
  def check_headers_signed(mail = @mail, signed = @signed)
47
47
  assert_equal mail.to, signed.to
@@ -57,33 +57,33 @@ class GpgTest < Test::Unit::TestCase
57
57
  end
58
58
  end
59
59
 
60
- context "gpg signed" do
61
- setup do
62
- @mail = Mail.new do
63
- to 'joe@foo.bar'
64
- from 'jane@foo.bar'
65
- subject 'test test'
66
- body 'sign me!'
67
- end
68
- end
69
-
70
- context 'simple mail' do
71
- setup do
72
- @signed = Mail::Gpg.sign(@mail, password: 'abc')
73
- end
74
-
75
- should 'have same recipients and subject' do
76
- check_headers_signed
77
- end
78
-
79
- should 'have proper gpgmime structure' do
80
- check_mime_structure_signed
81
- end
82
-
83
- should 'have correct signature' do
84
- check_signature
85
- end
86
- end
60
+ context "gpg signed" do
61
+ setup do
62
+ @mail = Mail.new do
63
+ to 'joe@foo.bar'
64
+ from 'jane@foo.bar'
65
+ subject 'test test'
66
+ body 'sign me!'
67
+ end
68
+ end
69
+
70
+ context 'simple mail' do
71
+ setup do
72
+ @signed = Mail::Gpg.sign(@mail, password: 'abc')
73
+ end
74
+
75
+ should 'have same recipients and subject' do
76
+ check_headers_signed
77
+ end
78
+
79
+ should 'have proper gpgmime structure' do
80
+ check_mime_structure_signed
81
+ end
82
+
83
+ should 'have correct signature' do
84
+ check_signature
85
+ end
86
+ end
87
87
 
88
88
  context 'mail with custom header' do
89
89
  setup do
@@ -153,7 +153,7 @@ class GpgTest < Test::Unit::TestCase
153
153
  assert_match /Rakefile/, original_part.parts.last.content_disposition
154
154
  end
155
155
  end
156
- end
156
+ end
157
157
 
158
158
  context "gpg encrypted" do
159
159
 
@@ -188,7 +188,7 @@ class GpgTest < Test::Unit::TestCase
188
188
  assert mail == @mail
189
189
  end
190
190
  end
191
-
191
+
192
192
  context 'simple mail (signed)' do
193
193
  setup do
194
194
  @encrypted = Mail::Gpg.encrypt(@mail, { :sign => true, :password => 'abc' })
@@ -210,12 +210,13 @@ class GpgTest < Test::Unit::TestCase
210
210
  assert mail = Mail::Gpg.decrypt(@encrypted, { :verify => true, :password => 'abc' })
211
211
  assert mail == @mail
212
212
  end
213
- end
213
+ end
214
214
 
215
215
  context 'mail with custom header' do
216
216
  setup do
217
217
  @mail.header['X-Custom-Header'] = 'custom value'
218
218
  @encrypted = Mail::Gpg.encrypt(@mail)
219
+ @encrypted.header['X-Another-Header'] = 'another value'
219
220
  end
220
221
 
221
222
  should 'have same recipients and subject' do
@@ -233,11 +234,26 @@ class GpgTest < Test::Unit::TestCase
233
234
  should 'preserve customer header values' do
234
235
  assert_equal 'custom value', @encrypted.header['X-Custom-Header'].to_s
235
236
  end
236
-
237
- should 'decrypt' do
238
- assert mail = Mail::Gpg.decrypt(@encrypted, { :password => 'abc' })
239
- assert mail == @mail
237
+
238
+ context 'when decrypted' do
239
+ setup do
240
+ @decrypted_mail = Mail::Gpg.decrypt(@encrypted, { :password => 'abc' })
241
+ end
242
+
243
+ should 'have same subject and body as the original' do
244
+ assert_equal @mail.subject, @decrypted_mail.subject
245
+ assert_equal @mail.body.to_s, @decrypted_mail.body.to_s
246
+ end
247
+
248
+ should 'preserve custom header from encrypted inner mail' do
249
+ assert_equal 'custom value', @decrypted_mail.header['X-Custom-Header'].to_s
250
+ end
251
+
252
+ should 'preserve custom header from outer mail' do
253
+ assert_equal 'another value', @decrypted_mail.header['X-Another-Header'].to_s
254
+ end
240
255
  end
256
+
241
257
  end
242
258
 
243
259
  context 'mail with multiple recipients' do
@@ -295,7 +311,7 @@ class GpgTest < Test::Unit::TestCase
295
311
  assert_match /encrypt me/, m.parts.first.body.to_s
296
312
  assert_match /Rakefile/, m.parts.last.content_disposition
297
313
  end
298
-
314
+
299
315
  should 'decrypt' do
300
316
  assert mail = Mail::Gpg.decrypt(@encrypted, { :password => 'abc' })
301
317
  assert mail == @mail
data/test/message_test.rb CHANGED
@@ -37,10 +37,10 @@ class MessageTest < Test::Unit::TestCase
37
37
  end
38
38
  end
39
39
 
40
- context "with gpg signing only" do
41
- setup do
42
- @mail.gpg sign: true, password: 'abc'
43
- end
40
+ context "with gpg signing only" do
41
+ setup do
42
+ @mail.gpg sign: true, password: 'abc'
43
+ end
44
44
 
45
45
  context "" do
46
46
  setup do
@@ -56,12 +56,12 @@ class MessageTest < Test::Unit::TestCase
56
56
  assert sign_part = m.parts.last
57
57
  assert m = Mail::Message.new(m.parts.last)
58
58
  assert !m.multipart?
59
- GPGME::Crypto.new.verify(sign_part.body.to_s, signed_text: @mail.encoded) do |sig|
60
- assert true == sig.valid?
61
- end
59
+ GPGME::Crypto.new.verify(sign_part.body.to_s, signed_text: @mail.encoded) do |sig|
60
+ assert true == sig.valid?
61
+ end
62
62
  end
63
63
  end
64
- end
64
+ end
65
65
 
66
66
  context "with gpg turned on" do
67
67
  setup do
@@ -111,7 +111,9 @@ class MessageTest < Test::Unit::TestCase
111
111
  assert m.multipart?
112
112
  assert m.encrypted?
113
113
  assert decrypted = m.decrypt(:password => 'abc')
114
+ assert_equal 'test', decrypted.subject
114
115
  assert decrypted == @mail
116
+ assert_equal 'i am unencrypted', decrypted.body.to_s
115
117
  end
116
118
 
117
119
  should "raise bad passphrase on decrypt" 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.0
4
+ version: 0.1.1
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: 2013-11-06 00:00:00.000000000 Z
12
+ date: 2013-11-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mail