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,13 @@
|
|
1
|
+
module GPGME
|
2
|
+
class SubKey
|
3
|
+
# Overwrite to specify the full fingerprint instead of the short key-ID.
|
4
|
+
def to_s
|
5
|
+
sprintf("%s %4d%s/%s %s\n",
|
6
|
+
secret? ? 'ssc' : 'sub',
|
7
|
+
length,
|
8
|
+
pubkey_algo_letter,
|
9
|
+
fingerprint,
|
10
|
+
timestamp.strftime('%Y-%m-%d'))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module GPGME
|
2
|
+
class UserID
|
3
|
+
def name
|
4
|
+
sanitize_encoding(@name)
|
5
|
+
end
|
6
|
+
def comment
|
7
|
+
sanitize_encoding(@comment)
|
8
|
+
end
|
9
|
+
def uid
|
10
|
+
sanitize_encoding(@uid)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def sanitize_encoding(str)
|
15
|
+
if str.is_a?(String) && str.encoding != 'UTF-8'
|
16
|
+
str.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: '')
|
17
|
+
else
|
18
|
+
str
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/schleuder/list.rb
CHANGED
@@ -1,193 +1,384 @@
|
|
1
1
|
module Schleuder
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
2
|
+
class List < ActiveRecord::Base
|
3
|
+
|
4
|
+
has_many :subscriptions, dependent: :destroy
|
5
|
+
before_destroy :delete_listdirs
|
6
|
+
|
7
|
+
serialize :headers_to_meta, JSON
|
8
|
+
serialize :bounces_drop_on_headers, JSON
|
9
|
+
serialize :keywords_admin_only, JSON
|
10
|
+
serialize :keywords_admin_notify, JSON
|
11
|
+
|
12
|
+
validates :email, presence: true, uniqueness: true, email: true
|
13
|
+
validates :fingerprint, presence: true, fingerprint: true
|
14
|
+
validates :send_encrypted_only,
|
15
|
+
:receive_encrypted_only,
|
16
|
+
:receive_signed_only,
|
17
|
+
:receive_authenticated_only,
|
18
|
+
:receive_from_subscribed_emailaddresses_only,
|
19
|
+
:receive_admin_only,
|
20
|
+
:keep_msgid,
|
21
|
+
:bounces_drop_all,
|
22
|
+
:bounces_notify_admins,
|
23
|
+
:include_list_headers,
|
24
|
+
:include_openpgp_header,
|
25
|
+
:forward_all_incoming_to_admins, boolean: true
|
26
|
+
validates_each :headers_to_meta,
|
27
|
+
:keywords_admin_only,
|
28
|
+
:keywords_admin_notify do |record, attrib, value|
|
29
|
+
value.each do |word|
|
30
|
+
if word !~ /\A[a-z_-]+\z/i
|
31
|
+
record.errors.add(attrib, I18n.t("errors.invalid_characters"))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
validates_each :bounces_drop_on_headers do |record, attrib, value|
|
36
|
+
value.each do |key, val|
|
37
|
+
if key.to_s !~ /\A[a-z-]+\z/i || val.to_s !~ /\A[[:graph:]]+\z/i
|
38
|
+
record.errors.add(attrib, I18n.t("errors.invalid_characters"))
|
39
|
+
end
|
40
|
+
end
|
26
41
|
end
|
42
|
+
validates :subject_prefix,
|
43
|
+
:subject_prefix_in,
|
44
|
+
:subject_prefix_out,
|
45
|
+
no_line_breaks: true
|
46
|
+
validates :openpgp_header_preference,
|
47
|
+
presence: true,
|
48
|
+
inclusion: {
|
49
|
+
in: %w(sign encrypt signencrypt unprotected none),
|
50
|
+
}
|
51
|
+
validates :max_message_size_kb, :logfiles_to_keep, greater_than_zero: true
|
52
|
+
validates :log_level,
|
53
|
+
presence: true,
|
54
|
+
inclusion: {
|
55
|
+
in: %w(debug info warn error),
|
56
|
+
}
|
57
|
+
validates :language,
|
58
|
+
presence: true,
|
59
|
+
inclusion: {
|
60
|
+
# TODO: find out why we break translations and available_locales if we use I18n.available_locales here.
|
61
|
+
in: %w(de en),
|
62
|
+
}
|
63
|
+
validates :public_footer, :internal_footer,
|
64
|
+
allow_blank: true,
|
65
|
+
format: {
|
66
|
+
with: /\A[[:graph:]\s]*\z/i,
|
67
|
+
}
|
68
|
+
|
69
|
+
default_scope { order(:email) }
|
70
|
+
|
71
|
+
def self.configurable_attributes
|
72
|
+
@configurable_attributes ||= begin
|
73
|
+
all = self.validators.map(&:attributes).flatten.uniq.compact.sort
|
74
|
+
all - [:email, :fingerprint]
|
27
75
|
end
|
28
|
-
@members
|
29
76
|
end
|
30
77
|
|
31
|
-
def
|
32
|
-
@
|
78
|
+
def logfile
|
79
|
+
@logfile ||= File.join(Conf.listlogs_dir, self.email.split('@').reverse, 'list.log')
|
80
|
+
end
|
81
|
+
|
82
|
+
def logger
|
83
|
+
@logger ||= Listlogger.new(self)
|
33
84
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
Schleuder.log.debug 'writing members'
|
38
|
-
Schleuder.log.info("writing #{members_file}")
|
39
|
-
@members = arr.collect { |m| m.kind_of?(Hash) ? Member.new(m) : m }
|
40
|
-
_write(YAML.dump(@members.collect { |m| m.to_hash }), members_file)
|
41
|
-
@members
|
85
|
+
|
86
|
+
def to_s
|
87
|
+
email
|
42
88
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
addresses = Array(addresses)
|
47
|
-
members.detect { |m| addresses.include?(m.email) } || false
|
89
|
+
|
90
|
+
def admins
|
91
|
+
subscriptions.where(admin: true)
|
48
92
|
end
|
49
93
|
|
50
|
-
def
|
51
|
-
|
52
|
-
if admin_email = self.config.admins.detect { |a| addresses.include?(a.email) }
|
53
|
-
Member.new(:email => admin_email)
|
54
|
-
else
|
55
|
-
false
|
56
|
-
end
|
94
|
+
def subscriptions_without_fingerprint
|
95
|
+
subscriptions.without_fingerprint
|
57
96
|
end
|
58
97
|
|
59
|
-
def
|
60
|
-
|
61
|
-
find_by_key(members, key)
|
98
|
+
def key(fingerprint=self.fingerprint)
|
99
|
+
keys(fingerprint).first
|
62
100
|
end
|
63
101
|
|
64
|
-
def
|
65
|
-
|
66
|
-
find_by_key(config.admins, key)
|
102
|
+
def secret_key
|
103
|
+
keys(self.fingerprint, true).first
|
67
104
|
end
|
68
105
|
|
69
|
-
def
|
70
|
-
|
106
|
+
def keys(identifier=nil, secret_only=nil)
|
107
|
+
gpg.find_keys(identifier, secret_only)
|
71
108
|
end
|
72
109
|
|
73
|
-
|
74
|
-
|
110
|
+
# TODO: find better name for this method. It does more than the current
|
111
|
+
# name suggests (filtering for capability).
|
112
|
+
def distinct_key(identifier)
|
113
|
+
keys = keys(identifier).select { |key| key.usable_for?(:encrypt) }
|
114
|
+
if keys.size == 1
|
115
|
+
return keys.first
|
116
|
+
else
|
117
|
+
return nil
|
118
|
+
end
|
75
119
|
end
|
76
120
|
|
77
|
-
|
78
|
-
|
79
|
-
@config ||= _load_config
|
121
|
+
def import_key(importable)
|
122
|
+
gpg.keyimport(importable)
|
80
123
|
end
|
81
124
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
125
|
+
def import_key_and_find_fingerprint(key_material)
|
126
|
+
return nil if key_material.blank?
|
127
|
+
|
128
|
+
import_result = import_key(key_material)
|
129
|
+
gpg.interpret_import_result(import_result)
|
130
|
+
end
|
131
|
+
|
132
|
+
def delete_key(fingerprint)
|
133
|
+
if key = keys(fingerprint).first
|
134
|
+
key.delete!
|
135
|
+
true
|
88
136
|
else
|
89
|
-
|
137
|
+
false
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def export_key(fingerprint=self.fingerprint)
|
142
|
+
key = keys(fingerprint).first
|
143
|
+
if key.blank?
|
144
|
+
return false
|
90
145
|
end
|
91
|
-
|
92
|
-
|
146
|
+
key.armored
|
147
|
+
end
|
148
|
+
|
149
|
+
def check_keys
|
150
|
+
now = Time.now
|
151
|
+
checkdate = now + (60 * 60 * 24 * 14) # two weeks
|
152
|
+
unusable = []
|
153
|
+
expiring = []
|
154
|
+
|
155
|
+
keys.each do |key|
|
156
|
+
expiry = key.subkeys.first.expires
|
157
|
+
if expiry && expiry > now && expiry < checkdate
|
158
|
+
# key expires in the near future
|
159
|
+
expdays = ((expiry - now)/86400).to_i
|
160
|
+
expiring << [key, expdays]
|
161
|
+
end
|
162
|
+
|
163
|
+
if ! key.usable?
|
164
|
+
unusable << [key, key.usability_issue]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
text = ''
|
169
|
+
expiring.each do |key,days|
|
170
|
+
text << I18n.t('key_expires', {
|
171
|
+
days: days,
|
172
|
+
key_oneline: key.oneline
|
173
|
+
})
|
174
|
+
text << "\n"
|
175
|
+
end
|
176
|
+
|
177
|
+
unusable.each do |key,usability_issue|
|
178
|
+
text << I18n.t('key_unusable', {
|
179
|
+
usability_issue: usability_issue,
|
180
|
+
key_oneline: key.oneline
|
181
|
+
})
|
182
|
+
text << "\n"
|
183
|
+
end
|
184
|
+
text
|
185
|
+
end
|
186
|
+
|
187
|
+
def refresh_keys
|
188
|
+
gpg.refresh_keys(self.keys)
|
189
|
+
end
|
190
|
+
|
191
|
+
def fetch_keys(input)
|
192
|
+
gpg.fetch_key(input)
|
93
193
|
end
|
94
194
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
if domain.nil?
|
102
|
-
# pre 2.2 style
|
103
|
-
File.join(Schleuder.config.lists_configfile, "#{local_part}.conf")
|
195
|
+
def pin_keys
|
196
|
+
updated_emails = subscriptions_without_fingerprint.collect do |subscription|
|
197
|
+
key = distinct_key(subscription.email)
|
198
|
+
if key
|
199
|
+
subscription.update(fingerprint: key.fingerprint)
|
200
|
+
"#{subscription.email}: #{key.fingerprint}"
|
104
201
|
else
|
105
|
-
|
202
|
+
nil
|
106
203
|
end
|
107
|
-
else
|
108
|
-
File.join(@listdir, Schleuder.config.lists_configfile)
|
109
204
|
end
|
205
|
+
updated_emails.compact.join("\n")
|
110
206
|
end
|
111
207
|
|
112
|
-
|
113
|
-
|
114
|
-
|
208
|
+
def self.by_recipient(recipient)
|
209
|
+
listname = recipient.gsub(/-(sendkey|request|owner|bounce)@/, '@')
|
210
|
+
where(email: listname).first
|
115
211
|
end
|
116
212
|
|
117
|
-
|
118
|
-
|
119
|
-
@owner_addr ||= self.config.myaddr.gsub(/^(.*)@(.*)$/, '\1-owner@\2')
|
213
|
+
def sendkey_address
|
214
|
+
@sendkey_address ||= email.gsub('@', '-sendkey@')
|
120
215
|
end
|
121
216
|
|
122
|
-
|
123
|
-
|
124
|
-
@request_addr ||= self.config.myaddr.gsub(/^(.*)@(.*)$/, '\1-request@\2')
|
217
|
+
def request_address
|
218
|
+
@request_address ||= email.gsub('@', '-request@')
|
125
219
|
end
|
126
220
|
|
127
|
-
|
128
|
-
|
129
|
-
self.config.myaddr.gsub(/^(.*)@(.*)$/, '\1-sendkey@\2')
|
221
|
+
def owner_address
|
222
|
+
@owner_address ||= email.gsub('@', '-owner@')
|
130
223
|
end
|
131
224
|
|
132
|
-
def
|
133
|
-
|
134
|
-
|
135
|
-
|
225
|
+
def bounce_address
|
226
|
+
@bounce_address ||= email.gsub('@', '-bounce@')
|
227
|
+
end
|
228
|
+
|
229
|
+
def gpg
|
230
|
+
@gpg_ctx ||= begin
|
231
|
+
# TODO: figure out why set it again...
|
232
|
+
# Set GNUPGHOME when list is created.
|
233
|
+
set_gnupg_home
|
234
|
+
GPGME::Ctx.new armor: true
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# TODO: place this somewhere sensible.
|
239
|
+
# Call cleanup when script finishes.
|
240
|
+
#Signal.trap(0, proc { @list.cleanup })
|
241
|
+
def cleanup
|
242
|
+
if @gpg_agent_pid
|
243
|
+
Process.kill('TERM', @gpg_agent_pid.to_i)
|
136
244
|
end
|
137
|
-
|
245
|
+
rescue => e
|
246
|
+
$stderr.puts "Failed to kill gpg-agent: #{e}"
|
247
|
+
end
|
248
|
+
|
249
|
+
def gpg_sign_options
|
250
|
+
{sign: true, sign_as: self.fingerprint}
|
251
|
+
end
|
252
|
+
|
253
|
+
def fingerprint=(arg)
|
254
|
+
# Strip whitespace from incoming arg.
|
255
|
+
if arg
|
256
|
+
write_attribute(:fingerprint, arg.gsub(/\s*/, '').chomp)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def self.listdir(listname)
|
261
|
+
File.join(
|
262
|
+
Conf.lists_dir,
|
263
|
+
listname.split('@').reverse
|
264
|
+
)
|
138
265
|
end
|
139
266
|
|
140
267
|
def listdir
|
141
|
-
@listdir ||=
|
268
|
+
@listdir ||= self.class.listdir(self.email)
|
142
269
|
end
|
143
270
|
|
144
|
-
|
145
|
-
|
271
|
+
# A convenience-method to simplify other code.
|
272
|
+
def subscribe(email, fingerprint=nil, adminflag=nil, deliveryflag=nil, key_material=nil)
|
273
|
+
messages = nil
|
274
|
+
args = {
|
275
|
+
list_id: self.id,
|
276
|
+
email: email
|
277
|
+
}
|
278
|
+
if key_material.present?
|
279
|
+
fingerprint, messages = import_key_and_find_fingerprint(key_material)
|
280
|
+
end
|
281
|
+
args[:fingerprint] = fingerprint
|
282
|
+
# ActiveRecord does not treat nil as falsy for boolean columns, so we
|
283
|
+
# have to avoid that in order to not receive an invalid object. The
|
284
|
+
# database will use the column's default-value if no value is being
|
285
|
+
# given. (I'd rather not duplicate the defaults here.)
|
286
|
+
if ! adminflag.nil?
|
287
|
+
args[:admin] = adminflag
|
288
|
+
end
|
289
|
+
if ! deliveryflag.nil?
|
290
|
+
args[:delivery_enabled] = deliveryflag
|
291
|
+
end
|
292
|
+
subscription = Subscription.create(args)
|
293
|
+
[subscription, messages]
|
146
294
|
end
|
147
295
|
|
148
|
-
def
|
149
|
-
|
296
|
+
def unsubscribe(email, delete_key=false)
|
297
|
+
sub = subscriptions.where(email: email).first
|
298
|
+
if sub.blank?
|
299
|
+
false
|
300
|
+
end
|
301
|
+
|
302
|
+
if ! sub.destroy
|
303
|
+
return sub
|
304
|
+
end
|
305
|
+
|
306
|
+
if delete_key
|
307
|
+
sub.delete_key
|
308
|
+
end
|
150
309
|
end
|
151
310
|
|
152
|
-
def
|
153
|
-
|
311
|
+
def keywords_admin_notify
|
312
|
+
Array(read_attribute(:keywords_admin_notify))
|
154
313
|
end
|
155
314
|
|
156
|
-
def
|
157
|
-
|
158
|
-
@list_archiver.archive(mail)
|
315
|
+
def keywords_admin_only
|
316
|
+
Array(read_attribute(:keywords_admin_only))
|
159
317
|
end
|
160
318
|
|
161
|
-
|
319
|
+
def admin_only?(keyword)
|
320
|
+
keywords_admin_only.include?(keyword)
|
321
|
+
end
|
162
322
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
323
|
+
def from_admin?(mail)
|
324
|
+
return false if ! mail.was_validly_signed?
|
325
|
+
admins.find do |admin|
|
326
|
+
admin.fingerprint == mail.signing_key.fingerprint
|
327
|
+
end.presence || false
|
167
328
|
end
|
168
329
|
|
169
|
-
def
|
170
|
-
|
171
|
-
res = ary.detect { |elem| elem.kind_of?(Member) && elem.uses_key?(key) }
|
172
|
-
Schleuder.log.debug "Found #{res} for #{key}" unless res.nil?
|
173
|
-
res || false
|
330
|
+
def set_attribute(attrib, value)
|
331
|
+
self.send("#{attrib}=", value)
|
174
332
|
end
|
175
333
|
|
176
|
-
def
|
177
|
-
|
334
|
+
def send_list_key_to_subscriptions
|
335
|
+
mail = Mail.new
|
336
|
+
mail.from = self.email
|
337
|
+
mail.subject = I18n.t('list_public_key_subject')
|
338
|
+
mail.body = I18n.t('list_public_key_attached')
|
339
|
+
mail.attach_list_key!(self)
|
340
|
+
send_to_subscriptions(mail)
|
341
|
+
true
|
178
342
|
end
|
179
343
|
|
180
|
-
def
|
181
|
-
|
182
|
-
|
183
|
-
|
344
|
+
def send_to_subscriptions(mail)
|
345
|
+
logger.debug "Sending to subscriptions."
|
346
|
+
mail.add_internal_footer!
|
347
|
+
self.subscriptions.each do |subscription|
|
348
|
+
begin
|
349
|
+
subscription.send_mail(mail)
|
350
|
+
rescue => exc
|
351
|
+
msg = I18n.t('errors.delivery_error',
|
352
|
+
{ email: subscription.email, error: exc.to_s })
|
353
|
+
logger.error msg
|
354
|
+
logger.error exc
|
355
|
+
end
|
184
356
|
end
|
185
|
-
key
|
186
357
|
end
|
187
358
|
|
188
|
-
|
189
|
-
|
359
|
+
private
|
360
|
+
|
361
|
+
def set_gnupg_home
|
362
|
+
ENV['GNUPGHOME'] = listdir
|
190
363
|
end
|
191
364
|
|
365
|
+
def delete_listdirs
|
366
|
+
if File.exists?(self.listdir)
|
367
|
+
FileUtils.rm_rf(self.listdir, secure: true)
|
368
|
+
Schleuder.logger.info "Deleted #{self.listdir}"
|
369
|
+
end
|
370
|
+
# If listlogs_dir is different from lists_dir, the logfile still exists
|
371
|
+
# and needs to be deleted, too.
|
372
|
+
logfile_dir = File.dirname(self.logfile)
|
373
|
+
if File.exists?(logfile_dir)
|
374
|
+
FileUtils.rm_rf(logfile_dir, secure: true)
|
375
|
+
Schleuder.logger.info "Deleted #{logfile_dir}"
|
376
|
+
end
|
377
|
+
true
|
378
|
+
rescue => exc
|
379
|
+
# Don't use list-logger here — if the list-dir isn't present we can't log to it!
|
380
|
+
Schleuder.logger.error "Error while deleting listdir: #{exc}"
|
381
|
+
return false
|
382
|
+
end
|
192
383
|
end
|
193
384
|
end
|