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'."""
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
40 """The email 'join' command."""
41 implements(IEmailCommand
)
44 argument_description
= '[digest=<yes|no>] [address=<address>]'
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
54 join address=myotheraddress@example.com
57 def process(self
, mlist
, msg
, msgdata
, arguments
, results
):
58 """See `IEmailCommand`."""
59 # Parse the arguments.
60 address
, delivery_mode
= self
._parse
_arguments
(arguments
)
62 real_name
, address
= parseaddr(msg
['from'])
63 # Address could be None or the empty string.
65 address
= msg
.get_sender()
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
82 :return: address, delivery_mode
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
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
98 if parts
[1].lower() == 'yes':
99 delivery_mode
= DeliveryMode
.mime_digests
100 elif parts
[1].lower() == 'no':
101 delivery_mode
= DeliveryMode
.regular
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
112 print >> results
, self
.name
, \
113 _('missing argument value: $argument')
114 return ContinueProcessing
.no
116 print >> results
, self
.name
, \
117 _('too many argument values: $argument')
118 return ContinueProcessing
.no
120 return address
, delivery_mode
124 # Fill in empty defaults
126 digest
= mlist
.digest_is_default
128 password
= Utils
.MakeRandomPassword()
130 realname
, address
= parseaddr(res
.msg
['from'])
132 # Fall back to the sender address
133 address
= res
.msg
.get_sender()
135 res
.results
.append(_('No valid address found to subscribe'))
137 # Watch for encoded names
139 h
= make_header(decode_header(realname
))
140 # BAW: in Python 2.2, use just unicode(h)
141 realname
= h
.__unicode
__()
144 # Coerce to byte string if uh contains only ascii
146 realname
= realname
.encode('us-ascii')
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()
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."""))
161 except Errors
.InvalidEmailAddress
:
162 res
.results
.append(_("""\
163 Mailman won't accept the given email address as a valid address."""))
165 except Errors
.MMAlreadyAMember
:
166 res
.results
.append(_('You are already subscribed!'))
168 except Errors
.MMCantDigestError
:
170 _('No one can subscribe to the digest of this list!'))
172 except Errors
.MMMustDigestError
:
173 res
.results
.append(_('This list only supports digest subscriptions!'))
175 except Errors
.MMSubscribeNeedsConfirmation
:
176 # We don't need to respond /and/ send a confirmation message.
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."""))
184 res
.results
.append(_('Subscription request succeeded.'))
188 class Subscribe(Join
):
189 """The email 'subscribe' command (an alias for 'join')."""