Collect the initialization of adapters into a separate method.
[mailman.git] / mailman / commands / join.py
blob45535470f23203ad038e87472f74a6c5e383e08d
1 # Copyright (C) 2002-2008 by the Free Software Foundation, Inc.
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.
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.
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.
17 """The email commands 'join' and 'subscribe'."""
19 __metaclass__ = type
20 __all__ = [
21 'Join',
22 'Subscribe',
26 from email.header import decode_header, make_header
27 from email.utils import formataddr, parseaddr
28 from zope.interface import implements
30 from mailman.Utils import MakeRandomPassword
31 from mailman.configuration import config
32 from mailman.i18n import _
33 from mailman.interfaces import (
34 ContinueProcessing, DeliveryMode, IEmailCommand)
35 from mailman.interfaces.registrar import IRegistrar
39 class Join:
40 """The email 'join' command."""
41 implements(IEmailCommand)
43 name = 'join'
44 argument_description = '[digest=<yes|no>] [address=<address>]'
45 description = _("""\
46 Join this mailing list. You will be asked to confirm your subscription
47 request and you may be issued a provisional password.
49 By using the 'digest' option, you can specify whether you want digest delivery
50 or not. If not specified, the mailing list's default will be used. You can
51 also subscribe an alternative address by using the 'address' option. For
52 example:
54 join address=myotheraddress@example.com
55 """)
57 def process(self, mlist, msg, msgdata, arguments, results):
58 """See `IEmailCommand`."""
59 # Parse the arguments.
60 address, delivery_mode = self._parse_arguments(arguments)
61 if address is None:
62 real_name, address = parseaddr(msg['from'])
63 # Address could be None or the empty string.
64 if not address:
65 address = msg.get_sender()
66 if not address:
67 print >> results, _(
68 '$self.name: No valid address found to subscribe')
69 return ContinueProcessing.no
70 domain = config.domains[mlist.host_name]
71 registrar = IRegistrar(domain)
72 registrar.register(address, real_name)
73 person = formataddr((real_name, address))
74 print >> results, _('Confirmation email sent to $person')
75 return ContinueProcessing.yes
77 def _parse_arguments(self, arguments):
78 """Parse command arguments.
80 :param arguments: The sequences of arguments as given to the
81 `process()` method.
82 :return: address, delivery_mode
83 """
84 address = None
85 delivery_mode = None
86 for argument in arguments:
87 parts = argument.split('=', 1)
88 if parts[0].lower() == 'digest':
89 if digest is not None:
90 print >> results, self.name, \
91 _('duplicate argument: $argument')
92 return ContinueProcessing.no
93 if len(parts) == 0:
94 # We treat just plain 'digest' as 'digest=yes'. We don't
95 # yet support the other types of digest delivery.
96 delivery_mode = DeliveryMode.mime_digests
97 else:
98 if parts[1].lower() == 'yes':
99 delivery_mode = DeliveryMode.mime_digests
100 elif parts[1].lower() == 'no':
101 delivery_mode = DeliveryMode.regular
102 else:
103 print >> results, self.name, \
104 _('bad argument: $argument')
105 return ContinueProcessing.no
106 elif parts[0].lower() == 'address':
107 if address is not None:
108 print >> results, self.name, \
109 _('duplicate argument $argument')
110 return ContinueProcessing.no
111 if len(parts) == 0:
112 print >> results, self.name, \
113 _('missing argument value: $argument')
114 return ContinueProcessing.no
115 if len(parts) > 1:
116 print >> results, self.name, \
117 _('too many argument values: $argument')
118 return ContinueProcessing.no
119 address = parts[1]
120 return address, delivery_mode
123 def ignore():
124 # Fill in empty defaults
125 if digest is None:
126 digest = mlist.digest_is_default
127 if password is None:
128 password = Utils.MakeRandomPassword()
129 if address is None:
130 realname, address = parseaddr(res.msg['from'])
131 if not address:
132 # Fall back to the sender address
133 address = res.msg.get_sender()
134 if not address:
135 res.results.append(_('No valid address found to subscribe'))
136 return STOP
137 # Watch for encoded names
138 try:
139 h = make_header(decode_header(realname))
140 # BAW: in Python 2.2, use just unicode(h)
141 realname = h.__unicode__()
142 except UnicodeError:
143 realname = u''
144 # Coerce to byte string if uh contains only ascii
145 try:
146 realname = realname.encode('us-ascii')
147 except UnicodeError:
148 pass
149 # Create the UserDesc record and do a non-approved subscription
150 listowner = mlist.GetOwnerEmail()
151 userdesc = UserDesc(address, realname, password, digest)
152 remote = res.msg.get_sender()
153 try:
154 mlist.AddMember(userdesc, remote)
155 except Errors.MembershipIsBanned:
156 res.results.append(_("""\
157 The email address you supplied is banned from this mailing list.
158 If you think this restriction is erroneous, please contact the list
159 owners at %(listowner)s."""))
160 return STOP
161 except Errors.InvalidEmailAddress:
162 res.results.append(_("""\
163 Mailman won't accept the given email address as a valid address."""))
164 return STOP
165 except Errors.MMAlreadyAMember:
166 res.results.append(_('You are already subscribed!'))
167 return STOP
168 except Errors.MMCantDigestError:
169 res.results.append(
170 _('No one can subscribe to the digest of this list!'))
171 return STOP
172 except Errors.MMMustDigestError:
173 res.results.append(_('This list only supports digest subscriptions!'))
174 return STOP
175 except Errors.MMSubscribeNeedsConfirmation:
176 # We don't need to respond /and/ send a confirmation message.
177 res.respond = 0
178 except Errors.MMNeedApproval:
179 res.results.append(_("""\
180 Your subscription request has been forwarded to the list administrator
181 at %(listowner)s for review."""))
182 else:
183 # Everything is a-ok
184 res.results.append(_('Subscription request succeeded.'))
188 class Subscribe(Join):
189 """The email 'subscribe' command (an alias for 'join')."""
191 name = 'subscribe'