[Mailman-Developers] Different approach to monthly password reminders

Dan Mick Dan Mick <Dan.Mick@West.Sun.COM>
Thu, 10 Aug 2000 23:23:14 -0700 (PDT)


Here is a hacked up 'mailpasswds' program that will

1) send one message per user per list
2) make that message contain only that list's password
3) make the message originate from the list's admin address
4) include the listname in the Subject header

This seems to be along the lines of what some people expect from
the monthly password reminders (instead of what they get).

YMMV, and I haven't tested this with every possible list config.
I also haven't yet changed any comments.

If you'd like to experiment without actually sending messages, remove
the '#' from '# print msg' (at the end of the function
'mail_passwords') and put a '# ' before
HandlerAPI.DeliverToUser(mlist, msg) right below it...i.e. switch

        # print msg
        HandlerAPI.DeliverToUser(mlist, msg)      
to
        print msg
        # HandlerAPI.DeliverToUser(mlist, msg)

Then when you run 'python mailpasswds.new', you'll get all the
messages it would have sent printed on stdout instead of actually
sending the mail.

Here's mailpasswds.new:

#! /usr/bin/env python
#
# Copyright (C) 1998,1999,2000 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.

If mm_cfg.VIRTUAL_HOST_OVERVIEW is true, we further group users by the virtual
host the mailing lists are assigned to.  This is so that virtual domains are
treated like real separate machines.

"""

# This puppy should probably do lots of logging.
import sys
import os
import string
import errno

import paths
from Mailman import mm_cfg
from Mailman import MailList
from Mailman import Utils
from Mailman import Message
from Mailman.Handlers import HandlerAPI

# Work around known problems with some RedHat cron daemons
import signal
signal.signal(signal.SIGCHLD, signal.SIG_DFL)



def mail_passwords(mlist, users, host):
    """Send each user their complete list of passwords.

    The list can be any random one - it is only used for the message
    delivery mechanism.  Users are grouped by virtual host.
    """
    mailman_owner = mm_cfg.MAILMAN_OWNER
    for addr, data in users.items():
        table = []
        for l, r, p, u in data:
            if len(l) > 39:
                table.append("%s\n           %-10s\n%s\n" % (l, p, u))
            else:
                table.append("%-40s %-10s\n%s\n" % (l, p, u))
        header = ("%-40s %-10s\n%-40s %-10s"
                  % ("List", "Password // URL", "----", "--------"))
        text = Utils.maketext(
            'cronpass.txt',
            {'hostname': host,
             'useraddr': addr,
             'exreq'   : r,
             'owner'   : mailman_owner,
             })
        # add this to the end so it doesn't get wrapped/filled
        text = text + header + '\n' + string.join(table, '\n')
       	subj = l + " password reminder"
        msg = Message.UserNotification(addr, mlist.GetAdminEmail(), subj, text)
        msg['X-No-Archive'] = 'yes'
    	# print msg 
        HandlerAPI.DeliverToUser(mlist, msg)



def main():
    """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.
    """
    # constrain to specified lists, if any
    confined_to = sys.argv[1:]
    # Group lists by the assigned virtual host, if
    # mm_cfg.VIRTUAL_HOST_OVERVIEW is true.  Otherwise, there's only one key
    # in this dictionary: mm_cfg.DEFAULT_HOST_NAME.  Each entry in this
    # dictionary is a dictionary of user email addresses
    hosts = {}
    for listname in Utils.list_names():
        if confined_to and listname not in confined_to:
            continue
##        else:
##            print 'Processing list:', listname
        mlist = MailList.MailList(listname, lock=0)
        if not mlist.send_reminders:
            continue
        listaddr = mlist.GetListEmail()
        listreq = mlist.GetRequestEmail()
        umbrella = mlist.umbrella_list
        # get host information
        if mm_cfg.VIRTUAL_HOST_OVERVIEW:
            host = mlist.host_name
        else:
            host = mm_cfg.DEFAULT_HOST_NAME
        #
        # each entry in this dictionary is a list of tuples of the following
        # form: (listaddr, listreq, password, url)
        users = {}
        for addr, passwd in mlist.passwords.items():
            url = mlist.GetOptionsURL(addr, absolute=1)
            realaddr = mlist.GetUserSubscribedAddress(addr)
            if not realaddr:
                continue
            recip = mlist.GetMemberAdminEmail(realaddr)
            userinfo = (listaddr, listreq, passwd, url)
            infolist = users.get(recip, [])
            infolist.append(userinfo)
            users[recip] = infolist
        mail_passwords(mlist, users, host)



if __name__ == '__main__':
    main()