schleuder 2.2.4 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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