diff options
Diffstat (limited to 'cron/disabled')
-rw-r--r-- | cron/disabled | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/cron/disabled b/cron/disabled new file mode 100644 index 00000000..dcf05f25 --- /dev/null +++ b/cron/disabled @@ -0,0 +1,209 @@ +#! @PYTHON@ +# +# Copyright (C) 2001,2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +"""Process disabled members, recommended once per day. + +This script cruises through every mailing list looking for members whose +delivery is disabled. If they have been disabled due to bounces, they will +receive another notification, or they may be removed if they've received the +maximum number of notifications. + +Use the --byadmin, --byuser, and --unknown flags to also send notifications to +members whose accounts have been disabled for those reasons. Use --all to +send the notification to all disabled members. + +Usage: %(PROGRAM)s [options] + +Options: + -h / --help + Print this message and exit. + + -o / --byadmin + Also send notifications to any member disabled by the list + owner/administrator. + + -m / --byuser + Also send notifications to any member disabled by themselves. + + -u / --unknown + Also send notifications to any member disabled for unknown reasons + (usually a legacy disabled address). + + -b / --notbybounce + Don't send notifications to members disabled because of bounces (the + default is to notify bounce disabled members). + + -a / --all + Send notifications to all disabled members. + + -f / --force + Send notifications to disabled members even if they're not due a new + notification yet. + + -l listname + --listname=listname + Process only the given list, otherwise do all lists. +""" + +import sys +import time +import getopt + +import paths +# mm_cfg must be imported before the other modules, due to the side-effect of +# it hacking sys.paths to include site-packages. Without this, running this +# script from cron with python -S will fail. +from Mailman import mm_cfg +from Mailman import Utils +from Mailman import MailList +from Mailman import Pending +from Mailman import MemberAdaptor +from Mailman.Bouncer import _BounceInfo +from Mailman.Logging.Syslog import syslog +from Mailman.i18n import _ + +# Work around known problems with some RedHat cron daemons +import signal +signal.signal(signal.SIGCHLD, signal.SIG_DFL) + +PROGRAM = sys.argv[0] + + + +def usage(code, msg=''): + if code: + fd = sys.stderr + else: + fd = sys.stdout + print >> fd, _(__doc__) + if msg: + print >> fd, msg + sys.exit(code) + + + +def main(): + try: + opts, args = getopt.getopt( + sys.argv[1:], 'hl:omubaf', + ['byadmin', 'byuser', 'unknown', 'notbybounce', 'all', + 'listname=', 'help', 'force']) + except getopt.error, msg: + usage(1, msg) + + if args: + usage(1) + + force = 0 + listnames = [] + who = [MemberAdaptor.BYBOUNCE] + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-l', '--list'): + listnames.append(arg) + elif opt in ('-o', '--byadmin'): + who.append(MemberAdaptor.BYADMIN) + elif opt in ('-m', '--byuser'): + who.append(MemberAdaptor.BYUSER) + elif opt in ('-u', '--unknown'): + who.append(MemberAdaptor.UNKNOWN) + elif opt in ('-b', '--notbybounce'): + try: + who.remove(MemberAdaptor.BYBOUNCE) + except ValueError: + # Already removed + pass + elif opt in ('-a', '--all'): + who = [MemberAdaptor.BYBOUNCE, MemberAdaptor.BYADMIN, + MemberAdaptor.BYUSER, MemberAdaptor.UNKNOWN] + elif opt in ('-f', '--force'): + force = 1 + + who = tuple(who) + + if not listnames: + listnames = Utils.list_names() + + msg = _('[disabled by periodic sweep and cull, no message available]') + today = time.mktime(time.localtime()[:3] + (0,) * 6) + for listname in listnames: + # List of members to notify + notify = [] + mlist = MailList.MailList(listname) + try: + interval = mlist.bounce_you_are_disabled_warnings_interval + # Find all the members who are currently bouncing and see if + # they've reached the disable threshold but haven't yet been + # disabled. This is a sweep through the membership catching + # situations where they've bounced a bunch, then the list admin + # lowered the threshold, but we haven't (yet) seen more bounces + # from the member. Note: we won't worry about stale information + # or anything else since the normal bounce processing code will + # handle that. + disables = [] + for member in mlist.getBouncingMembers(): + if mlist.getDeliveryStatus(member) <> MemberAdaptor.ENABLED: + continue + info = mlist.getBounceInfo(member) + if info.score >= mlist.bounce_score_threshold: + disables.append((member, info)) + if disables: + for member, info in disables: + mlist.disableBouncingMember(member, info, msg) + # Go through all the members who have delivery disabled, and find + # those that are due to have another notification. If they are + # disabled for another reason than bouncing, and we're processing + # them (because of the command line switch) then they won't have a + # bounce info record. We can piggyback on that for all disable + # purposes. + members = mlist.getDeliveryStatusMembers(who) + for member in members: + info = mlist.getBounceInfo(member) + if not info: + # See if they are bounce disabled, or disabled for some + # other reason. + status = mlist.getDeliveryStatus(member) + if status == MemberAdaptor.BYBOUNCE: + syslog( + 'error', + '%s disabled BYBOUNCE lacks bounce info, list: %s', + member, mlist.internal_name()) + continue + info = _BounceInfo( + member, 0, today, + mlist.bounce_you_are_disabled_warnings, + Pending.new(Pending.RE_ENABLE, mlist.internal_name(), + member)) + mlist.setBounceInfo(member, info) + lastnotice = time.mktime(info.lastnotice + (0,) * 6) + if force or today >= lastnotice + interval: + notify.append(member) + # Now, send notifications to anyone who is due + for member in notify: + syslog('bounce', 'Notifying disabled member %s for list: %s', + member, mlist.internal_name()) + mlist.sendNextNotification(member) + mlist.Save() + finally: + mlist.Unlock() + + + +if __name__ == '__main__': + main() |