# Copyright (C) 1998-2009 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
# GNU Mailman 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 3 of the License, or (at your option)
# any later version.
#
# GNU Mailman 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
# GNU Mailman. If not, see .
import os
import sys
import codecs
from cStringIO import StringIO
from email.utils import parseaddr
from mailman import Message
from mailman import Utils
from mailman import i18n
from mailman.app.membership import add_member
from mailman.config import config
from mailman.core import errors
from mailman.interfaces.member import AlreadySubscribedError, DeliveryMode
from mailman.options import SingleMailingListOptions
_ = i18n._
class ScriptOptions(SingleMailingListOptions):
usage=_("""\
%prog [options]
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 '-'.
""")
def add_options(self):
super(ScriptOptions, self).add_options()
self.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."""))
self.parser.add_option(
'-d', '--digest-members-file',
type='string', dest='digest', help=_("""\
Similar to -r, but these people become digest members."""))
self.parser.add_option(
'-w', '--welcome-msg',
type='yesno', metavar='', help=_("""\
Set whether or not to send the list members a welcome message, overriding
whatever the list's 'send_welcome_msg' setting is."""))
self.parser.add_option(
'-a', '--admin-notify',
type='yesno', metavar='', 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."""))
def sanity_check(self):
if not self.options.listname:
self.parser.error(_('Missing listname'))
if len(self.arguments) > 0:
self.parser.print_error(_('Unexpected arguments'))
if self.options.regular is None and self.options.digest is None:
parser.error(_('At least one of -r or -d is required'))
if self.options.regular == '-' and self.options.digest == '-':
parser.error(_("-r and -d cannot both be '-'"))
def readfile(filename):
if filename == '-':
fp = sys.stdin
else:
# XXX Need to specify other encodings.
fp = codecs.open(filename, encoding='utf-8')
# Strip all the lines of whitespace and discard blank lines
try:
return set(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)
def addall(mlist, subscribers, delivery_mode, ack, admin_notify, outfp):
tee = Tee(outfp)
for subscriber in subscribers:
try:
fullname, address = parseaddr(subscriber)
# Watch out for the empty 8-bit string.
if not fullname:
fullname = u''
password = Utils.MakeRandomPassword()
add_member(mlist, address, fullname, password, delivery_mode,
unicode(config.mailman.default_language))
# XXX Support ack and admin_notify
except AlreadySubscribedError:
print >> tee, _('Already a member: $subscriber')
except errors.InvalidEmailAddress:
if not address:
print >> tee, _('Bad/Invalid email address: blank line')
else:
print >> tee, _('Bad/Invalid email address: $subscriber')
else:
print >> tee, _('Subscribing: $subscriber')
def main():
options = ScriptOptions()
options.initialize()
fqdn_listname = options.options.listname
mlist = config.db.list_manager.get(fqdn_listname)
if mlist is None:
parser.error(_('No such list: $fqdn_listname'))
# Set up defaults.
send_welcome_msg = (options.options.welcome_msg
if options.options.welcome_msg is not None
else mlist.send_welcome_msg)
admin_notify = (options.options.admin_notify
if options.options.admin_notify is not None
else mlist.admin_notify)
with i18n.using_language(mlist.preferred_language):
if options.options.digest:
dmembers = readfile(options.options.digest)
else:
dmembers = set()
if options.options.regular:
nmembers = readfile(options.options.regular)
else:
nmembers = set()
if not dmembers and not nmembers:
print _('Nothing to do.')
sys.exit(0)
outfp = StringIO()
if nmembers:
addall(mlist, nmembers, DeliveryMode.regular,
send_welcome_msg, admin_notify, outfp)
if dmembers:
addall(mlist, dmembers, DeliveryMode.mime_digests,
send_welcome_msg, admin_notify, outfp)
config.db.commit()
if admin_notify:
subject = _('$mlist.real_name subscription notification')
msg = Message.UserNotification(
mlist.owner, mlist.no_reply_address, subject,
outfp.getvalue(), mlist.preferred_language)
msg.send(mlist)
if __name__ == '__main__':
main()