#! /usr/bin/env python # # Copyright (C) 1998 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. """Send password reminders for all lists to all users. Any arguments are taken as a list of addresses that become the focus - only the subscribers on the list are attended to, all other subscribers are ignored. In addition, if any addresses are specified, a line is printed for each list where that address is found. (Otherwise operation is silent.) We accumulate users and their passwords, and use the last list to send a single message to each user with their complete collection of passwords, rather than sending a single message for each password.""" # This puppy should probably do lots of logging. import sys, os, string, time, errno import paths from Mailman import MailList from Mailman import mm_cfg from Mailman import Utils # Work around known problems with some RedHat cron daemons import signal signal.signal(signal.SIGCHLD, signal.SIG_DFL) # Give time for the delivery process-forks to clear every so often, to # avoid saturation of the process table. Set zero or negative for no # pauses. PAUSE_FREQUENCY = 10 def MailAllPasswords(list, users): """Send each user their complete list of passwords. The list can be any random one - it is only used for the message delivery mechanism.""" subj = '%s maillist memberships reminder\n' % list.host_name count = PAUSE_FREQUENCY for user, data in users.items(): table = [] for l, p, u in data: if len(l) > 9: table.append("%s\n %-10s\n%s\n" % (l, p, u)) else: table.append("%-10s %-10s\n%s\n" % (l, p, u)) header = ("%-10s %-10s\n%-10s %-10s" % ("List", "Password // URL", "----", "--------")) text = Utils.maketext( 'cronpass.txt', {'hostname': list.host_name, 'user' : user, 'one_list': l, }) # add this to the end so it doesn't get wrapped/filled text = text + header + '\n' + string.join(table, '\n') list.SendTextToUser(subject = subj, recipient = user, text = text, sender = mm_cfg.MAILMAN_OWNER, add_headers = ["X-No-Archive: yes", "Precedence: bulk"]) count = count - 1 if count == 0: # The pause that refreshes. waitall() count = PAUSE_FREQUENCY def main(args): """Consolidate all the list/url/password info for each user, so we send the user a single message with the info for all their lists on this site.""" list = None users = {} # user: (listname, password, url) # Constrain to specified users, if any. confined_to = args[1:] a_public_list = None for name in Utils.list_names(): list = MailList.MailList(name, lock = 0) if not a_public_list and list.advertised: a_public_list = list list_name = list.real_name umbrella_list = list.umbrella_list if not list.send_reminders: continue for user, password in list.passwords.items(): if confined_to: if user not in confined_to: continue else: # We're a bit verbose when operating "confined_to": print "%s in %s" % (user, list.real_name) url = list.GetAbsoluteOptionsURL(user) recipient = list.GetMemberAdminEmail(user) if users.has_key(recipient): users[recipient].append(list_name, password, url) else: users[recipient] = [(list_name, password, url)] if list: MailAllPasswords(a_public_list or list, users) def waitall(): """Return only when there are no forked subprocesses running.""" try: while 1: os.wait() except os.error, val: if val[0] == errno.ECHILD: # errno.ECHILD: "No child processes" return else: raise val, None, sys.exc_info()[2] if __name__ == "__main__": main(sys.argv)