schleuder 3.2.2 → 3.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +21 -11
- data/Rakefile +18 -10
- data/bin/schleuder +2 -1
- data/bin/schleuder-api-daemon +3 -2
- data/db/migrate/20180110203100_add_sig_enc_to_headers_to_meta_defaults.rb +30 -0
- data/db/migrate/20180723173900_add_deliver_selfsent_to_list.rb +11 -0
- data/db/migrate/20190906194820_add_autocrypt_header_to_list.rb +11 -0
- data/db/schema.rb +4 -2
- data/etc/list-defaults.yml +13 -3
- data/etc/schleuder.yml +11 -0
- data/lib/schleuder-api-daemon.rb +9 -354
- data/lib/schleuder-api-daemon/helpers/schleuder-api-daemon-helper.rb +143 -0
- data/lib/schleuder-api-daemon/routes/key.rb +40 -0
- data/lib/schleuder-api-daemon/routes/list.rb +69 -0
- data/lib/schleuder-api-daemon/routes/status.rb +5 -0
- data/lib/schleuder-api-daemon/routes/subscription.rb +99 -0
- data/lib/schleuder-api-daemon/routes/version.rb +5 -0
- data/lib/schleuder.rb +12 -3
- data/lib/schleuder/cli.rb +33 -3
- data/lib/schleuder/cli/subcommand_fix.rb +1 -1
- data/lib/schleuder/conf.rb +7 -1
- data/lib/schleuder/errors/active_model_error.rb +2 -5
- data/lib/schleuder/errors/decryption_failed.rb +2 -7
- data/lib/schleuder/errors/key_adduid_failed.rb +1 -5
- data/lib/schleuder/errors/key_generation_failed.rb +1 -8
- data/lib/schleuder/errors/keyword_admin_only.rb +1 -5
- data/lib/schleuder/errors/list_not_found.rb +1 -5
- data/lib/schleuder/errors/listdir_problem.rb +2 -7
- data/lib/schleuder/errors/loading_list_settings_failed.rb +2 -5
- data/lib/schleuder/errors/message_empty.rb +1 -5
- data/lib/schleuder/errors/message_not_from_admin.rb +2 -5
- data/lib/schleuder/errors/message_sender_not_subscribed.rb +2 -5
- data/lib/schleuder/errors/message_too_big.rb +2 -5
- data/lib/schleuder/errors/message_unauthenticated.rb +1 -4
- data/lib/schleuder/errors/message_unencrypted.rb +2 -5
- data/lib/schleuder/errors/message_unsigned.rb +2 -5
- data/lib/schleuder/errors/too_many_keys.rb +1 -8
- data/lib/schleuder/filters/{request_filter.rb → post_decryption/10_request.rb} +0 -0
- data/lib/schleuder/filters/{max_message_size.rb → post_decryption/20_max_message_size.rb} +0 -0
- data/lib/schleuder/filters/{forward_filter.rb → post_decryption/30_forward_to_owner.rb} +0 -0
- data/lib/schleuder/filters/post_decryption/40_receive_admin_only.rb +10 -0
- data/lib/schleuder/filters/post_decryption/50_receive_authenticated_only.rb +10 -0
- data/lib/schleuder/filters/post_decryption/60_receive_signed_only.rb +10 -0
- data/lib/schleuder/filters/post_decryption/70_receive_encrypted_only.rb +10 -0
- data/lib/schleuder/filters/post_decryption/80_receive_from_subscribed_emailaddresses_only.rb +10 -0
- data/lib/schleuder/filters/post_decryption/90_strip_html_from_alternative_if_keywords_present.rb +21 -0
- data/lib/schleuder/filters/{bounces_filter.rb → pre_decryption/10_forward_bounce_to_admins.rb} +0 -0
- data/lib/schleuder/filters/{forward_incoming.rb → pre_decryption/20_forward_all_incoming_to_admins.rb} +0 -0
- data/lib/schleuder/filters/{send_key_filter.rb → pre_decryption/30_send_key.rb} +0 -0
- data/lib/schleuder/filters/{hotmail_message_filter.rb → pre_decryption/40_fix_exchange_messages.rb} +5 -3
- data/lib/schleuder/filters/{strip_alternative_filter.rb → pre_decryption/50_strip_html_from_alternative.rb} +1 -1
- data/lib/schleuder/filters_runner.rb +41 -31
- data/lib/schleuder/gpgme/ctx.rb +24 -3
- data/lib/schleuder/gpgme/import_status.rb +13 -7
- data/lib/schleuder/gpgme/key.rb +8 -0
- data/lib/schleuder/list.rb +26 -4
- data/lib/schleuder/logger_notifications.rb +8 -1
- data/lib/schleuder/mail/encrypted_part.rb +14 -0
- data/lib/schleuder/mail/gpg.rb +15 -0
- data/lib/schleuder/mail/message.rb +97 -49
- data/lib/schleuder/plugins/attach_listkey.rb +6 -10
- data/lib/schleuder/plugins/key_management.rb +34 -26
- data/lib/schleuder/plugins/resend.rb +14 -11
- data/lib/schleuder/plugins/subscription_management.rb +70 -3
- data/lib/schleuder/runner.rb +49 -10
- data/lib/schleuder/subscription.rb +5 -9
- data/lib/schleuder/validators/fingerprint_validator.rb +1 -1
- data/lib/schleuder/version.rb +1 -1
- data/locales/de.yml +101 -9
- data/locales/en.yml +107 -11
- metadata +72 -34
- data/lib/schleuder/errors/file_not_found.rb +0 -14
- data/lib/schleuder/errors/invalid_listname.rb +0 -13
- data/lib/schleuder/errors/list_exists.rb +0 -13
- data/lib/schleuder/errors/unknown_list_option.rb +0 -14
- data/lib/schleuder/filters/auth_filter.rb +0 -39
@@ -1,16 +1,12 @@
|
|
1
1
|
module Schleuder
|
2
2
|
module ListPlugins
|
3
3
|
def self.attach_listkey(arguments, list, mail)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
})
|
11
|
-
mail.attachments[filename].content_type = 'application/pgp-keys'
|
12
|
-
mail.attachments[filename].content_description = "OpenPGP public key of #{list.email}"
|
13
|
-
mail.attachments[filename].content_disposition = "attachment; filename=#{filename}"
|
4
|
+
new_part = Mail::Part.new
|
5
|
+
new_part.body = list.export_key
|
6
|
+
new_part.content_type = 'application/pgp-keys'
|
7
|
+
new_part.content_description = "OpenPGP public key of #{list.email}"
|
8
|
+
new_part.content_disposition = "attachment; filename=#{list.fingerprint}.pgpkey"
|
9
|
+
mail.add_part new_part
|
14
10
|
nil
|
15
11
|
end
|
16
12
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Schleuder
|
2
2
|
module RequestPlugins
|
3
3
|
def self.add_key(arguments, list, mail)
|
4
|
-
out = [I18n.t('plugins.key_management.import_result')]
|
5
4
|
|
6
5
|
if mail.has_attachments?
|
7
6
|
results = self.import_keys_from_attachments(list, mail)
|
@@ -9,15 +8,35 @@ module Schleuder
|
|
9
8
|
results = [self.import_key_from_body(list, mail)]
|
10
9
|
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
import_stati = results.compact.collect(&:imports).flatten
|
12
|
+
|
13
|
+
if import_stati.blank?
|
14
|
+
return I18n.t('plugins.key_management.no_imports')
|
15
|
+
end
|
16
|
+
|
17
|
+
out = []
|
18
|
+
|
19
|
+
import_stati.each do |import_status|
|
20
|
+
if import_status.action == 'error'
|
21
|
+
out << I18n.t("plugins.key_management.key_import_status.error", fingerprint: import_status.fingerprint)
|
22
|
+
else
|
23
|
+
key = list.gpg.find_distinct_key(import_status.fingerprint)
|
24
|
+
if key
|
25
|
+
out << I18n.t("plugins.key_management.key_import_status.#{import_status.action}", key_oneline: key.oneline)
|
26
|
+
end
|
27
|
+
end
|
15
28
|
end
|
16
29
|
|
17
|
-
out.join("\n")
|
30
|
+
out.join("\n\n")
|
18
31
|
end
|
19
32
|
|
20
33
|
def self.delete_key(arguments, list, mail)
|
34
|
+
if arguments.blank?
|
35
|
+
return I18n.t(
|
36
|
+
"plugins.key_management.delete_key_requires_arguments"
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
21
40
|
arguments.map do |argument|
|
22
41
|
keys = list.keys(argument)
|
23
42
|
case keys.size
|
@@ -26,9 +45,9 @@ module Schleuder
|
|
26
45
|
when 1
|
27
46
|
begin
|
28
47
|
keys.first.delete!
|
29
|
-
I18n.t('plugins.key_management.deleted', key_string: keys.first.
|
48
|
+
I18n.t('plugins.key_management.deleted', key_string: keys.first.oneline)
|
30
49
|
rescue GPGME::Error::Conflict
|
31
|
-
I18n.t('plugins.key_management.not_deletable', key_string: keys.first.
|
50
|
+
I18n.t('plugins.key_management.not_deletable', key_string: keys.first.oneline)
|
32
51
|
end
|
33
52
|
else
|
34
53
|
I18n.t('errors.too_many_matching_keys', {
|
@@ -71,6 +90,12 @@ module Schleuder
|
|
71
90
|
end
|
72
91
|
|
73
92
|
def self.fetch_key(arguments, list, mail)
|
93
|
+
if arguments.blank?
|
94
|
+
return I18n.t(
|
95
|
+
"plugins.key_management.fetch_key_requires_arguments"
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
74
99
|
arguments.map do |argument|
|
75
100
|
list.fetch_keys(argument)
|
76
101
|
end
|
@@ -79,35 +104,18 @@ module Schleuder
|
|
79
104
|
# helper methods
|
80
105
|
private
|
81
106
|
|
82
|
-
def self.is_armored_key?(material)
|
83
|
-
return false unless /^-----BEGIN PGP PUBLIC KEY BLOCK-----$/ =~ material
|
84
|
-
return false unless /^-----END PGP PUBLIC KEY BLOCK-----$/ =~ material
|
85
|
-
|
86
|
-
lines = material.split("\n").reject(&:empty?)
|
87
|
-
# remove header
|
88
|
-
lines.shift
|
89
|
-
# remove tail
|
90
|
-
lines.pop
|
91
|
-
# verify the rest
|
92
|
-
# TODO: verify length except for lasts lines?
|
93
|
-
# headers according to https://tools.ietf.org/html/rfc4880#section-6.2
|
94
|
-
lines.map do |line|
|
95
|
-
/\A((comment|version|messageid|hash|charset):.*|[0-9a-z\/=+]+)\Z/i =~ line
|
96
|
-
end.all?
|
97
|
-
end
|
98
|
-
|
99
107
|
def self.import_keys_from_attachments(list, mail)
|
100
108
|
mail.attachments.map do |attachment|
|
101
109
|
material = attachment.body.to_s
|
102
110
|
|
103
|
-
list.import_key(material)
|
111
|
+
list.import_key(material)
|
104
112
|
end
|
105
113
|
end
|
106
114
|
|
107
115
|
def self.import_key_from_body(list, mail)
|
108
116
|
key_material = mail.first_plaintext_part.body.to_s
|
109
117
|
|
110
|
-
list.import_key(key_material)
|
118
|
+
list.import_key(key_material)
|
111
119
|
end
|
112
120
|
end
|
113
121
|
end
|
@@ -56,6 +56,9 @@ module Schleuder
|
|
56
56
|
|
57
57
|
# Only continue if all recipients are still here.
|
58
58
|
if recip_map.size < arguments.size
|
59
|
+
recip_map.keys.each do |aborted_sender|
|
60
|
+
mail.add_pseudoheader(:error, I18n.t("plugins.resend.aborted", email: aborted_sender))
|
61
|
+
end
|
59
62
|
return
|
60
63
|
end
|
61
64
|
|
@@ -117,22 +120,22 @@ module Schleuder
|
|
117
120
|
Array(recipients).inject({}) do |hash, email|
|
118
121
|
keys = mail.list.keys(email)
|
119
122
|
# Exclude unusable keys.
|
120
|
-
keys.select
|
121
|
-
case
|
123
|
+
usable_keys = keys.select { |key| key.usable_for?(:encrypt) }
|
124
|
+
case usable_keys.size
|
122
125
|
when 1
|
123
|
-
hash[email] =
|
126
|
+
hash[email] = usable_keys.first
|
124
127
|
when 0
|
125
128
|
if encrypted_only
|
126
129
|
# Don't add the email to the result to exclude it from the
|
127
130
|
# recipients.
|
128
|
-
|
131
|
+
add_resend_msg(mail, email, :error, 'not_resent_no_keys', usable_keys.size, keys.size)
|
129
132
|
else
|
130
133
|
hash[email] = ''
|
131
134
|
end
|
132
135
|
else
|
133
136
|
# Always report this situation, regardless of sending or not. It's
|
134
137
|
# bad and should be fixed.
|
135
|
-
|
138
|
+
add_resend_msg(mail, email, :notice, 'not_resent_encrypted_no_keys', usable_keys.size, keys.size)
|
136
139
|
if ! encrypted_only
|
137
140
|
hash[email] = ''
|
138
141
|
end
|
@@ -152,8 +155,8 @@ module Schleuder
|
|
152
155
|
gpg_opts
|
153
156
|
end
|
154
157
|
|
155
|
-
def self.
|
156
|
-
mail.add_pseudoheader(
|
158
|
+
def self.add_resend_msg(mail, email, severity, msg, usable_keys_size, all_keys_size)
|
159
|
+
mail.add_pseudoheader(severity, I18n.t("plugins.resend.#{msg}", email: email, usable_keys: usable_keys_size, all_keys: all_keys_size))
|
157
160
|
end
|
158
161
|
|
159
162
|
def self.add_error_header(mail, recipients_map)
|
@@ -163,15 +166,15 @@ module Schleuder
|
|
163
166
|
def self.add_resent_headers(mail, recipients_map, to_or_cc, sent_encrypted)
|
164
167
|
if sent_encrypted
|
165
168
|
prefix = I18n.t('plugins.resend.encrypted_to')
|
166
|
-
str = recipients_map.map do |email, key|
|
169
|
+
str = "\n" + recipients_map.map do |email, key|
|
167
170
|
"#{email} (#{key.fingerprint})"
|
168
|
-
end.join(
|
171
|
+
end.join(",\n")
|
169
172
|
else
|
170
173
|
prefix = I18n.t('plugins.resend.unencrypted_to')
|
171
|
-
str = recipients_map.keys.join(
|
174
|
+
str = ' ' + recipients_map.keys.join(", ")
|
172
175
|
end
|
173
176
|
headername = resent_header_name(to_or_cc)
|
174
|
-
mail.add_pseudoheader(headername, "#{prefix}
|
177
|
+
mail.add_pseudoheader(headername, "#{prefix}#{str}")
|
175
178
|
end
|
176
179
|
|
177
180
|
def self.resent_header_name(to_or_cc)
|
@@ -1,12 +1,18 @@
|
|
1
1
|
module Schleuder
|
2
2
|
module RequestPlugins
|
3
3
|
def self.subscribe(arguments, list, mail)
|
4
|
+
if arguments.blank?
|
5
|
+
return I18n.t(
|
6
|
+
"plugins.subscription_management.subscribe_requires_arguments"
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
4
10
|
email = arguments.shift
|
5
11
|
|
6
12
|
if arguments.present?
|
7
13
|
# Collect all arguments that look like fingerprint-material
|
8
14
|
fingerprint = ''
|
9
|
-
while arguments.first.present? && arguments.first.match(
|
15
|
+
while arguments.first.present? && arguments.first.match(/^(0x)?[a-f0-9]+$/i)
|
10
16
|
fingerprint << arguments.shift
|
11
17
|
end
|
12
18
|
# Use possibly remaining args as flags.
|
@@ -37,6 +43,13 @@ module Schleuder
|
|
37
43
|
# If no address was given we unsubscribe the sender.
|
38
44
|
email = arguments.first.presence || mail.signer.email
|
39
45
|
|
46
|
+
# Refuse to unsubscribe the last admin.
|
47
|
+
if list.admins.size == 1 && list.admins.first.email == email
|
48
|
+
return I18n.t(
|
49
|
+
"plugins.subscription_management.cannot_unsubscribe_last_admin", email: email
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
40
53
|
# TODO: May signers have multiple UIDs? We don't match those currently.
|
41
54
|
if ! list.from_admin?(mail) && email != mail.signer.email
|
42
55
|
# Only admins may unsubscribe others.
|
@@ -98,6 +111,12 @@ module Schleuder
|
|
98
111
|
end
|
99
112
|
|
100
113
|
def self.set_fingerprint(arguments, list, mail)
|
114
|
+
if arguments.blank?
|
115
|
+
return I18n.t(
|
116
|
+
"plugins.subscription_management.set_fingerprint_requires_arguments"
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
101
120
|
if arguments.first.match(/@/)
|
102
121
|
if arguments.first == mail.signer.email || list.from_admin?(mail)
|
103
122
|
email = arguments.shift
|
@@ -118,8 +137,15 @@ module Schleuder
|
|
118
137
|
)
|
119
138
|
end
|
120
139
|
|
121
|
-
|
140
|
+
fingerprint = arguments.join
|
141
|
+
unless GPGME::Key.valid_fingerprint?(fingerprint)
|
142
|
+
return I18n.t(
|
143
|
+
"plugins.subscription_management.set_fingerprint_requires_valid_fingerprint",
|
144
|
+
fingerprint: fingerprint
|
145
|
+
)
|
146
|
+
end
|
122
147
|
|
148
|
+
sub.fingerprint = fingerprint
|
123
149
|
if sub.save
|
124
150
|
I18n.t(
|
125
151
|
"plugins.subscription_management.fingerprint_set",
|
@@ -130,7 +156,48 @@ module Schleuder
|
|
130
156
|
I18n.t(
|
131
157
|
"plugins.subscription_management.setting_fingerprint_failed",
|
132
158
|
email: email,
|
133
|
-
fingerprint:
|
159
|
+
fingerprint: sub.fingerprint,
|
160
|
+
errors: sub.errors.to_a.join("\n")
|
161
|
+
)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def self.unset_fingerprint(arguments, list, mail)
|
166
|
+
if arguments.blank?
|
167
|
+
return I18n.t(
|
168
|
+
"plugins.subscription_management.unset_fingerprint_requires_arguments"
|
169
|
+
)
|
170
|
+
end
|
171
|
+
|
172
|
+
email = arguments.first
|
173
|
+
unless email == mail.signer.email || list.from_admin?(mail)
|
174
|
+
return I18n.t(
|
175
|
+
"plugins.subscription_management.unset_fingerprint_only_self"
|
176
|
+
)
|
177
|
+
end
|
178
|
+
if email == mail.signer.email && list.from_admin?(mail) && arguments.last != 'force'
|
179
|
+
return I18n.t(
|
180
|
+
"plugins.subscription_management.unset_fingerprint_requires_arguments"
|
181
|
+
)
|
182
|
+
end
|
183
|
+
|
184
|
+
sub = list.subscriptions.where(email: email).first
|
185
|
+
if sub.blank?
|
186
|
+
return I18n.t(
|
187
|
+
"plugins.subscription_management.is_not_subscribed", email: email
|
188
|
+
)
|
189
|
+
end
|
190
|
+
|
191
|
+
sub.fingerprint = ''
|
192
|
+
if sub.save
|
193
|
+
I18n.t(
|
194
|
+
"plugins.subscription_management.fingerprint_unset",
|
195
|
+
email: email
|
196
|
+
)
|
197
|
+
else
|
198
|
+
I18n.t(
|
199
|
+
"plugins.subscription_management.unsetting_fingerprint_failed",
|
200
|
+
email: email,
|
134
201
|
errors: sub.errors.to_a.join("\n")
|
135
202
|
)
|
136
203
|
end
|
data/lib/schleuder/runner.rb
CHANGED
@@ -5,20 +5,48 @@ module Schleuder
|
|
5
5
|
return error if error
|
6
6
|
|
7
7
|
logger.info "Parsing incoming email."
|
8
|
+
|
9
|
+
# is it valid utf-8?
|
10
|
+
msg_scrubbed = false
|
11
|
+
unless msg.valid_encoding?
|
12
|
+
logger.warn "Converting message due to invalid characters"
|
13
|
+
detection = CharlockHolmes::EncodingDetector.detect(msg)
|
14
|
+
begin
|
15
|
+
msg = CharlockHolmes::Converter.convert(msg, detection[:encoding], 'UTF-8')
|
16
|
+
rescue ArgumentError
|
17
|
+
# it looks like even icu wasn't able to convert
|
18
|
+
# so we scrub the invalid characters to be able to
|
19
|
+
# at least parse the message somehow. Though this might
|
20
|
+
# result in data loss.
|
21
|
+
logger.warn "Scrubbing message due to invalid characters"
|
22
|
+
msg = msg.scrub
|
23
|
+
msg_scrubbed = true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
8
27
|
@mail = Mail.create_message_to_list(msg, recipient, list)
|
9
28
|
|
10
|
-
|
29
|
+
if msg_scrubbed
|
30
|
+
@mail.add_pseudoheader(:note, I18n.t("pseudoheaders.scrubbed_message"))
|
31
|
+
end
|
32
|
+
|
33
|
+
error = run_filters('pre')
|
11
34
|
return error if error
|
12
35
|
|
13
36
|
begin
|
14
37
|
# This decrypts, verifies, etc.
|
15
38
|
@mail = @mail.setup
|
16
|
-
|
39
|
+
|
40
|
+
rescue GPGME::Error::BadPassphrase,
|
41
|
+
GPGME::Error::DecryptFailed,
|
42
|
+
GPGME::Error::NoData,
|
43
|
+
GPGME::Error::NoSecretKey
|
44
|
+
|
17
45
|
logger.warn "Decryption of incoming message failed."
|
18
46
|
return Errors::DecryptionFailed.new(list)
|
19
47
|
end
|
20
48
|
|
21
|
-
error = run_filters(
|
49
|
+
error = run_filters('post')
|
22
50
|
return error if error
|
23
51
|
|
24
52
|
if ! @mail.was_validly_signed?
|
@@ -45,8 +73,8 @@ module Schleuder
|
|
45
73
|
|
46
74
|
# Subscriptions
|
47
75
|
logger.debug "Creating clean copy of message"
|
48
|
-
copy = @mail.clean_copy(
|
49
|
-
list.send_to_subscriptions(copy)
|
76
|
+
copy = @mail.clean_copy(list.headers_to_meta.any?)
|
77
|
+
list.send_to_subscriptions(copy, @mail)
|
50
78
|
nil
|
51
79
|
end
|
52
80
|
|
@@ -56,8 +84,8 @@ module Schleuder
|
|
56
84
|
@list
|
57
85
|
end
|
58
86
|
|
59
|
-
def run_filters(
|
60
|
-
error = filters_runner.run(@mail
|
87
|
+
def run_filters(filter_type)
|
88
|
+
error = filters_runner(filter_type).run(@mail)
|
61
89
|
if error
|
62
90
|
if list.bounces_notify_admins?
|
63
91
|
text = "#{I18n.t('.bounces_notify_admins')}\n\n#{error}"
|
@@ -68,8 +96,19 @@ module Schleuder
|
|
68
96
|
end
|
69
97
|
end
|
70
98
|
|
71
|
-
def filters_runner
|
72
|
-
|
99
|
+
def filters_runner(filter_type)
|
100
|
+
if filter_type == 'pre'
|
101
|
+
filters_runner_pre_decryption
|
102
|
+
else
|
103
|
+
filters_runner_post_decryption
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def filters_runner_pre_decryption
|
108
|
+
@filters_runner_pre_decryption ||= Filters::Runner.new(list,'pre')
|
109
|
+
end
|
110
|
+
def filters_runner_post_decryption
|
111
|
+
@filters_runner_post_decryption ||= Filters::Runner.new(list,'post')
|
73
112
|
end
|
74
113
|
|
75
114
|
def logger
|
@@ -94,7 +133,7 @@ module Schleuder
|
|
94
133
|
return log_and_return(Errors::ListNotFound.new(recipient), true)
|
95
134
|
end
|
96
135
|
|
97
|
-
# Check
|
136
|
+
# Check necessary permissions of crucial files.
|
98
137
|
if ! File.exist?(@list.listdir)
|
99
138
|
return log_and_return(Errors::ListdirProblem.new(@list.listdir, :not_existing))
|
100
139
|
elsif ! File.directory?(@list.listdir)
|
@@ -23,10 +23,11 @@ module Schleuder
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def fingerprint=(arg)
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
29
|
-
|
26
|
+
# Always assign the given value, because it must be possible to overwrite
|
27
|
+
# the previous fingerprint with an empty value. That value should better
|
28
|
+
# be nil instead of a blank string, but currently schleuder-cli (v0.1.0) expects
|
29
|
+
# only strings.
|
30
|
+
write_attribute(:fingerprint, arg.to_s.gsub(/\s*/, '').gsub(/^0x/, '').chomp.upcase)
|
30
31
|
end
|
31
32
|
|
32
33
|
def key
|
@@ -39,11 +40,6 @@ module Schleuder
|
|
39
40
|
def send_mail(mail)
|
40
41
|
list.logger.debug "Preparing sending to #{self.inspect}"
|
41
42
|
|
42
|
-
if ! self.delivery_enabled
|
43
|
-
list.logger.info "Not sending to #{self.email}: delivery is disabled."
|
44
|
-
return false
|
45
|
-
end
|
46
|
-
|
47
43
|
mail = ensure_headers(mail)
|
48
44
|
gpg_opts = self.list.gpg_sign_options
|
49
45
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class FingerprintValidator < ActiveModel::EachValidator
|
2
2
|
def validate_each(record, attribute, value)
|
3
|
-
unless value
|
3
|
+
unless GPGME::Key.valid_fingerprint?(value)
|
4
4
|
record.errors[attribute] << (options[:message] || I18n.t("errors.invalid_fingerprint"))
|
5
5
|
end
|
6
6
|
end
|