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.
- data/History.txt +5 -0
- data/lib/mail/gpg.rb +12 -6
- data/lib/mail/gpg/signed_part.rb +37 -0
- data/lib/mail/gpg/version.rb +1 -1
- data/test/action_mailer_test.rb +6 -4
- data/test/gpg_test.rb +27 -8
- data/test/message_test.rb +10 -5
- metadata +3 -2
data/History.txt
CHANGED
data/lib/mail/gpg.rb
CHANGED
@@ -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/
|
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
|
-
|
50
|
-
add_part
|
51
|
-
add_part
|
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
|
-
|
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
|
-
|
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
|
data/lib/mail/gpg/version.rb
CHANGED
data/test/action_mailer_test.rb
CHANGED
@@ -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
|
-
|
73
|
-
|
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
|
-
|
119
|
-
|
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
|
data/test/gpg_test.rb
CHANGED
@@ -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
|
-
|
34
|
-
|
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
|
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.
|
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
|
162
|
-
|
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 /
|
183
|
+
assert_match /H1/, original_part.parts.last.body.to_s
|
165
184
|
end
|
166
185
|
end
|
167
186
|
end
|
data/test/message_test.rb
CHANGED
@@ -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
|
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
|
+
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-
|
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
|