schleuder 2.2.4 → 3.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +138 -0
  3. data/Rakefile +136 -0
  4. data/bin/pinentry-clearpassphrase +72 -0
  5. data/bin/schleuder +9 -89
  6. data/bin/schleuder-api-daemon +4 -0
  7. data/db/migrate/20140501103532_create_lists.rb +39 -0
  8. data/db/migrate/20140501112859_create_subscriptions.rb +21 -0
  9. data/db/migrate/201508092100_add_language_to_lists.rb +11 -0
  10. data/db/migrate/20150812165700_change_keywords_admin_only_defaults.rb +8 -0
  11. data/db/migrate/20150813235800_add_forward_all_incoming_to_admins.rb +11 -0
  12. data/db/migrate/201508141727_change_send_encrypted_only_default.rb +8 -0
  13. data/db/migrate/201508222143_add_logfiles_to_keep_to_lists.rb +11 -0
  14. data/db/migrate/201508261723_rename_delivery_disabled_to_delivery_enabled_and_change_default.rb +14 -0
  15. data/db/migrate/201508261815_strip_gpg_passphrase.rb +11 -0
  16. data/db/migrate/201508261827_remove_default_mime.rb +9 -0
  17. data/db/migrate/20160501172700_fix_headers_to_meta_defaults.rb +8 -0
  18. data/db/migrate/20170713215059_add_internal_footer_to_list.rb +11 -0
  19. data/db/schema.rb +62 -0
  20. data/etc/init.d/schleuder-api-daemon +87 -0
  21. data/etc/list-defaults.yml +123 -0
  22. data/etc/postfix/schleuder_sqlite.cf +28 -0
  23. data/etc/schleuder-api-daemon.service +10 -0
  24. data/etc/schleuder.cron.weekly +6 -0
  25. data/etc/schleuder.yml +61 -0
  26. data/lib/schleuder-api-daemon.rb +420 -0
  27. data/lib/schleuder.rb +81 -47
  28. data/lib/schleuder/cli.rb +334 -0
  29. data/lib/schleuder/cli/cert.rb +24 -0
  30. data/lib/schleuder/cli/schleuder_cert_manager.rb +84 -0
  31. data/lib/schleuder/cli/subcommand_fix.rb +11 -0
  32. data/lib/schleuder/conf.rb +131 -0
  33. data/lib/schleuder/errors/active_model_error.rb +15 -0
  34. data/lib/schleuder/errors/base.rb +17 -0
  35. data/lib/schleuder/errors/decryption_failed.rb +16 -0
  36. data/lib/schleuder/errors/fatal_error.rb +13 -0
  37. data/lib/schleuder/errors/file_not_found.rb +14 -0
  38. data/lib/schleuder/errors/invalid_listname.rb +13 -0
  39. data/lib/schleuder/errors/key_adduid_failed.rb +13 -0
  40. data/lib/schleuder/errors/key_generation_failed.rb +16 -0
  41. data/lib/schleuder/errors/keyword_admin_only.rb +13 -0
  42. data/lib/schleuder/errors/list_exists.rb +13 -0
  43. data/lib/schleuder/errors/list_not_found.rb +14 -0
  44. data/lib/schleuder/errors/list_property_missing.rb +14 -0
  45. data/lib/schleuder/errors/listdir_problem.rb +16 -0
  46. data/lib/schleuder/errors/loading_list_settings_failed.rb +14 -0
  47. data/lib/schleuder/errors/message_empty.rb +14 -0
  48. data/lib/schleuder/errors/message_not_from_admin.rb +13 -0
  49. data/lib/schleuder/errors/message_sender_not_subscribed.rb +13 -0
  50. data/lib/schleuder/errors/message_too_big.rb +14 -0
  51. data/lib/schleuder/errors/message_unauthenticated.rb +13 -0
  52. data/lib/schleuder/errors/message_unencrypted.rb +13 -0
  53. data/lib/schleuder/errors/message_unsigned.rb +13 -0
  54. data/lib/schleuder/errors/standard_error.rb +5 -0
  55. data/lib/schleuder/errors/too_many_keys.rb +17 -0
  56. data/lib/schleuder/errors/unknown_list_option.rb +14 -0
  57. data/lib/schleuder/filters/auth_filter.rb +39 -0
  58. data/lib/schleuder/filters/bounces_filter.rb +12 -0
  59. data/lib/schleuder/filters/forward_filter.rb +17 -0
  60. data/lib/schleuder/filters/forward_incoming.rb +13 -0
  61. data/lib/schleuder/filters/hotmail_message_filter.rb +25 -0
  62. data/lib/schleuder/filters/max_message_size.rb +14 -0
  63. data/lib/schleuder/filters/request_filter.rb +26 -0
  64. data/lib/schleuder/filters/send_key_filter.rb +20 -0
  65. data/lib/schleuder/filters/strip_alternative_filter.rb +21 -0
  66. data/lib/schleuder/filters_runner.rb +83 -0
  67. data/lib/schleuder/gpgme/ctx.rb +274 -0
  68. data/lib/schleuder/gpgme/import_status.rb +27 -0
  69. data/lib/schleuder/gpgme/key.rb +212 -0
  70. data/lib/schleuder/gpgme/sub_key.rb +13 -0
  71. data/lib/schleuder/gpgme/user_id.rb +22 -0
  72. data/lib/schleuder/list.rb +318 -127
  73. data/lib/schleuder/list_builder.rb +139 -0
  74. data/lib/schleuder/listlogger.rb +31 -0
  75. data/lib/schleuder/logger.rb +23 -0
  76. data/lib/schleuder/logger_notifications.rb +69 -0
  77. data/lib/schleuder/mail/message.rb +482 -0
  78. data/lib/schleuder/mail/parts_list.rb +9 -0
  79. data/lib/schleuder/plugin_runners/base.rb +91 -0
  80. data/lib/schleuder/plugin_runners/list_plugins_runner.rb +24 -0
  81. data/lib/schleuder/plugin_runners/request_plugins_runner.rb +27 -0
  82. data/lib/schleuder/plugins/attach_listkey.rb +17 -0
  83. data/lib/schleuder/plugins/get_version.rb +7 -0
  84. data/lib/schleuder/plugins/key_management.rb +113 -0
  85. data/lib/schleuder/plugins/list_management.rb +15 -0
  86. data/lib/schleuder/plugins/resend.rb +196 -0
  87. data/lib/schleuder/plugins/sign_this.rb +46 -0
  88. data/lib/schleuder/plugins/subscription_management.rb +140 -0
  89. data/lib/schleuder/runner.rb +130 -0
  90. data/lib/schleuder/subscription.rb +98 -0
  91. data/lib/schleuder/validators/boolean_validator.rb +7 -0
  92. data/lib/schleuder/validators/email_validator.rb +7 -0
  93. data/lib/schleuder/validators/fingerprint_validator.rb +7 -0
  94. data/lib/schleuder/validators/greater_than_zero_validator.rb +7 -0
  95. data/lib/schleuder/validators/no_line_breaks_validator.rb +7 -0
  96. data/lib/schleuder/version.rb +1 -1
  97. data/locales/de.yml +179 -0
  98. data/locales/en.yml +179 -0
  99. metadata +305 -108
  100. checksums.yaml.gz.sig +0 -3
  101. data.tar.gz.sig +0 -2
  102. data/LICENSE +0 -339
  103. data/README +0 -32
  104. data/bin/schleuder-fix-gem-dependencies +0 -37
  105. data/bin/schleuder-init-setup +0 -37
  106. data/bin/schleuder-migrate-v2.1-to-v2.2 +0 -225
  107. data/bin/schleuder-newlist +0 -413
  108. data/contrib/check-expired-keys.rb +0 -60
  109. data/contrib/mutt-schleuder-colors.rc +0 -10
  110. data/contrib/mutt-schleuder-resend.vim +0 -24
  111. data/contrib/smtpserver.rb +0 -76
  112. data/ext/default-list.conf +0 -149
  113. data/ext/default-members.conf +0 -7
  114. data/ext/list.conf.example +0 -14
  115. data/ext/schleuder.conf +0 -64
  116. data/lib/schleuder/archiver.rb +0 -46
  117. data/lib/schleuder/crypt.rb +0 -210
  118. data/lib/schleuder/errors.rb +0 -5
  119. data/lib/schleuder/list_config.rb +0 -146
  120. data/lib/schleuder/log/listlogger.rb +0 -57
  121. data/lib/schleuder/log/outputter/emailoutputter.rb +0 -120
  122. data/lib/schleuder/log/outputter/metaemailoutputter.rb +0 -50
  123. data/lib/schleuder/log/schleuderlogger.rb +0 -34
  124. data/lib/schleuder/mail.rb +0 -873
  125. data/lib/schleuder/mailer.rb +0 -26
  126. data/lib/schleuder/member.rb +0 -69
  127. data/lib/schleuder/plugin.rb +0 -54
  128. data/lib/schleuder/processor.rb +0 -363
  129. data/lib/schleuder/schleuder_config.rb +0 -75
  130. data/lib/schleuder/storage.rb +0 -84
  131. data/lib/schleuder/utils.rb +0 -80
  132. data/man/schleuder-newlist.8 +0 -174
  133. data/man/schleuder.8 +0 -416
  134. data/plugins/README +0 -20
  135. data/plugins/manage_keys_plugin.rb +0 -113
  136. data/plugins/manage_members_plugin.rb +0 -156
  137. data/plugins/manage_self_plugin.rb +0 -26
  138. data/plugins/resend_plugin.rb +0 -35
  139. data/plugins/sign_this_plugin.rb +0 -14
  140. data/plugins/version_plugin.rb +0 -12
  141. metadata.gz.sig +0 -0
@@ -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
@@ -1,5 +0,0 @@
1
-
2
- class SchleuderError < RuntimeError
3
- end
4
- class NewListError < SchleuderError
5
- end
@@ -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