summaryrefslogtreecommitdiff
path: root/Mailman/bin
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/bin')
-rw-r--r--Mailman/bin/Makefile.in71
-rw-r--r--Mailman/bin/__init__.py0
-rwxr-xr-xMailman/bin/newlist.py229
-rwxr-xr-xMailman/bin/rmlist.py153
4 files changed, 453 insertions, 0 deletions
diff --git a/Mailman/bin/Makefile.in b/Mailman/bin/Makefile.in
new file mode 100644
index 000000000..1ba409155
--- /dev/null
+++ b/Mailman/bin/Makefile.in
@@ -0,0 +1,71 @@
+# 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.
+
+# NOTE: Makefile.in is converted into Makefile by the configure script
+# in the parent directory. Once configure has run, you can recreate
+# the Makefile by running just config.status.
+
+# Variables set by configure
+
+VPATH= @srcdir@
+srcdir= @srcdir@
+bindir= @bindir@
+prefix= @prefix@
+exec_prefix= @exec_prefix@
+DESTDIR=
+
+CC= @CC@
+CHMOD= @CHMOD@
+INSTALL= @INSTALL@
+
+DEFS= @DEFS@
+
+# Customizable but not set by configure
+
+OPT= @OPT@
+CFLAGS= $(OPT) $(DEFS)
+PACKAGEDIR= $(prefix)/Mailman/bin
+SHELL= /bin/sh
+
+MODULES= *.py
+
+# Modes for directories and executables created by the install
+# process. Default to group-writable directories but
+# user-only-writable for executables.
+DIRMODE= 775
+EXEMODE= 755
+FILEMODE= 644
+INSTALL_PROGRAM=$(INSTALL) -m $(EXEMODE)
+
+
+# Rules
+
+all:
+
+install:
+ for f in $(MODULES); \
+ do \
+ $(INSTALL) -m $(FILEMODE) $(srcdir)/$$f $(DESTDIR)$(PACKAGEDIR); \
+ done
+
+finish:
+
+clean:
+
+distclean:
+ -rm *.pyc
+ -rm Makefile
diff --git a/Mailman/bin/__init__.py b/Mailman/bin/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Mailman/bin/__init__.py
diff --git a/Mailman/bin/newlist.py b/Mailman/bin/newlist.py
new file mode 100755
index 000000000..79b584eee
--- /dev/null
+++ b/Mailman/bin/newlist.py
@@ -0,0 +1,229 @@
+# 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 sha
+import sys
+import getpass
+import optparse
+
+from Mailman import Errors
+from Mailman import MailList
+from Mailman import Message
+from Mailman import Utils
+from Mailman import Version
+from Mailman import i18n
+from Mailman import mm_cfg
+
+_ = i18n._
+
+
+
+def parseargs():
+ parser = optparse.OptionParser(version='GNU Mailman ' + Version.VERSION,
+ usage=_("""\
+Create a new, unpopulated mailing list.
+
+Usage: %%prog [options] [listname [listadmin-addr [admin-password]]]
+
+You can specify as many of the arguments as you want on the command line:
+you will be prompted for the missing ones.
+
+Every Mailman list has two parameters which define the default host name for
+outgoing email, and the default URL for all web interfaces. When you
+configured Mailman, certain defaults were calculated, but if you are running
+multiple virtual Mailman sites, then the defaults may not be appropriate for
+the list you are creating.
+
+You also specify the domain to create your new list in by typing the command
+like so:
+
+ newlist --urlhost=www.mydom.ain mylist
+
+where `www.mydom.ain' should be the base hostname for the URL to this virtual
+hosts's lists. E.g. with this setting people will view the general list
+overviews at http://www.mydom.ain/mailman/listinfo. Also, www.mydom.ain
+should be a key in the VIRTUAL_HOSTS mapping in mm_cfg.py/Defaults.py if
+the email hostname to be automatically determined.
+
+If you want the email hostname to be different from the one looked up by the
+VIRTUAL_HOSTS or if urlhost is not registered in VIRTUAL_HOSTS, you can specify
+`emailhost' like so:
+
+ newlist --urlhost=www.mydom.ain --emailhost=mydom.ain mylist
+
+where `mydom.ain' is the mail domain name. If you don't specify emailhost but
+urlhost is not in the virtual host list, then mm_cfg.DEFAULT_EMAIL_HOST will
+be used for the email interface.
+
+For backward compatibility, you can also specify the domain to create your
+new list in by spelling the listname like so:
+
+ mylist@www.mydom.ain
+
+where www.mydom.ain is used for `urlhost' but it will also be used for
+`emailhost' if it is not found in the virtual host table. Note that
+'--urlhost' and '--emailhost' have precedence to this notation.
+
+If you spell the list name as just `mylist', then the email hostname will be
+taken from DEFAULT_EMAIL_HOST and the url will be taken from DEFAULT_URL (as
+defined in your Defaults.py file or overridden by settings in mm_cfg.py).
+
+Note that listnames are forced to lowercase."""))
+ parser.add_option('-l', '--language',
+ type='string', action='store',
+ default=mm_cfg.DEFAULT_SERVER_LANGUAGE,
+ help=_("""\
+Make the list's preferred language LANGUAGE, which must be a two letter
+language code."""))
+ parser.add_option('-u', '--urlhost',
+ type='string', action='store',
+ help=_('The hostname for the web interface'))
+ parser.add_option('-e', '--emailhost',
+ type='string', action='store',
+ help=_('The hostname for the email server'))
+ parser.add_option('-q', '--quiet',
+ default=False, action='store_true',
+ help=_("""\
+Normally the administrator is notified by email (after a prompt) that their
+list has been created. This option suppresses the prompt and
+notification."""))
+ opts, args = parser.parse_args()
+ # Is the language known?
+ if opts.language not in mm_cfg.LC_DESCRIPTIONS:
+ parser.print_help()
+ print >> sys.stderr, _('Unknown language: $opts.language')
+ sys.exit(1)
+ return parser, opts, args
+
+
+
+def main():
+ parser, opts, args = parseargs()
+
+ # Handle variable number of positional arguments
+ if args:
+ listname = args.pop(0)
+ else:
+ listname = raw_input(_('Enter the name of the list: '))
+
+ listname = listname.lower()
+ if '@' in listname:
+ # Note that --urlhost and --emailhost have precedence
+ listname, domain = listname.split('@', 1)
+ urlhost = opts.urlhost or domain
+ emailhost = opts.emailhost or mm_cfg.VIRTUAL_HOSTS.get(domain, domain)
+
+ urlhost = opts.urlhost or mm_cfg.DEFAULT_URL_HOST
+ host_name = (opts.emailhost or
+ mm_cfg.VIRTUAL_HOSTS.get(urlhost, mm_cfg.DEFAULT_EMAIL_HOST))
+ web_page_url = mm_cfg.DEFAULT_URL_PATTERN % urlhost
+
+ if Utils.list_exists(listname):
+ parser.print_help()
+ print >> sys.stderr, _('List already exists: $listname')
+
+ if args:
+ owner_mail = args.pop(0)
+ else:
+ owner_mail = raw_input(
+ _('Enter the email of the person running the list: '))
+
+ if args:
+ listpasswd = args.pop(0)
+ else:
+ listpasswd = getpass.getpass(_('Initial $listname password: '))
+
+ # List passwords cannot be empty
+ listpasswd = listpasswd.strip()
+ if not listpasswd:
+ parser.print_help()
+ print >> sys.stderr, _('The list password cannot be empty')
+
+ mlist = MailList.MailList()
+ try:
+ pw = sha.new(listpasswd).hexdigest()
+ # Guarantee that all newly created files have the proper permission.
+ # proper group ownership should be assured by the autoconf script
+ # enforcing that all directories have the group sticky bit set.
+ oldmask = os.umask(002)
+ try:
+ try:
+ mlist.Create(listname, owner_mail, pw)
+ except Errors.BadListNameError, s:
+ parser.print_help()
+ print >> sys.stderr, _('Illegal list name: $s')
+ sys.exit(1)
+ except Errors.EmailAddressError, s:
+ parser.print_help()
+ print >> sys.stderr, _('Bad owner email address: $s')
+ sys.exit(1)
+ except Errors.MMListAlreadyExistsError:
+ parser.print_help()
+ print >> sys.stderr, _('List already exists: $listname')
+ sys.exit(1)
+ finally:
+ os.umask(oldmask)
+
+ # Assign domain-specific attributes
+ mlist.host_name = host_name
+ mlist.web_page_url = web_page_url
+
+ # And assign the preferred language
+ mlist.preferred_language = opts.language
+ mlist.Save()
+ finally:
+ mlist.Unlock()
+
+ # Now do the MTA-specific list creation tasks
+ if mm_cfg.MTA:
+ modname = 'Mailman.MTA.' + mm_cfg.MTA
+ __import__(modname)
+ sys.modules[modname].create(mlist)
+
+ # And send the notice to the list owner
+ if not opts.quiet:
+ print _('Hit enter to notify $listname owner...'),
+ sys.stdin.readline()
+ siteowner = Utils.get_site_email(mlist.host_name, 'owner')
+ d = dict(
+ listname = listname,
+ password = listpasswd,
+ admin_url = mlist.GetScriptURL('admin', absolute=True),
+ listinfo_url = mlist.GetScriptURL('listinfo', absolute=True),
+ requestaddr = mlist.GetRequestEmail(),
+ siteowner = siteowner,
+ )
+ text = Utils.maketext('newlist.txt', d, mlist=mlist)
+ # Set the I18N language to the list's preferred language so the header
+ # will match the template language. Stashing and restoring the old
+ # translation context is just (healthy? :) paranoia.
+ otrans = i18n.get_translation()
+ i18n.set_language(mlist.preferred_language)
+ try:
+ msg = Message.UserNotification(
+ owner_mail, siteowner,
+ _('Your new mailing list: $listname'),
+ text, mlist.preferred_language)
+ msg.send(mlist)
+ finally:
+ i18n.set_translation(otrans)
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/Mailman/bin/rmlist.py b/Mailman/bin/rmlist.py
new file mode 100755
index 000000000..fbaf30641
--- /dev/null
+++ b/Mailman/bin/rmlist.py
@@ -0,0 +1,153 @@
+#! @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.
+
+"""Remove the components of a mailing list with impunity - beware!
+
+This removes (almost) all traces of a mailing list. By default, the lists
+archives are not removed, which is very handy for retiring old lists.
+
+Usage:
+ rmlist [-a] [-h] listname
+
+Where:
+ --archives
+ -a
+ Remove the list's archives too, or if the list has already been
+ deleted, remove any residual archives.
+
+ --help
+ -h
+ Print this help message and exit.
+
+"""
+
+import os
+import sys
+import getopt
+import shutil
+
+import paths
+from Mailman import mm_cfg
+from Mailman import Utils
+from Mailman import MailList
+from Mailman.i18n import _
+
+try:
+ True, False
+except NameError:
+ True = 1
+ False = 0
+
+
+
+def usage(code, msg=''):
+ if code:
+ fd = sys.stderr
+ else:
+ fd = sys.stdout
+ print >> fd, _(__doc__)
+ if msg:
+ print >> fd, msg
+ sys.exit(code)
+
+
+
+def remove_it(listname, filename, msg):
+ if os.path.islink(filename):
+ print _('Removing %(msg)s')
+ os.unlink(filename)
+ elif os.path.isdir(filename):
+ print _('Removing %(msg)s')
+ shutil.rmtree(filename)
+ elif os.path.isfile(filename):
+ os.unlink(filename)
+ else:
+ print _('%(listname)s %(msg)s not found as %(filename)s')
+
+
+
+def main():
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], 'ah',
+ ['archives', 'help'])
+ except getopt.error, msg:
+ usage(1, msg)
+
+ if len(args) <> 1:
+ usage(1)
+ listname = args[0].lower().strip()
+
+ removeArchives = False
+ for opt, arg in opts:
+ if opt in ('-a', '--archives'):
+ removeArchives = True
+ elif opt in ('-h', '--help'):
+ usage(0)
+
+ if not Utils.list_exists(listname):
+ if not removeArchives:
+ usage(1, _('No such list (or list already deleted): %(listname)s'))
+ else:
+ print _(
+ 'No such list: %(listname)s. Removing its residual archives.')
+
+ if not removeArchives:
+ print _('Not removing archives. Reinvoke with -a to remove them.')
+
+
+ REMOVABLES = []
+ if Utils.list_exists(listname):
+ mlist = MailList.MailList(listname, lock=0)
+
+ # Do the MTA-specific list deletion tasks
+ if mm_cfg.MTA:
+ modname = 'Mailman.MTA.' + mm_cfg.MTA
+ __import__(modname)
+ sys.modules[modname].remove(mlist)
+
+ REMOVABLES = [
+ (os.path.join('lists', listname), _('list info')),
+ ]
+
+ # Remove any stale locks associated with the list
+ for filename in os.listdir(mm_cfg.LOCK_DIR):
+ fn_listname = filename.split('.')[0]
+ if fn_listname == listname:
+ REMOVABLES.append((os.path.join(mm_cfg.LOCK_DIR, filename),
+ _('stale lock file')))
+
+ if removeArchives:
+ REMOVABLES.extend([
+ (os.path.join('archives', 'private', listname),
+ _('private archives')),
+ (os.path.join('archives', 'private', listname + '.mbox'),
+ _('private archives')),
+ (os.path.join('archives', 'public', listname),
+ _('public archives')),
+ (os.path.join('archives', 'public', listname + '.mbox'),
+ _('public archives')),
+ ])
+
+ for dirtmpl, msg in REMOVABLES:
+ dir = os.path.join(mm_cfg.VAR_PREFIX, dirtmpl)
+ remove_it(listname, dir, msg)
+
+
+
+if __name__ == '__main__':
+ main()