schleuder 2.2.4 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +138 -0
- data/Rakefile +136 -0
- data/bin/pinentry-clearpassphrase +72 -0
- data/bin/schleuder +9 -89
- data/bin/schleuder-api-daemon +4 -0
- data/db/migrate/20140501103532_create_lists.rb +39 -0
- data/db/migrate/20140501112859_create_subscriptions.rb +21 -0
- data/db/migrate/201508092100_add_language_to_lists.rb +11 -0
- data/db/migrate/20150812165700_change_keywords_admin_only_defaults.rb +8 -0
- data/db/migrate/20150813235800_add_forward_all_incoming_to_admins.rb +11 -0
- data/db/migrate/201508141727_change_send_encrypted_only_default.rb +8 -0
- data/db/migrate/201508222143_add_logfiles_to_keep_to_lists.rb +11 -0
- data/db/migrate/201508261723_rename_delivery_disabled_to_delivery_enabled_and_change_default.rb +14 -0
- data/db/migrate/201508261815_strip_gpg_passphrase.rb +11 -0
- data/db/migrate/201508261827_remove_default_mime.rb +9 -0
- data/db/migrate/20160501172700_fix_headers_to_meta_defaults.rb +8 -0
- data/db/migrate/20170713215059_add_internal_footer_to_list.rb +11 -0
- data/db/schema.rb +62 -0
- data/etc/init.d/schleuder-api-daemon +87 -0
- data/etc/list-defaults.yml +123 -0
- data/etc/postfix/schleuder_sqlite.cf +28 -0
- data/etc/schleuder-api-daemon.service +10 -0
- data/etc/schleuder.cron.weekly +6 -0
- data/etc/schleuder.yml +61 -0
- data/lib/schleuder-api-daemon.rb +420 -0
- data/lib/schleuder.rb +81 -47
- data/lib/schleuder/cli.rb +334 -0
- data/lib/schleuder/cli/cert.rb +24 -0
- data/lib/schleuder/cli/schleuder_cert_manager.rb +84 -0
- data/lib/schleuder/cli/subcommand_fix.rb +11 -0
- data/lib/schleuder/conf.rb +131 -0
- data/lib/schleuder/errors/active_model_error.rb +15 -0
- data/lib/schleuder/errors/base.rb +17 -0
- data/lib/schleuder/errors/decryption_failed.rb +16 -0
- data/lib/schleuder/errors/fatal_error.rb +13 -0
- data/lib/schleuder/errors/file_not_found.rb +14 -0
- data/lib/schleuder/errors/invalid_listname.rb +13 -0
- data/lib/schleuder/errors/key_adduid_failed.rb +13 -0
- data/lib/schleuder/errors/key_generation_failed.rb +16 -0
- data/lib/schleuder/errors/keyword_admin_only.rb +13 -0
- data/lib/schleuder/errors/list_exists.rb +13 -0
- data/lib/schleuder/errors/list_not_found.rb +14 -0
- data/lib/schleuder/errors/list_property_missing.rb +14 -0
- data/lib/schleuder/errors/listdir_problem.rb +16 -0
- data/lib/schleuder/errors/loading_list_settings_failed.rb +14 -0
- data/lib/schleuder/errors/message_empty.rb +14 -0
- data/lib/schleuder/errors/message_not_from_admin.rb +13 -0
- data/lib/schleuder/errors/message_sender_not_subscribed.rb +13 -0
- data/lib/schleuder/errors/message_too_big.rb +14 -0
- data/lib/schleuder/errors/message_unauthenticated.rb +13 -0
- data/lib/schleuder/errors/message_unencrypted.rb +13 -0
- data/lib/schleuder/errors/message_unsigned.rb +13 -0
- data/lib/schleuder/errors/standard_error.rb +5 -0
- data/lib/schleuder/errors/too_many_keys.rb +17 -0
- data/lib/schleuder/errors/unknown_list_option.rb +14 -0
- data/lib/schleuder/filters/auth_filter.rb +39 -0
- data/lib/schleuder/filters/bounces_filter.rb +12 -0
- data/lib/schleuder/filters/forward_filter.rb +17 -0
- data/lib/schleuder/filters/forward_incoming.rb +13 -0
- data/lib/schleuder/filters/hotmail_message_filter.rb +25 -0
- data/lib/schleuder/filters/max_message_size.rb +14 -0
- data/lib/schleuder/filters/request_filter.rb +26 -0
- data/lib/schleuder/filters/send_key_filter.rb +20 -0
- data/lib/schleuder/filters/strip_alternative_filter.rb +21 -0
- data/lib/schleuder/filters_runner.rb +83 -0
- data/lib/schleuder/gpgme/ctx.rb +274 -0
- data/lib/schleuder/gpgme/import_status.rb +27 -0
- data/lib/schleuder/gpgme/key.rb +212 -0
- data/lib/schleuder/gpgme/sub_key.rb +13 -0
- data/lib/schleuder/gpgme/user_id.rb +22 -0
- data/lib/schleuder/list.rb +318 -127
- data/lib/schleuder/list_builder.rb +139 -0
- data/lib/schleuder/listlogger.rb +31 -0
- data/lib/schleuder/logger.rb +23 -0
- data/lib/schleuder/logger_notifications.rb +69 -0
- data/lib/schleuder/mail/message.rb +482 -0
- data/lib/schleuder/mail/parts_list.rb +9 -0
- data/lib/schleuder/plugin_runners/base.rb +91 -0
- data/lib/schleuder/plugin_runners/list_plugins_runner.rb +24 -0
- data/lib/schleuder/plugin_runners/request_plugins_runner.rb +27 -0
- data/lib/schleuder/plugins/attach_listkey.rb +17 -0
- data/lib/schleuder/plugins/get_version.rb +7 -0
- data/lib/schleuder/plugins/key_management.rb +113 -0
- data/lib/schleuder/plugins/list_management.rb +15 -0
- data/lib/schleuder/plugins/resend.rb +196 -0
- data/lib/schleuder/plugins/sign_this.rb +46 -0
- data/lib/schleuder/plugins/subscription_management.rb +140 -0
- data/lib/schleuder/runner.rb +130 -0
- data/lib/schleuder/subscription.rb +98 -0
- data/lib/schleuder/validators/boolean_validator.rb +7 -0
- data/lib/schleuder/validators/email_validator.rb +7 -0
- data/lib/schleuder/validators/fingerprint_validator.rb +7 -0
- data/lib/schleuder/validators/greater_than_zero_validator.rb +7 -0
- data/lib/schleuder/validators/no_line_breaks_validator.rb +7 -0
- data/lib/schleuder/version.rb +1 -1
- data/locales/de.yml +179 -0
- data/locales/en.yml +179 -0
- metadata +305 -108
- checksums.yaml.gz.sig +0 -3
- data.tar.gz.sig +0 -2
- data/LICENSE +0 -339
- data/README +0 -32
- data/bin/schleuder-fix-gem-dependencies +0 -37
- data/bin/schleuder-init-setup +0 -37
- data/bin/schleuder-migrate-v2.1-to-v2.2 +0 -225
- data/bin/schleuder-newlist +0 -413
- data/contrib/check-expired-keys.rb +0 -60
- data/contrib/mutt-schleuder-colors.rc +0 -10
- data/contrib/mutt-schleuder-resend.vim +0 -24
- data/contrib/smtpserver.rb +0 -76
- data/ext/default-list.conf +0 -149
- data/ext/default-members.conf +0 -7
- data/ext/list.conf.example +0 -14
- data/ext/schleuder.conf +0 -64
- data/lib/schleuder/archiver.rb +0 -46
- data/lib/schleuder/crypt.rb +0 -210
- data/lib/schleuder/errors.rb +0 -5
- data/lib/schleuder/list_config.rb +0 -146
- data/lib/schleuder/log/listlogger.rb +0 -57
- data/lib/schleuder/log/outputter/emailoutputter.rb +0 -120
- data/lib/schleuder/log/outputter/metaemailoutputter.rb +0 -50
- data/lib/schleuder/log/schleuderlogger.rb +0 -34
- data/lib/schleuder/mail.rb +0 -873
- data/lib/schleuder/mailer.rb +0 -26
- data/lib/schleuder/member.rb +0 -69
- data/lib/schleuder/plugin.rb +0 -54
- data/lib/schleuder/processor.rb +0 -363
- data/lib/schleuder/schleuder_config.rb +0 -75
- data/lib/schleuder/storage.rb +0 -84
- data/lib/schleuder/utils.rb +0 -80
- data/man/schleuder-newlist.8 +0 -174
- data/man/schleuder.8 +0 -416
- data/plugins/README +0 -20
- data/plugins/manage_keys_plugin.rb +0 -113
- data/plugins/manage_members_plugin.rb +0 -156
- data/plugins/manage_self_plugin.rb +0 -26
- data/plugins/resend_plugin.rb +0 -35
- data/plugins/sign_this_plugin.rb +0 -14
- data/plugins/version_plugin.rb +0 -12
- metadata.gz.sig +0 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
module Schleuder
|
2
|
+
module RequestPlugins
|
3
|
+
def self.sign_this(arguments, list, mail)
|
4
|
+
if mail.has_attachments?
|
5
|
+
list.logger.debug "Signing each attachment's body"
|
6
|
+
intro = I18n.t('plugins.signatures_attached')
|
7
|
+
parts = mail.attachments.map do |attachment|
|
8
|
+
make_signature_part(attachment, list)
|
9
|
+
end
|
10
|
+
[intro, parts].flatten
|
11
|
+
else
|
12
|
+
list.logger.debug "Clear-signing first available text/plain part"
|
13
|
+
clearsign(mail.first_plaintext_part)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# helper methods
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.make_signature_part(attachment, list)
|
21
|
+
material = attachment.body.to_s
|
22
|
+
return nil if material.strip.blank?
|
23
|
+
file_basename = attachment.filename.presence || Digest::SHA256.hexdigest(material)
|
24
|
+
list.logger.debug "Signing #{file_basename}"
|
25
|
+
filename = "#{file_basename}.sig"
|
26
|
+
part = Mail::Part.new
|
27
|
+
part.body = detachsign(material)
|
28
|
+
part.content_type = 'application/pgp-signature'
|
29
|
+
part.content_disposition = "attachment; filename=#{filename}"
|
30
|
+
part.content_description = "OpenPGP signature for '#{file_basename}'"
|
31
|
+
part
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.detachsign(thing)
|
35
|
+
crypto.sign(thing, mode: GPGME::SIG_MODE_DETACH).to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.clearsign(mail)
|
39
|
+
crypto.clearsign(mail.body.to_s).to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.crypto
|
43
|
+
@crypto ||= GPGME::Crypto.new(armor: true)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Schleuder
|
2
|
+
module RequestPlugins
|
3
|
+
def self.subscribe(arguments, list, mail)
|
4
|
+
email = arguments.shift
|
5
|
+
|
6
|
+
if arguments.present?
|
7
|
+
# Collect all arguments that look like fingerprint-material
|
8
|
+
fingerprint = ''
|
9
|
+
while arguments.first.present? && arguments.first.match(/\A(0x)?[a-f0-9]+/i)
|
10
|
+
fingerprint << arguments.shift
|
11
|
+
end
|
12
|
+
# Use possibly remaining args as flags.
|
13
|
+
adminflag = arguments.shift
|
14
|
+
deliveryflag = arguments.shift
|
15
|
+
end
|
16
|
+
|
17
|
+
sub, _ = list.subscribe(email, fingerprint, adminflag, deliveryflag)
|
18
|
+
|
19
|
+
if sub.persisted?
|
20
|
+
I18n.t(
|
21
|
+
"plugins.subscription_management.subscribed",
|
22
|
+
email: sub.email,
|
23
|
+
fingerprint: sub.fingerprint,
|
24
|
+
admin: sub.admin,
|
25
|
+
delivery_enabled: sub.delivery_enabled
|
26
|
+
)
|
27
|
+
else
|
28
|
+
I18n.t(
|
29
|
+
"plugins.subscription_management.subscribing_failed",
|
30
|
+
email: sub.email,
|
31
|
+
errors: sub.errors.full_messages.join(".\n")
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.unsubscribe(arguments, list, mail)
|
37
|
+
# If no address was given we unsubscribe the sender.
|
38
|
+
email = arguments.first.presence || mail.signer.email
|
39
|
+
|
40
|
+
# TODO: May signers have multiple UIDs? We don't match those currently.
|
41
|
+
if ! list.from_admin?(mail) && email != mail.signer.email
|
42
|
+
# Only admins may unsubscribe others.
|
43
|
+
return I18n.t(
|
44
|
+
"plugins.subscription_management.forbidden", email: email
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
sub = list.subscriptions.where(email: email).first
|
49
|
+
|
50
|
+
if sub.blank?
|
51
|
+
return I18n.t(
|
52
|
+
"plugins.subscription_management.is_not_subscribed", email: email
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
if res = sub.delete
|
57
|
+
I18n.t(
|
58
|
+
"plugins.subscription_management.unsubscribed", email: email
|
59
|
+
)
|
60
|
+
else
|
61
|
+
I18n.t(
|
62
|
+
"plugins.subscription_management.unsubscribing_failed",
|
63
|
+
email: email,
|
64
|
+
error: res.errors.to_a
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.list_subscriptions(arguments, list, mail)
|
70
|
+
subs = if arguments.blank?
|
71
|
+
list.subscriptions.all.to_a
|
72
|
+
else
|
73
|
+
arguments.map do |argument|
|
74
|
+
list.subscriptions.where("email like ?", "%#{argument}%").to_a
|
75
|
+
end.flatten
|
76
|
+
end
|
77
|
+
|
78
|
+
if subs.blank?
|
79
|
+
return nil
|
80
|
+
end
|
81
|
+
|
82
|
+
out = [ I18n.t("plugins.subscription_management.list_of_subscriptions") ]
|
83
|
+
|
84
|
+
out << subs.map do |subscription|
|
85
|
+
# Fingerprints are at most 40 characters long, and lines shouldn't
|
86
|
+
# exceed 80 characters if possible.
|
87
|
+
s = subscription.email
|
88
|
+
if subscription.fingerprint.present?
|
89
|
+
s << "\t0x#{subscription.fingerprint}"
|
90
|
+
end
|
91
|
+
if ! subscription.delivery_enabled?
|
92
|
+
s << "\tDelivery disabled!"
|
93
|
+
end
|
94
|
+
s
|
95
|
+
end
|
96
|
+
|
97
|
+
out.join("\n")
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.set_fingerprint(arguments, list, mail)
|
101
|
+
if arguments.first.match(/@/)
|
102
|
+
if arguments.first == mail.signer.email || list.from_admin?(mail)
|
103
|
+
email = arguments.shift
|
104
|
+
else
|
105
|
+
return I18n.t(
|
106
|
+
"plugins.subscription_management.set_fingerprint_only_self"
|
107
|
+
)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
email = mail.signer.email
|
111
|
+
end
|
112
|
+
|
113
|
+
sub = list.subscriptions.where(email: email).first
|
114
|
+
|
115
|
+
if sub.blank?
|
116
|
+
return I18n.t(
|
117
|
+
"plugins.subscription_management.is_not_subscribed", email: email
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
sub.fingerprint = arguments.join
|
122
|
+
|
123
|
+
if sub.save
|
124
|
+
I18n.t(
|
125
|
+
"plugins.subscription_management.fingerprint_set",
|
126
|
+
email: email,
|
127
|
+
fingerprint: sub.fingerprint
|
128
|
+
)
|
129
|
+
else
|
130
|
+
I18n.t(
|
131
|
+
"plugins.subscription_management.setting_fingerprint_failed",
|
132
|
+
email: email,
|
133
|
+
fingerprint: arguments.last,
|
134
|
+
errors: sub.errors.to_a.join("\n")
|
135
|
+
)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Schleuder
|
2
|
+
class Runner
|
3
|
+
def run(msg, recipient)
|
4
|
+
error = setup_list(recipient)
|
5
|
+
return error if error
|
6
|
+
|
7
|
+
logger.info "Parsing incoming email."
|
8
|
+
@mail = Mail.create_message_to_list(msg, recipient, list)
|
9
|
+
|
10
|
+
error = run_filters(Filters::Runner::PRE_SETUP_FILTERS)
|
11
|
+
return error if error
|
12
|
+
|
13
|
+
begin
|
14
|
+
# This decrypts, verifies, etc.
|
15
|
+
@mail = @mail.setup
|
16
|
+
rescue GPGME::Error::DecryptFailed
|
17
|
+
logger.warn "Decryption of incoming message failed."
|
18
|
+
return Errors::DecryptionFailed.new(list)
|
19
|
+
end
|
20
|
+
|
21
|
+
error = run_filters(Filters::Runner::POST_SETUP_FILTERS)
|
22
|
+
return error if error
|
23
|
+
|
24
|
+
if ! @mail.was_validly_signed?
|
25
|
+
logger.debug "Message was not validly signed, adding subject_prefix_in"
|
26
|
+
@mail.add_subject_prefix_in!
|
27
|
+
end
|
28
|
+
|
29
|
+
if ! @mail.was_encrypted?
|
30
|
+
logger.debug "Message was not encrypted, skipping plugins"
|
31
|
+
elsif @mail.was_validly_signed?
|
32
|
+
# Plugins
|
33
|
+
logger.debug "Message was encrypted and validly signed"
|
34
|
+
PluginRunners::ListPluginsRunner.run(list, @mail).compact
|
35
|
+
end
|
36
|
+
|
37
|
+
# Don't send empty messages over the list.
|
38
|
+
if @mail.empty?
|
39
|
+
logger.info "Message found empty, not sending it to list."
|
40
|
+
return Errors::MessageEmpty.new(@list)
|
41
|
+
end
|
42
|
+
|
43
|
+
logger.debug "Adding subject_prefix"
|
44
|
+
@mail.add_subject_prefix!
|
45
|
+
|
46
|
+
# Subscriptions
|
47
|
+
logger.debug "Creating clean copy of message"
|
48
|
+
copy = @mail.clean_copy(true)
|
49
|
+
list.send_to_subscriptions(copy)
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def list
|
56
|
+
@list
|
57
|
+
end
|
58
|
+
|
59
|
+
def run_filters(filters)
|
60
|
+
error = filters_runner.run(@mail, filters)
|
61
|
+
if error
|
62
|
+
if list.bounces_notify_admins?
|
63
|
+
text = "#{I18n.t('.bounces_notify_admins')}\n\n#{error}"
|
64
|
+
# TODO: raw_source is mostly blank?
|
65
|
+
logger.notify_admin text, @mail.original_message, I18n.t('notice')
|
66
|
+
end
|
67
|
+
return error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def filters_runner
|
72
|
+
@filters_runner ||= Filters::Runner.new(list)
|
73
|
+
end
|
74
|
+
|
75
|
+
def logger
|
76
|
+
list.present? && list.logger || Schleuder.logger
|
77
|
+
end
|
78
|
+
|
79
|
+
def log_and_return(error, reveal_error=false)
|
80
|
+
Schleuder.logger.error(error)
|
81
|
+
if reveal_error
|
82
|
+
error
|
83
|
+
else
|
84
|
+
# Return an unrevealing error, the sender and all bystanders don't need to know these details.
|
85
|
+
Errors::FatalError.new
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def setup_list(recipient)
|
90
|
+
return @list if @list
|
91
|
+
|
92
|
+
logger.info "Loading list '#{recipient}'"
|
93
|
+
if ! @list = List.by_recipient(recipient)
|
94
|
+
return log_and_return(Errors::ListNotFound.new(recipient), true)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Check neccessary permissions of crucial files.
|
98
|
+
if ! File.exist?(@list.listdir)
|
99
|
+
return log_and_return(Errors::ListdirProblem.new(@list.listdir, :not_existing))
|
100
|
+
elsif ! File.directory?(@list.listdir)
|
101
|
+
return log_and_return(Errors::ListdirProblem.new(@list.listdir, :not_a_directory))
|
102
|
+
elsif ! File.readable?(@list.listdir)
|
103
|
+
return log_and_return(Errors::ListdirProblem.new(@list.listdir, :not_readable))
|
104
|
+
elsif ! File.writable?(@list.listdir)
|
105
|
+
return log_and_return(Errors::ListdirProblem.new(@list.listdir, :not_writable))
|
106
|
+
else
|
107
|
+
if File.exist?(@list.logfile) && ! File.writable?(@list.logfile)
|
108
|
+
return log_and_return(Errors::ListdirProblem.new(@list.logfile, :not_writable))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Check basic sanity of list.
|
113
|
+
%w[fingerprint key secret_key admins].each do |attrib|
|
114
|
+
if @list.send(attrib).blank?
|
115
|
+
return log_and_return(Errors::ListPropertyMissing.new(@list.listdir, attrib))
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Set locale
|
120
|
+
if I18n.available_locales.include?(@list.language.to_sym)
|
121
|
+
I18n.locale = @list.language.to_sym
|
122
|
+
end
|
123
|
+
|
124
|
+
# This cannot be put in List, as Mail wouldn't know it then.
|
125
|
+
logger.debug "Setting GNUPGHOME to #{@list.listdir}"
|
126
|
+
ENV['GNUPGHOME'] = @list.listdir
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Schleuder
|
2
|
+
class Subscription < ActiveRecord::Base
|
3
|
+
belongs_to :list
|
4
|
+
|
5
|
+
validates :list_id, inclusion: {
|
6
|
+
in: -> (id) { List.pluck(:id) },
|
7
|
+
message: "must refer to an existing list"
|
8
|
+
}
|
9
|
+
validates :email, presence: true, email: true, uniqueness: {scope: :list_id}
|
10
|
+
validates :fingerprint, allow_blank: true, fingerprint: true
|
11
|
+
validates :delivery_enabled, :admin, boolean: true
|
12
|
+
|
13
|
+
default_scope { order(:email) }
|
14
|
+
|
15
|
+
scope :without_fingerprint, -> { where(fingerprint: [nil,'']) }
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
email
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.configurable_attributes
|
22
|
+
[:fingerprint, :admin, :delivery_enabled]
|
23
|
+
end
|
24
|
+
|
25
|
+
def fingerprint=(arg)
|
26
|
+
# Allow input to contain whitespace and '0x'-prefix, but don't store it
|
27
|
+
# into the DB.
|
28
|
+
value = arg.to_s.gsub(/\s*/, '').gsub(/^0x/, '').chomp
|
29
|
+
write_attribute(:fingerprint, value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def key
|
33
|
+
# TODO: make key-related methods a concern, so we don't have to go
|
34
|
+
# through the list and neither re-implement the methods here.
|
35
|
+
# Prefix '0x' to force GnuPG to match only hex-values, not UIDs.
|
36
|
+
list.keys("0x#{self.fingerprint}").first
|
37
|
+
end
|
38
|
+
|
39
|
+
def send_mail(mail)
|
40
|
+
list.logger.debug "Preparing sending to #{self.inspect}"
|
41
|
+
|
42
|
+
if ! self.delivery_enabled
|
43
|
+
list.logger.info "Not sending to #{self.email}: delivery is disabled."
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
|
47
|
+
mail = ensure_headers(mail)
|
48
|
+
gpg_opts = self.list.gpg_sign_options
|
49
|
+
|
50
|
+
if self.key.blank?
|
51
|
+
if self.list.send_encrypted_only?
|
52
|
+
notify_of_missed_message(:absent)
|
53
|
+
return false
|
54
|
+
else
|
55
|
+
list.logger.warn "Sending plaintext because no key is present!"
|
56
|
+
end
|
57
|
+
elsif ! self.key.usable?
|
58
|
+
if self.list.send_encrypted_only?
|
59
|
+
notify_of_missed_message(key.usability_issue)
|
60
|
+
return false
|
61
|
+
else
|
62
|
+
list.logger.warn "Sending plaintext because assigned key is #{key.usability_issue}!"
|
63
|
+
end
|
64
|
+
else
|
65
|
+
gpg_opts.merge!(encrypt: true, keys: {self.email => "0x#{self.fingerprint}"})
|
66
|
+
end
|
67
|
+
|
68
|
+
list.logger.info "Sending message to #{self.email}"
|
69
|
+
mail.gpg gpg_opts
|
70
|
+
mail.deliver
|
71
|
+
end
|
72
|
+
|
73
|
+
def ensure_headers(mail)
|
74
|
+
mail.to = self.email
|
75
|
+
mail.from = self.list.email
|
76
|
+
mail.sender = self.list.bounce_address
|
77
|
+
mail
|
78
|
+
end
|
79
|
+
|
80
|
+
def notify_of_missed_message(reason)
|
81
|
+
self.list.logger.warn "Not sending to #{self.email}: key is unusable because it is #{reason} and sending plain text not allowed"
|
82
|
+
mail = ensure_headers(Mail.new)
|
83
|
+
mail.subject = I18n.t('notice')
|
84
|
+
mail.body = I18n.t("missed_message_due_to_unusable_key", list_email: self.list.email) + I18n.t('errors.signoff')
|
85
|
+
mail.gpg self.list.gpg_sign_options
|
86
|
+
mail.deliver
|
87
|
+
end
|
88
|
+
|
89
|
+
def admin?
|
90
|
+
self.admin == true
|
91
|
+
end
|
92
|
+
|
93
|
+
def delete_key
|
94
|
+
list.delete_key(self.fingerprint)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|