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
data/lib/schleuder/crypt.rb
DELETED
@@ -1,210 +0,0 @@
|
|
1
|
-
module Schleuder
|
2
|
-
# Wrapper for ruby-gpgme. Method naming is not strictly logical, this might
|
3
|
-
# change but aliases will be set up then.
|
4
|
-
class Crypt
|
5
|
-
# Instantiates and stores password
|
6
|
-
def initialize(password, options={})
|
7
|
-
unless options[:new_keyring]
|
8
|
-
# Check file permissions. ruby-gpgme unfortunately returns unspecific
|
9
|
-
# errors if it can't read files.
|
10
|
-
%w(pubring.gpg secring.gpg trustdb.gpg).each do |fn|
|
11
|
-
f = File.join(ENV['GNUPGHOME'], fn)
|
12
|
-
if ! File.readable?(f)
|
13
|
-
raise Errno::EACCES.new('%s is not readable' % f)
|
14
|
-
elsif ! File.writable?(f)
|
15
|
-
raise Errno::EACCES.new('%s is not writable' % f)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
@password = password
|
21
|
-
if GPGME.respond_to? 'check_version'
|
22
|
-
GPGME::check_version('0.0.0')
|
23
|
-
end
|
24
|
-
@ctx = GPGME::Ctx.new
|
25
|
-
# feed the passphrase into the Context
|
26
|
-
@ctx.set_passphrase_cb(method(:passfunc))
|
27
|
-
end
|
28
|
-
|
29
|
-
# Verify a gpg-signature. Use +signed_string+ if the signature is
|
30
|
-
# detached. Returns a GPGME::SignatureResult
|
31
|
-
def verify(sig, signed_string='')
|
32
|
-
in_signed = ''
|
33
|
-
if signed_string.empty?
|
34
|
-
# verify +sig+ as cleartext (aka pgp/inline) signature
|
35
|
-
Schleuder.log.debug 'No extra signed_string, verifying cleartext signature'
|
36
|
-
output = GPGME.verify(sig) do |sig|
|
37
|
-
in_signed = sig
|
38
|
-
end
|
39
|
-
else
|
40
|
-
# verify detached signature
|
41
|
-
Schleuder.log.debug 'Verifying detached signature'
|
42
|
-
# Don't know why we need a GPGME::Data object this time but without gpgme throws exceptions
|
43
|
-
plain = GPGME::Data.new
|
44
|
-
GPGME.verify(sig, signed_string, plain) do |sig|
|
45
|
-
in_signed = sig
|
46
|
-
end
|
47
|
-
output = signed_string
|
48
|
-
|
49
|
-
end
|
50
|
-
Schleuder.log.debug 'verify_result: ' + in_signed.inspect
|
51
|
-
|
52
|
-
[output, in_signed]
|
53
|
-
end
|
54
|
-
|
55
|
-
# Decrypt a string.
|
56
|
-
def decrypt(str)
|
57
|
-
output = ""
|
58
|
-
in_encrypted = nil
|
59
|
-
in_signed = nil
|
60
|
-
|
61
|
-
# TODO: return ciphertext if missing key when decrypting inline
|
62
|
-
# attachments or recursing into mime-messages. Breaking if even the
|
63
|
-
# whole message is not decryptable is a job for the processor.
|
64
|
-
|
65
|
-
# match pgp-mime- and inline-pgp-signatures
|
66
|
-
if str =~ /^-----BEGIN PGP SIG/
|
67
|
-
Schleuder.log.debug 'found ascii-armored, signed, not encrypted message, verifying'
|
68
|
-
output, in_signed = verify(str)
|
69
|
-
else
|
70
|
-
begin
|
71
|
-
Schleuder.log.debug 'Trying to decrypt'
|
72
|
-
output = GPGME.decrypt(str, :passphrase_callback => method(:passfunc)) do |sig|
|
73
|
-
in_signed = sig
|
74
|
-
end
|
75
|
-
in_encrypted = true
|
76
|
-
rescue GPGME::Error::NoData => exc
|
77
|
-
Schleuder.log.debug "Caught NoData-exception from gpgme. This probably means we're dealing with a binary signature, trying to verify."
|
78
|
-
output, in_signed = verify(str)
|
79
|
-
if output.empty?
|
80
|
-
Schleuder.log.debug "Empty output from verification. No more options, returning."
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
Schleuder.log.debug "mime_type of decrypted content: #{output.mime.inspect}"
|
85
|
-
Schleuder.log.debug "in_signed: #{in_signed.inspect}"
|
86
|
-
Schleuder.log.debug "in_encrypted: #{in_encrypted.inspect}"
|
87
|
-
if output.empty?
|
88
|
-
Schleuder.log.debug "Empty output, returning input"
|
89
|
-
output = str
|
90
|
-
end
|
91
|
-
# TODO: return mailadresses or keys instead of signature-objects?
|
92
|
-
[output, in_encrypted, in_signed]
|
93
|
-
rescue GPGME::Error::General => exc
|
94
|
-
Schleuder.log.warn "gpgme returned a general error. Most likely this is due to unexpected input, but as you never know here's the input and the exception:\ninput:\n#{str.inspect}\n#{exc.to_s}\n#{exc.backtrace[0..9].join("\n")}"
|
95
|
-
[str, nil, nil]
|
96
|
-
end
|
97
|
-
|
98
|
-
# Encrypt a string to a single receiver and sign it. +receiver+ must be a
|
99
|
-
# Schleuder::Member
|
100
|
-
def encrypt_str(str, receiver)
|
101
|
-
# encrypt and sign and return encrypted data as string
|
102
|
-
# For some reason sometimes the last two characters of str are stolen
|
103
|
-
# unless we append a blank or newline... Life is hard...
|
104
|
-
GPGME.encrypt([receiver.key],
|
105
|
-
"#{str} ",
|
106
|
-
{:passphrase_callback => method(:passfunc),
|
107
|
-
:armor => true,
|
108
|
-
:sign => true,
|
109
|
-
:always_trust => true
|
110
|
-
})
|
111
|
-
end
|
112
|
-
|
113
|
-
# Lists all public keys matching +pattern+. Returns an array of
|
114
|
-
# GPGME::GpgKey's
|
115
|
-
def list_keys(pattern='')
|
116
|
-
GPGME.list_keys(pattern)
|
117
|
-
end
|
118
|
-
|
119
|
-
# Returns the GPGME::GpgKey matching +pattern+. Log an error if more than
|
120
|
-
# one matches, because duplicated user-ids is a sensitive issue.
|
121
|
-
def get_key(pattern, only_valid_keys=false)
|
122
|
-
pattern = "<#{pattern}>" if pattern =~ /.*@.*/ && !(pattern =~ /^<.*>$/)
|
123
|
-
keys = list_keys(pattern)
|
124
|
-
|
125
|
-
keys.reject! { |key| unusable_key?(key) } if only_valid_keys
|
126
|
-
|
127
|
-
if keys.empty?
|
128
|
-
[false, "no key found for #{pattern}."]
|
129
|
-
elsif keys.length > 1
|
130
|
-
Schleuder.log.warn "There's more than one key matching the pattern you gave me!"
|
131
|
-
Schleuder.log.debug { "Pattern: #{pattern.inspect}" }
|
132
|
-
Schleuder.log.debug { "Keys: #{keys.inspect}" }
|
133
|
-
[false, "no distinct key for #{pattern.inspect} found. Matching keys: #{key_infos(keys,only_valid_keys).join(', ')}"]
|
134
|
-
else
|
135
|
-
[keys.first]
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# Signs +string+ with the private key of the list (aka detached signature)
|
140
|
-
def sign(string)
|
141
|
-
GPGME::detach_sign(string, {:armor => true, :passphrase_callback => method(:passfunc)})
|
142
|
-
end
|
143
|
-
|
144
|
-
# Clearsigns +string+ with the private key of the list
|
145
|
-
def clearsign(string)
|
146
|
-
GPGME::clearsign(string, {:armor => true, :passphrase_callback => method(:passfunc)})
|
147
|
-
end
|
148
|
-
|
149
|
-
# Exports the public key matching +keyid+ as ascii key block.
|
150
|
-
def export(keyid)
|
151
|
-
GPGME.export(keyid, :armor=>:true)
|
152
|
-
end
|
153
|
-
|
154
|
-
# Delete the public key matching +pattern+ from the public key ring of the
|
155
|
-
# list
|
156
|
-
def delete_key(key)
|
157
|
-
msg = nil
|
158
|
-
key, msg = get_key(key) if key.kind_of?(String)
|
159
|
-
|
160
|
-
if key
|
161
|
-
@ctx.delete_key(key)
|
162
|
-
return true
|
163
|
-
else
|
164
|
-
msg
|
165
|
-
end
|
166
|
-
rescue => e
|
167
|
-
return e
|
168
|
-
end
|
169
|
-
|
170
|
-
# Import +keydata+ into public key ring of the list
|
171
|
-
def add_key(keydata)
|
172
|
-
GPGME.import(keydata)
|
173
|
-
end
|
174
|
-
|
175
|
-
def add_key_from_file(keyfile)
|
176
|
-
add_key(File.read(keyfile))
|
177
|
-
end
|
178
|
-
|
179
|
-
def key_descr(key)
|
180
|
-
key.to_s.split("\n").first.split[1..2].join(' ')
|
181
|
-
end
|
182
|
-
|
183
|
-
private
|
184
|
-
|
185
|
-
def key_infos(keys, only_valid_keys=false)
|
186
|
-
keys.collect do |key|
|
187
|
-
info = key_descr(key)
|
188
|
-
unless only_valid_keys
|
189
|
-
info << trust_info(key)
|
190
|
-
end
|
191
|
-
info
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def trust_info(key)
|
196
|
-
unusable_key?(key) ? " *#{key.trust}*" : ''
|
197
|
-
end
|
198
|
-
|
199
|
-
def unusable_key?(key)
|
200
|
-
[:revoked, :expired].include?(key.trust)
|
201
|
-
end
|
202
|
-
|
203
|
-
def passfunc(hook, uid_hint, passphrase_info, prev_was_bad, fd)
|
204
|
-
io = IO.for_fd(fd, 'w')
|
205
|
-
io.puts @password
|
206
|
-
io.flush
|
207
|
-
end
|
208
|
-
|
209
|
-
end
|
210
|
-
end
|
data/lib/schleuder/errors.rb
DELETED
@@ -1,146 +0,0 @@
|
|
1
|
-
# the list config class - a simple container
|
2
|
-
|
3
|
-
module Schleuder
|
4
|
-
class ListConfig < Storage
|
5
|
-
|
6
|
-
# Options and their defaults
|
7
|
-
# If you want to change the defaults, edit conf/default-list.conf
|
8
|
-
|
9
|
-
# Emailaddress of the list
|
10
|
-
schleuder_attr :myaddr, ''
|
11
|
-
|
12
|
-
# Realname of this list address (mainly used for gpg key)
|
13
|
-
schleuder_attr :myname, ''
|
14
|
-
|
15
|
-
# Listadmin's emailaddress(es). Must be an array.
|
16
|
-
schleuder_attr :admins, []
|
17
|
-
|
18
|
-
# Default mime setting
|
19
|
-
schleuder_attr :default_mime, 'MIME'
|
20
|
-
|
21
|
-
# The gpg password
|
22
|
-
schleuder_attr :gpg_password, nil
|
23
|
-
|
24
|
-
# The fingerprint of the key used for this list
|
25
|
-
schleuder_attr :key_fingerprint, nil
|
26
|
-
|
27
|
-
# Wether sending emails in the clear is allowed or not.
|
28
|
-
schleuder_attr :send_encrypted_only, false
|
29
|
-
|
30
|
-
# Wether to accept only incoming emails that are encrypted
|
31
|
-
schleuder_attr :receive_encrypted_only, false
|
32
|
-
|
33
|
-
# Wether to accept only emails that are validly signed
|
34
|
-
schleuder_attr :receive_signed_only, false
|
35
|
-
|
36
|
-
# Wether to accept only emails that are validly signed by a list-member's key
|
37
|
-
schleuder_attr :receive_authenticated_only, false
|
38
|
-
|
39
|
-
# Wether to accept only emails that are validly signed by a list-admin's key
|
40
|
-
schleuder_attr :receive_admin_only, false
|
41
|
-
|
42
|
-
# Whether to accept only emails that are sent from a members address.
|
43
|
-
# NOTE: better rely on :receive_authenticated_only and ignore that option.
|
44
|
-
schleuder_attr :receive_from_member_emailaddresses_only, false
|
45
|
-
|
46
|
-
# Wether to keep the msgid or not
|
47
|
-
schleuder_attr :keep_msgid, true
|
48
|
-
|
49
|
-
# Footer for outgoing mails
|
50
|
-
schleuder_attr :public_footer, ''
|
51
|
-
|
52
|
-
# Subject prefix for incoming (signed) mails from listmembers
|
53
|
-
schleuder_attr :prefix, ''
|
54
|
-
|
55
|
-
# Subject prefix for incoming mails
|
56
|
-
schleuder_attr :prefix_in, ''
|
57
|
-
|
58
|
-
# Subject prefix for outgoing mails
|
59
|
-
schleuder_attr :prefix_out, ''
|
60
|
-
|
61
|
-
# The log_level (ERROR || WARN || INFO || DEBUG)
|
62
|
-
schleuder_attr :log_level, 'ERROR'
|
63
|
-
|
64
|
-
# Log to SYSLOG?
|
65
|
-
schleuder_attr :log_syslog, false
|
66
|
-
|
67
|
-
# Log to IO (writing into STDIN of another process/executable)
|
68
|
-
schleuder_attr :log_io, false
|
69
|
-
|
70
|
-
# Log to a file? If the path doesn't start with a slash the list-dir will
|
71
|
-
# be prefixed.
|
72
|
-
schleuder_attr :log_file, 'list.log'
|
73
|
-
|
74
|
-
# Which headers from original mail to include into the internal meta data
|
75
|
-
schleuder_attr :headers_to_meta, [:from, :to, :cc, :date]
|
76
|
-
|
77
|
-
# Restrict specific plugins to admin
|
78
|
-
schleuder_attr :keywords_admin_only, ['ADD-MEMBER', 'DELETE-MEMBER', 'DELETE-KEY', 'SAVE-MEMBERS', 'DEL-KEY' ]
|
79
|
-
|
80
|
-
# Notify admin if these keywords triggered commands.
|
81
|
-
schleuder_attr :keywords_admin_notify, [ 'ADD-KEY' ]
|
82
|
-
|
83
|
-
# Drop any bounces (incoming email not passing the receive_*_only-rules)
|
84
|
-
schleuder_attr :bounces_drop_all, false
|
85
|
-
|
86
|
-
# Drop bounces if they match one of these headers. Must be a hash, keys and values are case insensitive.
|
87
|
-
schleuder_attr :bounces_drop_on_headers, {'x-spam-flag' => 'yes'}
|
88
|
-
|
89
|
-
# Send a notice to admin(s) on bouncing or dropping
|
90
|
-
schleuder_attr :bounces_notify_admin, true
|
91
|
-
|
92
|
-
# Include RFC-compliant List-* Headers into member mails
|
93
|
-
schleuder_attr :include_list_headers, true
|
94
|
-
|
95
|
-
# Include OpenPGP-Header
|
96
|
-
schleuder_attr :include_openpgp_header, true
|
97
|
-
# Preferred way to receive emails to note in OpenPGP-Header ('sign'|'encrypt'|'signencrypt'|'unprotected'|'none')
|
98
|
-
# 'none' to not include a preference
|
99
|
-
# default: 'signencrypt'
|
100
|
-
schleuder_attr :openpgp_header_preference, 'signencrypt'
|
101
|
-
|
102
|
-
# If we want to dump the original incoming mail.
|
103
|
-
# ATTENTION: this stores the incoming e-mail on disk!
|
104
|
-
schleuder_attr :dump_incoming_mail, false
|
105
|
-
|
106
|
-
# Maximum size of message allowed on the list in kilobyte. All others will be bounced.
|
107
|
-
schleuder_attr :max_message_size, 10240 # 10MB
|
108
|
-
|
109
|
-
# Whether to archive messages sent to list members or not.
|
110
|
-
# default: false
|
111
|
-
schleuder_attr :archive, false
|
112
|
-
|
113
|
-
### END OF CONFIG OPTIONS
|
114
|
-
|
115
|
-
def initialize(config=nil)
|
116
|
-
# First Overload with default-list.conf then load our config
|
117
|
-
overload_from_file!(Schleuder.config.lists_default_conf)
|
118
|
-
# overload with config_file
|
119
|
-
super(config)
|
120
|
-
|
121
|
-
# load admins as members
|
122
|
-
self.admins = self.admins
|
123
|
-
# compress fingerprint
|
124
|
-
self.key_fingerprint = self.key_fingerprint
|
125
|
-
end
|
126
|
-
|
127
|
-
def key_fingerprint=(fpr)
|
128
|
-
schleuder_attributes['key_fingerprint'] = Schleuder::Utils.compress_fingerprint(fpr)
|
129
|
-
end
|
130
|
-
|
131
|
-
def admins=(ary)
|
132
|
-
schleuder_attributes['admins'] = Array(ary).collect { |mem|
|
133
|
-
if mem.kind_of?(Member)
|
134
|
-
mem
|
135
|
-
else
|
136
|
-
if mem.kind_of?(Hash) && mem.has_key?("email")
|
137
|
-
Member.new(mem)
|
138
|
-
else
|
139
|
-
Schleuder.log.error "Wrong input: #{mem.inspect} is not suitable data for a Member."
|
140
|
-
nil
|
141
|
-
end
|
142
|
-
end
|
143
|
-
}.compact
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
module Schleuder
|
2
|
-
class ListLogger < Log4r::Logger
|
3
|
-
# Instantiates the list-logger and sets outputters and level.
|
4
|
-
# Warning: Do *not* rely on the list-object here! It's not yet available
|
5
|
-
# (this actually is part of setting it up) and you'd produce loops and
|
6
|
-
# break the whole thing.
|
7
|
-
def initialize(listname, listdir, config)
|
8
|
-
# Initialize self
|
9
|
-
super('list')
|
10
|
-
|
11
|
-
# define the initial log_level for all outputters (they inherit it)
|
12
|
-
@level = eval("Log4r::#{config.log_level.upcase}")
|
13
|
-
|
14
|
-
# Setting up outputters.
|
15
|
-
fmtr = Log4r::PatternFormatter.new(:pattern => "%d #{listname} %l\t%M")
|
16
|
-
|
17
|
-
if config.log_file
|
18
|
-
require 'log4r/outputter/fileoutputter'
|
19
|
-
filename = config.log_file
|
20
|
-
filename = File.join(listdir, filename) unless filename[0..0].eql?('/')
|
21
|
-
filename = File.join(filename, "#{listname}.log") if filename.end_with?('/')
|
22
|
-
add Log4r::FileOutputter.new("file",
|
23
|
-
{ :level => @level,
|
24
|
-
:filename => filename,
|
25
|
-
:formatter => fmtr }
|
26
|
-
)
|
27
|
-
end
|
28
|
-
|
29
|
-
if config.log_syslog
|
30
|
-
require 'log4r/outputter/syslogoutputter'
|
31
|
-
syslogfmtr = Log4r::PatternFormatter.new(:pattern => "#{listname}: %M")
|
32
|
-
add Log4r::SyslogOutputter.new("syslog",
|
33
|
-
{ :level => @level,
|
34
|
-
:ident => 'schleuder',
|
35
|
-
:facility => "LOG_MAIL",
|
36
|
-
:formatter => syslogfmtr }
|
37
|
-
)
|
38
|
-
end
|
39
|
-
|
40
|
-
if config.log_io
|
41
|
-
require 'log4r/outputter/iooutputter'
|
42
|
-
require 'stringio'
|
43
|
-
io = IO.popen(config.log_io, 'w')
|
44
|
-
add Log4r::IOOutputter.new("io", io, :level => @level)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Add this as last outputter, else you'll see logging-statements from
|
48
|
-
# sending the email before the original error is logged — that's a little
|
49
|
-
# confusing.
|
50
|
-
add EmailOutputter.new("email", :formatter => fmtr)
|
51
|
-
end
|
52
|
-
|
53
|
-
def notify_admin(*args)
|
54
|
-
Log4r::Outputter['email'].notify_admin *args
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,120 +0,0 @@
|
|
1
|
-
module Schleuder
|
2
|
-
class EmailOutputter < Log4r::EmailOutputter
|
3
|
-
def initialize(name, hash={})
|
4
|
-
# The class needs to/from/subject, we don't use it
|
5
|
-
hash = {:to => Schleuder.config.superadminaddr,
|
6
|
-
:from => Schleuder.config.myaddr,
|
7
|
-
:'error-to' => Schleuder.config.superadminaddr,
|
8
|
-
:subject => 'Error',
|
9
|
-
:server => Schleuder.config.smtp_host,
|
10
|
-
:port => Schleuder.config.smtp_port,
|
11
|
-
:immediate_at => 'ERROR, FATAL',
|
12
|
-
:formatter => formatter,
|
13
|
-
:domain => 'schleuder', # necessary for log4r from debian "stable"
|
14
|
-
:buffsize => 1024**1024 # set the buff size very high otherwise we would trigger random log mails on random log statements if the buffer is full.
|
15
|
-
}.merge(hash)
|
16
|
-
@altmsg = "Hello,\n\nsending an encrypted error message to you failed. Therefore you receive only\nthis message and are kindly requested to take care of the encryption problem\n(e.g. fix your keys) and have a look at the logs to find the error.\n\nYours, Schleuder\n"
|
17
|
-
super name, hash
|
18
|
-
end
|
19
|
-
|
20
|
-
def format(events)
|
21
|
-
events.map { |event| @formatter.format(event) }
|
22
|
-
end
|
23
|
-
|
24
|
-
def notify_admin(subject, msg)
|
25
|
-
send_mail(makeemail(subject, msg))
|
26
|
-
end
|
27
|
-
|
28
|
-
def makeemail(subject=@subject, msg=nil)
|
29
|
-
m = Mail.new
|
30
|
-
m.subject = subject
|
31
|
-
m.date = Time.now
|
32
|
-
m.from = @from
|
33
|
-
|
34
|
-
if msg
|
35
|
-
case msg
|
36
|
-
when String
|
37
|
-
m.body = msg
|
38
|
-
when Array
|
39
|
-
m.body = ''
|
40
|
-
m.mime_version = 1.0
|
41
|
-
msg.each do |msgpart|
|
42
|
-
part = Mail.new
|
43
|
-
case msgpart
|
44
|
-
when Mail
|
45
|
-
# This contruction is needed to have valid boundaries. Did I mention that Tmail sucks?
|
46
|
-
part.body = Mail.parse(msgpart.to_s).to_s
|
47
|
-
part.content_type = 'message/rfc822'
|
48
|
-
when String
|
49
|
-
part.body = msgpart.to_s
|
50
|
-
part.content_type = 'text/plain'
|
51
|
-
else
|
52
|
-
# This shouldn't happen (we should only have forwarded emails or
|
53
|
-
# strings to notify admins), but who knows.
|
54
|
-
part.body = msgpart
|
55
|
-
part.content_type = 'application/octet-stream'
|
56
|
-
end
|
57
|
-
m.parts.push part
|
58
|
-
end
|
59
|
-
end
|
60
|
-
else
|
61
|
-
# Get the triggering error-msg(s).
|
62
|
-
msg = format(@buff.select { |e| e.level > Log4r::WARN }).join
|
63
|
-
# Get the whole log.
|
64
|
-
backlog = format(@buff).join
|
65
|
-
|
66
|
-
infopart = Mail.new
|
67
|
-
infopart.body = "An error occurred working for list #{Schleuder.list.listname}:\n\n#{msg}\n\nSee also attachments.\n\n"
|
68
|
-
m.parts.push infopart
|
69
|
-
|
70
|
-
if Schleuder.origmsg
|
71
|
-
origm = Mail.new
|
72
|
-
origm.body = Schleuder.origmsg << "\n"
|
73
|
-
origm.content_type = "message/rfc822"
|
74
|
-
origm.set_content_disposition 'inline', { :filename => 'schleuder-orig-message.txt' }
|
75
|
-
origm['content-description'] = "'The originally incoming message'"
|
76
|
-
m.parts.push origm
|
77
|
-
end
|
78
|
-
|
79
|
-
backlogpart = Mail.new
|
80
|
-
backlogpart.body = backlog << "\n\n"
|
81
|
-
backlogpart['content-description'] = "'Schleuder logging output'"
|
82
|
-
backlogpart.set_content_disposition 'inline', { :filename => 'schleuder-log.txt' }
|
83
|
-
m.parts.push backlogpart
|
84
|
-
end
|
85
|
-
|
86
|
-
# Trigger re-parsing of the body, else TMail doesn't know it's multipart... :/
|
87
|
-
m.to_s
|
88
|
-
m
|
89
|
-
end
|
90
|
-
|
91
|
-
def send_mail(mail=makeemail)
|
92
|
-
if @send_mail_lock
|
93
|
-
self.level = Log4r::OFF # it's possible that the loglevel haven't yet been changed
|
94
|
-
Schleuder.log.warn "This is a loop in sending a mail in the EmailOutputer, breaking!"
|
95
|
-
return false
|
96
|
-
end
|
97
|
-
@send_mail_lock = true
|
98
|
-
Schleuder.log.info 'Sending notification to admin'
|
99
|
-
Schleuder.list.config.admins.each do |admin|
|
100
|
-
Schleuder.log.debug { "Looping for admin #{admin}" }
|
101
|
-
m = mail.individualize(admin)
|
102
|
-
m.to = admin.email
|
103
|
-
sender = Schleuder.config.superadminaddr
|
104
|
-
if !Processor.send(m, admin, true, sender)
|
105
|
-
m.body = @altmsg
|
106
|
-
m.content_type = 'text/plain'
|
107
|
-
Processor.send(m, admin, false, sender)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
Schleuder.log.info { 'Sending notification done' }
|
111
|
-
rescue => e
|
112
|
-
# switch off logging per email, else we create loops here!
|
113
|
-
self.level = Log4r::OFF
|
114
|
-
raise
|
115
|
-
ensure
|
116
|
-
@send_mail_lock = false
|
117
|
-
@buff.clear
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|