diff options
| -rwxr-xr-x | Mailman/bin/add_members.py | 216 | ||||
| -rw-r--r-- | bin/Makefile.in | 7 | ||||
| -rwxr-xr-x | bin/add_members | 255 | ||||
| -rwxr-xr-x | configure | 11 | ||||
| -rw-r--r-- | configure.in | 3 |
5 files changed, 226 insertions, 266 deletions
diff --git a/Mailman/bin/add_members.py b/Mailman/bin/add_members.py new file mode 100755 index 000000000..0adcda518 --- /dev/null +++ b/Mailman/bin/add_members.py @@ -0,0 +1,216 @@ +# Copyright (C) 1998-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. + +import os +import sys +import optparse + +from cStringIO import StringIO +from email.Utils import parseaddr + +from Mailman import Errors +from Mailman import MailList +from Mailman import Message +from Mailman import Utils +from Mailman import i18n +from Mailman import mm_cfg + +_ = i18n._ +__i18n_templates__ = True + + + +def parseargs(): + parser = optparse.OptionParser(version=mm_cfg.MAILMAN_VERSION, + usage=_("""\ +%prog [options] listname + +Add members to a list. 'listname' is the name of the Mailman list you are +adding members to; the list must already exist. + +You must supply at least one of -r and -d options. At most one of the +files can be '-'. +""")) + parser.add_option('-r', '--regular-members-file', + type='string', dest='regular', help=_("""\ +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.""")) + parser.add_option('-d', '--digest-members-file', + type='string', dest='digest', help=_("""\ +Similar to -r, but these people become digest members.""")) + parser.add_option('-w', '--welcome-msg', + type='string', metavar='<y|n>', help=_("""\ +Set whether or not to send the list members a welcome message, overriding +whatever the list's 'send_welcome_msg' setting is.""")) + parser.add_option('-a', '--admin-notify', + type='string', metavar='<y|n>', help=_("""\ +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.""")) + opts, args = parser.parse_args() + if not args: + parser.print_help() + print >> sys.stderr, _('Missing listname') + sys.exit(1) + if len(args) > 1: + parser.print_help() + print >> sys.stderr, _('Unexpected arguments') + sys.exit(1) + if opts.welcome_msg is not None: + ch = opts.welcome_msg[0].lower() + if ch == 'y': + opts.welcome_msg = True + elif ch == 'n': + opts.welcome_msg = False + else: + parser.print_help() + print >> sys.stderr, _('Illegal value for -w: $opts.welcome_msg') + sys.exit(1) + if opts.admin_notify is not None: + ch = opts.admin_notify[0].lower() + if ch == 'y': + opts.admin_notify = True + elif ch == 'n': + opts.admin_notify = False + else: + parser.print_help() + print >> sys.stderr, _('Illegal value for -a: $opts.admin_notify') + sys.exit(1) + if opts.regular is None and opts.digest is None: + parser.print_help() + print >> sys.stderr, _('At least one of -r or -d is required') + sys.exit(1) + if opts.regular == '-' and opts.digest == '-': + parser.print_help() + print >> sys.stderr, _("-r and -d cannot both be '-'") + sys.exit(1) + return parser, opts, args + + + +def readfile(filename): + if filename == '-': + fp = sys.stdin + else: + fp = open(filename) + # Strip all the lines of whitespace and discard blank lines + try: + return [line.strip() for line in fp if line] + finally: + if fp is not sys.stdin: + fp.close() + + + +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') + except Errors.MMBadEmailError: + if userdesc.address == '': + print >> tee, _('Bad/Invalid email address: blank line') + else: + print >> tee, _('Bad/Invalid email address: $member') + except Errors.MMHostileAddress: + print >> tee, _('Hostile address (illegal characters): $member') + else: + print >> tee, _('Subscribed: $member') + + + +def main(): + parser, opts, args = parseargs() + + listname = args[0].lower().strip() + try: + mlist = MailList.MailList(listname) + except Errors.MMUnknownListError: + parser.print_help() + print >> sys.stderr, _('No such list: $listname') + sys.exit(1) + + # Set up defaults + if opts.welcome_msg is None: + send_welcome_msg = mlist.send_welcome_msg + else: + send_welcome_msg = opts.welcome_msg + if opts.admin_notify is None: + admin_notify = mlist.admin_notify_mchanges + else: + admin_notify = opts.admin_notify + + otrans = i18n.get_translation() + # Read the regular and digest member files + try: + if opts.digest: + dmembers = readfile(opts.digest) + else: + dmembers = [] + if opts.regular: + nmembers = readfile(opts.regular) + else: + nmembers = [] + + if not dmembers and not nmembers: + print _('Nothing to do.') + sys.exit(0) + + s = StringIO() + i18n.set_language(mlist.preferred_language) + if nmembers: + addall(mlist, nmembers, False, send_welcome_msg, s) + + if dmembers: + addall(mlist, dmembers, True, send_welcome_msg, s) + + if admin_notify: + subject = _('$mlist.real_name subscription notification') + msg = Message.UserNotification( + mlist.owner, Utils.get_site_email(), subject, s.getvalue(), + mlist.preferred_language) + msg.send(mlist) + + mlist.Save() + finally: + mlist.Unlock() + i18n.set_translation(otrans) + + +if __name__ == '__main__': + main() diff --git a/bin/Makefile.in b/bin/Makefile.in index 46ae3f09a..dbf6bc295 100644 --- a/bin/Makefile.in +++ b/bin/Makefile.in @@ -44,7 +44,7 @@ SCRIPTSDIR= $(prefix)/bin SHELL= /bin/sh -SCRIPTS= mmshell add_members \ +SCRIPTS= mmshell \ remove_members clone_member update \ sync_members check_db withlist check_perms find_member \ config_list dumpdb cleanarch \ @@ -53,8 +53,9 @@ SCRIPTS= mmshell add_members \ msgfmt.py discard \ reset_pw.py templ2pot.py po2templ.py -LN_SCRIPTS= arch change_pw inject list_lists list_members list_owners \ - mmsitepass newlist rmlist show_qfiles unshunt version +LN_SCRIPTS= add_members arch change_pw inject list_lists list_members \ + list_owners mmsitepass newlist rmlist show_qfiles unshunt \ + version BUILDDIR= ../build/bin diff --git a/bin/add_members b/bin/add_members deleted file mode 100755 index fdc3f02b8..000000000 --- a/bin/add_members +++ /dev/null @@ -1,255 +0,0 @@ -#! @PYTHON@ -# -# Copyright (C) 1998-2003 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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. - - --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 - - - -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:w:h', - ['admin-notify=', - 'regular-members-file=', - 'non-digest-members-file=', - 'digest-members-file=', - '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_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 ('-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) - - mlist.Save() - finally: - mlist.Unlock() - i18n.set_translation(otrans) - - -if __name__ == '__main__': - main() @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 7890 . +# From configure.in Revision: 7891 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59. # @@ -721,13 +721,13 @@ echo X"$0" | /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then + if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi -if test ! -r $srcdir/$ac_unique_file; then +if test ! -r "$srcdir/$ac_unique_file"; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } @@ -736,7 +736,7 @@ if test ! -r $srcdir/$ac_unique_file; then { (exit 1); exit 1; }; } fi fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || +(cd $srcdir && test -r "./$ac_unique_file") 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` @@ -4276,8 +4276,7 @@ done -SCRIPTS="build/bin/add_members:bin/add_members \ -build/bin/check_db:bin/check_db \ +SCRIPTS="build/bin/check_db:bin/check_db \ build/bin/check_perms:bin/check_perms \ build/bin/cleanarch:bin/cleanarch \ build/bin/clone_member:bin/clone_member \ diff --git a/configure.in b/configure.in index 68b33ffb9..78cc5e0a6 100644 --- a/configure.in +++ b/configure.in @@ -15,7 +15,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. dnl Process this file with autoconf to produce a configure script. -AC_REVISION($Revision: 7891 $) +AC_REVISION($Revision: 7892 $) AC_PREREQ(2.0) AC_INIT(src/common.h) @@ -594,7 +594,6 @@ AC_CHECK_FUNCS(vsnprintf) dnl Expand PYTHON path in the scripts, output into build/scriptname AC_DEFUN(MM_SCRIPTS, [dnl -bin/add_members \ bin/check_db \ bin/check_perms \ bin/cleanarch \ |
