cli_members.py 4.06 KB
Newer Older
Barry Warsaw's avatar
Barry Warsaw committed
1
# Copyright (C) 2009-2010 by the Free Software Foundation, Inc.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
#
# 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 <http://www.gnu.org/licenses/>.

"""The 'members' subcommand."""

from __future__ import absolute_import, unicode_literals

__metaclass__ = type
__all__ = [
    'Members',
    ]


28 29 30
import sys
import codecs

31 32
from email.utils import formataddr, parseaddr
from operator import attrgetter
33
from zope.component import getUtility
34 35
from zope.interface import implements

36 37
from mailman.app.membership import add_member
from mailman.config import config
38
from mailman.core.i18n import _
39
from mailman.interfaces.command import ICLISubCommand
Barry Warsaw's avatar
Barry Warsaw committed
40
from mailman.interfaces.listmanager import IListManager
41
from mailman.interfaces.member import AlreadySubscribedError, DeliveryMode
42 43 44 45



class Members:
46
    """Manage list memberships.  With no arguments, list all members."""
47 48 49 50 51 52 53

    implements(ICLISubCommand)

    name = 'members'

    def add(self, parser, command_parser):
        """See `ICLISubCommand`."""
Barry Warsaw's avatar
Typo.  
Barry Warsaw committed
54
        self.parser = parser
55 56 57
        command_parser.add_argument(
            '-a', '--add',
            dest='filename',
58 59 60 61
            help=_("""\
            Add all member addresses in FILENAME.  FILENAME can be '-' to
            indicate standard input.  Blank lines and lines That start with a
            '#' are ignored."""))
62 63 64 65 66 67 68 69
        # Required positional argument.
        command_parser.add_argument(
            'listname', metavar='LISTNAME', nargs=1,
            help=_("""\
            The 'fully qualified list name', i.e. the posting address of the
            mailing list.  It must be a valid email address and the domain
            must be registered with Mailman.  List names are forced to lower
            case."""))
70 71 72

    def process(self, args):
        """See `ICLISubCommand`."""
73 74 75
        assert len(args.listname) == 1, (
            'Unexpected positional arguments: %s' % args.listname)
        fqdn_listname = args.listname[0]
76
        mlist = getUtility(IListManager).get(fqdn_listname)
77 78
        if mlist is None:
            self.parser.error(_('No such list: $fqdn_listname'))
79 80 81 82 83 84
        if args.filename is None:
            for address in sorted(mlist.members.addresses,
                                  key=attrgetter('address')):
                print formataddr((address.real_name, address.original_address))
            return
        elif args.filename == '-':
85 86 87 88 89
            fp = sys.stdin
        else:
            fp = codecs.open(args.filename, 'r', 'utf-8')
        try:
            for line in fp:
90 91 92
                # Ignore blank lines and lines that start with a '#'.
                if line.startswith('#') or len(line.strip()) == 0:
                    continue
93 94 95 96 97 98
                real_name, email = parseaddr(line)
                # If not given in the input data, parseaddr() will return the
                # empty string, as opposed to the empty unicode.  We need a
                # unicode real name here.
                if real_name == '':
                    real_name = u''
99 100 101 102 103 104 105 106
                try:
                    add_member(mlist, email, real_name, None,
                               DeliveryMode.regular,
                               mlist.preferred_language.code)
                except AlreadySubscribedError:
                    # It's okay if the address is already subscribed, just
                    # print a warning and continue.
                    print 'Already subscribed (skipping):', email, real_name
107 108 109 110
        finally:
            if fp is not sys.stdin:
                fp.close()
        config.db.commit()