1# Copyright (C) 2002-2018 by the Free Software Foundation, Inc.
2#
3# This program is free software; you can redistribute it and/or
4# modify it under the terms of the GNU General Public License
5# as published by the Free Software Foundation; either version 2
6# of the License, or (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16
17"""
18    subscribe [password] [digest|nodigest] [address=<address>]
19        Subscribe to this mailing list.  Your password must be given to
20        unsubscribe or change your options, but if you omit the password, one
21        will be generated for you.  You may be periodically reminded of your
22        password.
23
24        The next argument may be either: `nodigest' or `digest' (no quotes!).
25        If you wish to subscribe an address other than the address you sent
26        this request from, you may specify `address=<address>' (no brackets
27        around the email address, and no quotes!)
28"""
29
30from email.Utils import parseaddr
31from email.Header import decode_header, make_header
32
33from Mailman import Utils
34from Mailman import Errors
35from Mailman.UserDesc import UserDesc
36from Mailman.i18n import _
37
38STOP = 1
39
40
41
42def gethelp(mlist):
43    return _(__doc__)
44
45
46
47def process(res, args):
48    mlist = res.mlist
49    digest = None
50    password = None
51    address = None
52    realname = None
53    # Parse the args
54    argnum = 0
55    for arg in args:
56        if arg.lower().startswith('address='):
57            address = arg[8:]
58        elif argnum == 0:
59            password = arg
60        elif argnum == 1:
61            if arg.lower() not in ('digest', 'nodigest'):
62                res.results.append(_('Bad digest specifier: %(arg)s'))
63                return STOP
64            if arg.lower() == 'digest':
65                digest = 1
66            else:
67                digest = 0
68        else:
69            res.results.append(_('Usage:'))
70            res.results.append(gethelp(mlist))
71            return STOP
72        argnum += 1
73    # Fix the password/digest issue
74    if (digest is None
75            and password and password.lower() in ('digest', 'nodigest')):
76        if password.lower() == 'digest':
77            digest = 1
78        else:
79            digest = 0
80        password = None
81    # Fill in empty defaults
82    if digest is None:
83        digest = mlist.digest_is_default
84    if password is None:
85        password = Utils.MakeRandomPassword()
86    if address is None:
87        realname, address = parseaddr(res.msg['from'])
88        if not address:
89            # Fall back to the sender address
90            address = res.msg.get_sender()
91        if not address:
92            res.results.append(_('No valid address found to subscribe'))
93            return STOP
94        # Watch for encoded names
95        try:
96            h = make_header(decode_header(realname))
97            # BAW: in Python 2.2, use just unicode(h)
98            realname = h.__unicode__()
99        except UnicodeError:
100            realname = u''
101        # Coerce to byte string if uh contains only ascii
102        try:
103            realname = realname.encode('us-ascii')
104        except UnicodeError:
105            pass
106    # Create the UserDesc record and do a non-approved subscription
107    listowner = mlist.GetOwnerEmail()
108    userdesc = UserDesc(address, realname, password, digest)
109    remote = res.msg.get_sender()
110    try:
111        mlist.AddMember(userdesc, remote)
112    except Errors.MembershipIsBanned:
113        res.results.append(_("""\
114The email address you supplied is banned from this mailing list.
115If you think this restriction is erroneous, please contact the list
116owners at %(listowner)s."""))
117        return STOP
118    except Errors.MMBadEmailError:
119        res.results.append(_("""\
120Mailman won't accept the given email address as a valid address.
121(E.g. it must have an @ in it.)"""))
122        return STOP
123    except Errors.MMHostileAddress:
124        res.results.append(_("""\
125Your subscription is not allowed because
126the email address you gave is insecure."""))
127        return STOP
128    except Errors.MMAlreadyAMember:
129        res.results.append(_('You are already subscribed!'))
130        return STOP
131    except Errors.MMAlreadyPending:
132        res.results.append(
133            _('You already have a subscription pending confirmation'))
134        return STOP
135    except Errors.MMCantDigestError:
136        res.results.append(
137            _('No one can subscribe to the digest of this list!'))
138        return STOP
139    except Errors.MMMustDigestError:
140        res.results.append(_('This list only supports digest subscriptions!'))
141        return STOP
142    except Errors.MMSubscribeNeedsConfirmation:
143        # We don't need to respond /and/ send a confirmation message.
144        res.respond = 0
145    except Errors.MMNeedApproval:
146        res.results.append(_("""\
147Your subscription request has been forwarded to the list administrator
148at %(listowner)s for review."""))
149    else:
150        # Everything is a-ok
151        res.results.append(_('Subscription request succeeded.'))
152