mail-gpg 0.1.0 → 0.1.1

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/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