--- cron/mailpasswds 2009-05-21 12:40:18.359375000 -0700 +++ /cygdrive/f/test-mailman/cron/mailpasswds 2009-08-05 17:29:29.000000000 -0700 @@ -1,6 +1,6 @@ #! @PYTHON@ # -# Copyright (C) 1998-2003 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2009 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 @@ -109,118 +109,65 @@ if listnames is None: listnames = Utils.list_names() - # This is the list that all the reminders will look like they come from, - # but with the host name coerced to the virtual host we're processing. - try: - sitelist = MailList.MailList(mm_cfg.MAILMAN_SITE_LIST, lock=0) - except Errors.MMUnknownListError: - # Do it this way for I18n's _() - sitelistname = mm_cfg.MAILMAN_SITE_LIST - print >> sys.stderr, _('Site list is missing: %(sitelistname)s') - syslog('error', 'Site list is missing: %s', mm_cfg.MAILMAN_SITE_LIST) - sys.exit(1) - - # Group lists by host_name if VIRTUAL_HOST_OVERVIEW is true, otherwise - # there's only one key in this dictionary: mm_cfg.DEFAULT_EMAIL_HOST. The - # values are lists of the unlocked MailList instances. - byhost = {} for listname in listnames: mlist = MailList.MailList(listname, lock=0) if not mlist.send_reminders: continue - if mm_cfg.VIRTUAL_HOST_OVERVIEW: - host = mlist.host_name - else: - # See the note in Defaults.py concerning DEFAULT_HOST_NAME - # vs. DEFAULT_EMAIL_HOST. - host = mm_cfg.DEFAULT_HOST_NAME or mm_cfg.DEFAULT_EMAIL_HOST - byhost.setdefault(host, []).append(mlist) - - # Now for each virtual host, collate the user information. Each user - # entry has the form (listaddr, password, optionsurl) - for host in byhost.keys(): - # Site owner is `mailman@dom.ain' + host = mlist.host_name userinfo = {} - for mlist in byhost[host]: - listaddr = mlist.GetListEmail() - for member in mlist.getMembers(): - # The user may have disabled reminders for this list - if mlist.getMemberOption(member, - mm_cfg.SuppressPasswordReminder): - continue - # Group by the lower-cased address, since Mailman always - # treates person@dom.ain the same as PERSON@dom.ain. - try: - password = mlist.getMemberPassword(member) - except Errors.NotAMemberError: - # Here's a member with no passwords, which I think was - # possible in older versions of Mailman. Log this and - # move on. - syslog('error', 'password-less member %s for list %s', - member, mlist.internal_name()) - continue - optionsurl = mlist.GetOptionsURL(member) - lang = mlist.getMemberLanguage(member) - info = (listaddr, password, optionsurl, lang) - userinfo.setdefault(member, []).append(info) - # Now that we've collected user information for this host, send each + listaddr = mlist.GetListEmail() + for member in mlist.getMembers(): + # The user may have disabled reminders for this list + if mlist.getMemberOption(member, + mm_cfg.SuppressPasswordReminder): + continue + # Group by the lower-cased address, since Mailman always + # treates person@dom.ain the same as PERSON@dom.ain. + try: + password = mlist.getMemberPassword(member) + except Errors.NotAMemberError: + # Here's a member with no passwords, which I think was + # possible in older versions of Mailman. Log this and + # move on. + syslog('error', 'password-less member %s for list %s', + member, mlist.internal_name()) + continue + optionsurl = mlist.GetOptionsURL(member) + lang = mlist.getMemberLanguage(member) + userinfo[member] = (listaddr, password, optionsurl, lang) + # Now that we've collected user information for this list, send each # user the password reminder. for addr in userinfo.keys(): - # If the person is on more than one list, it is possible that they - # have different preferred languages, and there's no good way to - # know which one they want their password reminder in. Pick the - # most popular, and break the tie randomly. - # - # Also, we need an example -request address for cronpass.txt and - # again, there's no clear winner. Just take the first one in this - # case. - table = [] - langs = {} - for listaddr, password, optionsurl, lang in userinfo[addr]: - langs[lang] = langs.get(lang, 0) + 1 - # If the list address is really long, break it across two - # lines. - if len(listaddr) > 39: - fmt = '%s\n %-10s\n%s\n' - else: - fmt = '%-40s %-10s\n%s\n' - table.append(fmt % (listaddr, password, optionsurl)) - # Figure out which language to use - langcnt = 0 - poplang = None - for lang, cnt in langs.items(): - if cnt > langcnt: - poplang = lang - langcnt = cnt - enc = Utils.GetCharSet(poplang) + listaddr, password, optionsurl, lang = userinfo[addr] + # If the list address is really long, break it across two + # lines. + fmt = 'List: %s\nPassword: %s\nURL: %s\n' + table = fmt % (listaddr, password, optionsurl) + enc = Utils.GetCharSet(lang) # Now we're finally ready to send the email! - siteowner = Utils.get_site_email(host, 'owner') - sitereq = Utils.get_site_email(host, 'request') - sitebounce = Utils.get_site_email(host, 'bounces') + listowner = mlist.GetOwnerEmail() + listreq = mlist.GetRequestEmail() + listbounce = mlist.GetBouncesEmail() text = Utils.maketext( 'cronpass.txt', {'hostname': host, 'useraddr': addr, - 'exreq' : sitereq, - 'owner' : siteowner, - }, lang=poplang) + 'exreq' : listreq, + 'owner' : listowner, + }, lang=lang) # Coerce everything to Unicode text = tounicode(text, enc) - table = [tounicode(_t, enc) for _t in table] + table = tounicode(table, enc) # Translate the message and headers to user's suggested lang otrans = i18n.get_translation() try: - i18n.set_language(poplang) - # Craft table header after language was set - header = '%-40s %-10s\n%-40s %-10s' % ( - _('List'), _('Password // URL'), '----', '--------') - header = tounicode(header, enc) + i18n.set_language(lang) # Add the table to the end so it doesn't get wrapped/filled - text += (header + '\n' + NL.join(table)) + text += table msg = Message.UserNotification( - addr, siteowner, + addr, listowner, _('%(host)s mailing list memberships reminder'), - text.encode(enc, 'replace'), poplang) + text.encode(enc, 'replace'), lang) # Note that text must be encoded into 'enc' because unicode # cause error within email module in some language (Japanese). finally: @@ -230,8 +177,7 @@ # list, but we also want to be sure that the apparent host name is # the current virtual host. Look in CookHeaders.py for why this # trick works. Blarg. - msg.send(sitelist, **{'errorsto': sitebounce, - '_nolist' : 1, + msg.send(mlist, **{'errorsto': listbounce, 'verp' : mm_cfg.VERP_PASSWORD_REMINDERS, })