summaryrefslogtreecommitdiff
path: root/mailman/bin/checkdbs.py
diff options
context:
space:
mode:
Diffstat (limited to 'mailman/bin/checkdbs.py')
-rw-r--r--mailman/bin/checkdbs.py199
1 files changed, 199 insertions, 0 deletions
diff --git a/mailman/bin/checkdbs.py b/mailman/bin/checkdbs.py
new file mode 100644
index 000000000..a39b9c4aa
--- /dev/null
+++ b/mailman/bin/checkdbs.py
@@ -0,0 +1,199 @@
+# Copyright (C) 1998-2008 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+import sys
+import time
+import optparse
+
+from email.Charset import Charset
+
+from mailman import MailList
+from mailman import Message
+from mailman import Utils
+from mailman import Version
+from mailman import i18n
+from mailman.app.requests import handle_request
+from mailman.configuration import config
+
+_ = i18n._
+
+# Work around known problems with some RedHat cron daemons
+import signal
+signal.signal(signal.SIGCHLD, signal.SIG_DFL)
+
+NL = u'\n'
+now = time.time()
+
+
+
+def parseargs():
+ parser = optparse.OptionParser(version=Version.MAILMAN_VERSION,
+ usage=_("""\
+%prog [options]
+
+Check for pending admin requests and mail the list owners if necessary."""))
+ parser.add_option('-C', '--config',
+ help=_('Alternative configuration file to use'))
+ opts, args = parser.parse_args()
+ if args:
+ parser.print_help()
+ print >> sys.stderr, _('Unexpected arguments')
+ sys.exit(1)
+ return opts, args, parser
+
+
+
+def pending_requests(mlist):
+ # Must return a byte string
+ lcset = Utils.GetCharSet(mlist.preferred_language)
+ pending = []
+ first = True
+ requestsdb = config.db.get_list_requests(mlist)
+ for request in requestsdb.of_type(RequestType.subscription):
+ if first:
+ pending.append(_('Pending subscriptions:'))
+ first = False
+ key, data = requestsdb.get_request(request.id)
+ when = data['when']
+ addr = data['addr']
+ fullname = data['fullname']
+ passwd = data['passwd']
+ digest = data['digest']
+ lang = data['lang']
+ if fullname:
+ if isinstance(fullname, unicode):
+ fullname = fullname.encode(lcset, 'replace')
+ fullname = ' (%s)' % fullname
+ pending.append(' %s%s %s' % (addr, fullname, time.ctime(when)))
+ first = True
+ for request in requestsdb.of_type(RequestType.held_message):
+ if first:
+ pending.append(_('\nPending posts:'))
+ first = False
+ key, data = requestsdb.get_request(request.id)
+ when = data['when']
+ sender = data['sender']
+ subject = data['subject']
+ reason = data['reason']
+ text = data['text']
+ msgdata = data['msgdata']
+ subject = Utils.oneline(subject, lcset)
+ date = time.ctime(when)
+ reason = _(reason)
+ pending.append(_("""\
+From: $sender on $date
+Subject: $subject
+Cause: $reason"""))
+ pending.append('')
+ # Coerce all items in pending to a Unicode so we can join them
+ upending = []
+ charset = Utils.GetCharSet(mlist.preferred_language)
+ for s in pending:
+ if isinstance(s, unicode):
+ upending.append(s)
+ else:
+ upending.append(unicode(s, charset, 'replace'))
+ # Make sure that the text we return from here can be encoded to a byte
+ # string in the charset of the list's language. This could fail if for
+ # example, the request was pended while the list's language was French,
+ # but then it was changed to English before checkdbs ran.
+ text = NL.join(upending)
+ charset = Charset(Utils.GetCharSet(mlist.preferred_language))
+ incodec = charset.input_codec or 'ascii'
+ outcodec = charset.output_codec or 'ascii'
+ if isinstance(text, unicode):
+ return text.encode(outcodec, 'replace')
+ # Be sure this is a byte string encodeable in the list's charset
+ utext = unicode(text, incodec, 'replace')
+ return utext.encode(outcodec, 'replace')
+
+
+
+def auto_discard(mlist):
+ # Discard old held messages
+ discard_count = 0
+ expire = config.days(mlist.max_days_to_hold)
+ requestsdb = config.db.get_list_requests(mlist)
+ heldmsgs = list(requestsdb.of_type(RequestType.held_message))
+ if expire and heldmsgs:
+ for request in heldmsgs:
+ key, data = requestsdb.get_request(request.id)
+ if now - data['date'] > expire:
+ handle_request(mlist, request.id, config.DISCARD)
+ discard_count += 1
+ mlist.Save()
+ return discard_count
+
+
+
+def main():
+ opts, args, parser = parseargs()
+ config.load(opts.config)
+
+ i18n.set_language(config.DEFAULT_SERVER_LANGUAGE)
+
+ for name in config.list_manager.names:
+ # The list must be locked in order to open the requests database
+ mlist = MailList.MailList(name)
+ try:
+ count = config.db.requests.get_list_requests(mlist).count
+ # While we're at it, let's evict yesterday's autoresponse data
+ midnight_today = Utils.midnight()
+ evictions = []
+ for sender in mlist.hold_and_cmd_autoresponses.keys():
+ date, respcount = mlist.hold_and_cmd_autoresponses[sender]
+ if Utils.midnight(date) < midnight_today:
+ evictions.append(sender)
+ if evictions:
+ for sender in evictions:
+ del mlist.hold_and_cmd_autoresponses[sender]
+ # This is the only place we've changed the list's database
+ mlist.Save()
+ if count:
+ i18n.set_language(mlist.preferred_language)
+ realname = mlist.real_name
+ discarded = auto_discard(mlist)
+ if discarded:
+ count = count - discarded
+ text = _(
+ 'Notice: $discarded old request(s) automatically expired.\n\n')
+ else:
+ text = ''
+ if count:
+ text += Utils.maketext(
+ 'checkdbs.txt',
+ {'count' : count,
+ 'host_name': mlist.host_name,
+ 'adminDB' : mlist.GetScriptURL('admindb', absolute=1),
+ 'real_name': realname,
+ }, mlist=mlist)
+ text += '\n' + pending_requests(mlist)
+ subject = _('$count $realname moderator request(s) waiting')
+ else:
+ subject = _('$realname moderator request check result')
+ msg = Message.UserNotification(mlist.GetOwnerEmail(),
+ mlist.GetBouncesEmail(),
+ subject, text,
+ mlist.preferred_language)
+ msg.send(mlist, **{'tomoderators': True})
+ finally:
+ mlist.Unlock()
+
+
+
+if __name__ == '__main__':
+ main()