diff options
Diffstat (limited to 'bin/add_members')
-rwxr-xr-x | bin/add_members | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/bin/add_members b/bin/add_members new file mode 100755 index 00000000..ad4f43b8 --- /dev/null +++ b/bin/add_members @@ -0,0 +1,297 @@ +#! @PYTHON@ +# +# Copyright (C) 1998,1999,2000,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. +# +# argv[1] should be the name of the list. +# argv[2] should be the list of non-digested users. +# argv[3] should be the list of digested users. + +# Make sure that the list of email addresses doesn't contain any comments, +# like majordomo may throw in. For now, you just have to remove them manually. + +"""Add members to a list from the command line. + +Usage: + add_members [options] listname + +Options: + + --regular-members-file=file + -r file + A file containing addresses of the members to be added, one + address per line. This list of people become non-digest + members. If file is `-', read addresses from stdin. Note that + -n/--non-digest-members-file are deprecated synonyms for this option. + + --digest-members-file=file + -d=file + Similar to above, but these people become digest members. + + --changes-msg=<y|n> + -c <y|n> + Set whether or not to send the list members the `there's going to be + big changes to your list' message. defaults to no. + + --welcome-msg=<y|n> + -w <y|n> + Set whether or not to send the list members a welcome message, + overriding whatever the list's `send_welcome_msg' setting is. + + --admin-notify=<y|n> + -a <y|n> + Set whether or not to send the list administrators a notification on + the success/failure of these subscriptions, overriding whatever the + list's `admin_notify_mchanges' setting is. + + --help + -h + Print this help message and exit. + + listname + The name of the Mailman list you are adding members to. It must + already exist. + +You must supply at least one of -r and -d options. At most one of the +files can be `-'. +""" + +import sys +import os +import getopt +from cStringIO import StringIO + +import paths +# Import this /after/ paths so that the sys.path is properly hacked +from email.Utils import parseaddr + +from Mailman import MailList +from Mailman import Utils +from Mailman import Message +from Mailman import Errors +from Mailman import mm_cfg +from Mailman import i18n + +_ = i18n._ + + + +def usage(status, msg=''): + if status: + fd = sys.stderr + else: + fd = sys.stdout + print >> fd, _(__doc__) + if msg: + print >> fd, msg + sys.exit(status) + + + +def readfile(filename): + if filename == '-': + fp = sys.stdin + closep = 0 + else: + fp = open(filename) + closep = 1 + # strip all the lines of whitespace and discard blank lines + lines = filter(None, [line.strip() for line in fp.readlines()]) + if closep: + fp.close() + return lines + + + +def SendExplanation(mlist, users): + listname = mlist.real_name + listhost = mlist.host_name + d = {'listname' : listname, + 'listhost' : listhost, + 'listaddr' : mlist.GetListEmail(), + 'listinfo_url': mlist.GetScriptURL('listinfo', absolute=1), + 'requestaddr' : mlist.GetRequestEmail(), + 'adminaddr' : mlist.GetOwnerEmail(), + 'version' : mm_cfg.VERSION, + } + otrans = i18n.get_translation() + i18n.set_language(mlist.preferred_language) + try: + text = Utils.maketext('convert.txt', d) + subject = _('Big change in %(listname)s@%(listhost)s mailing list') + msg = Message.UserNotification(users, mlist.GetBouncesEmail(), + subject, text, + mlist.preferred_language) + finally: + i18n.set_translation(otrans) + msg.send(mlist) + + + +class Tee: + def __init__(self, outfp): + self.__outfp = outfp + + def write(self, msg): + sys.stdout.write(msg) + self.__outfp.write(msg) + + +class UserDesc: pass + + + +def addall(mlist, members, digest, ack, outfp): + tee = Tee(outfp) + for member in members: + userdesc = UserDesc() + userdesc.fullname, userdesc.address = parseaddr(member) + userdesc.digest = digest + + try: + mlist.ApprovedAddMember(userdesc, ack, 0) + except Errors.MMAlreadyAMember: + print >> tee, _('Already a member: %(member)s') + except Errors.MMBadEmailError: + if userdesc.address == '': + print >> tee, _('Bad/Invalid email address: blank line') + else: + print >> tee, _('Bad/Invalid email address: %(member)s') + except Errors.MMHostileAddress: + print >> tee, _('Hostile address (illegal characters): %(member)s') + else: + print >> tee, _('Subscribed: %(member)s') + + + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], + 'a:n:r:d:c:w:h', + ['admin-notify=', + 'regular-members-file=', + 'non-digest-members-file=', + 'digest-members-file=', + 'changes-msg=', + 'welcome-msg=', + 'help']) + except getopt.error, msg: + usage(1, msg) + + if len(args) <> 1: + usage(1) + + listname = args[0].lower().strip() + nfile = None + dfile = None + send_changes_msg = 0 + send_welcome_msg = None + admin_notif = None + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-d', '--digest-members-file'): + dfile = arg + # Deprecate -/--non-digest-members-file or consistency with + # list_members + elif opt in ('-r', '--regular-members-file'): + nfile = arg + elif opt in ('-n', '--non-digest-members-file'): + nfile = arg + # I don't think we need to use the warnings module here. + print >> sys.stderr, 'option', opt, \ + 'is deprecated, use -r/--regular-members-file' + elif opt in ('-c', '--changes-msg'): + if arg.lower()[0] == 'y': + send_changes_msg = 1 + elif arg.lower()[0] == 'n': + send_changes_msg = 0 + else: + usage(1, _('Bad argument to -c/--changes-msg: %(arg)s')) + elif opt in ('-w', '--welcome-msg'): + if arg.lower()[0] == 'y': + send_welcome_msg = 1 + elif arg.lower()[0] == 'n': + send_welcome_msg = 0 + else: + usage(1, _('Bad argument to -w/--welcome-msg: %(arg)s')) + elif opt in ('-a', '--admin-notify'): + if arg.lower()[0] == 'y': + admin_notif = 1 + elif arg.lower()[0] == 'n': + admin_notif = 0 + else: + usage(1, _('Bad argument to -a/--admin-notify: %(arg)s')) + + if dfile is None and nfile is None: + usage(1) + + if dfile == "-" and nfile == "-": + usage(1, _('Cannot read both digest and normal members ' + 'from standard input.')) + + try: + mlist = MailList.MailList(listname) + except Errors.MMUnknownListError: + usage(1, _('No such list: %(listname)s')) + + # Set up defaults + if send_welcome_msg is None: + send_welcome_msg = mlist.send_welcome_msg + if admin_notif is None: + admin_notif = mlist.admin_notify_mchanges + + otrans = i18n.get_translation() + # Read the regular and digest member files + try: + dmembers = [] + if dfile: + dmembers = readfile(dfile) + + nmembers = [] + if nfile: + nmembers = readfile(nfile) + + if not dmembers and not nmembers: + usage(0, _('Nothing to do.')) + + s = StringIO() + i18n.set_language(mlist.preferred_language) + if nmembers: + addall(mlist, nmembers, 0, send_welcome_msg, s) + + if dmembers: + addall(mlist, dmembers, 1, send_welcome_msg, s) + + if admin_notif: + realname = mlist.real_name + subject = _('%(realname)s subscription notification') + msg = Message.UserNotification( + mlist.owner, Utils.get_site_email(), subject, s.getvalue(), + mlist.preferred_language) + msg.send(mlist) + + if send_changes_msg: + SendExplanation(mlist, nmembers + dmembers) + + mlist.Save() + finally: + mlist.Unlock() + i18n.set_translation(otrans) + + +if __name__ == '__main__': + main() |