Commit 9045262c authored by Mark Sapiro's avatar Mark Sapiro

Merge branch 'fix_721' into 'master'

Add an address= option to the email join command.

Closes #721

See merge request !650
parents 8943d8a0 970c9cd3
Pipeline #148788574 passed with stage
in 71 minutes and 49 seconds
......@@ -59,13 +59,15 @@ Some commands have even more detailed help.
>>> print(results)
The results of your email command are provided below.
<BLANKLINE>
join [digest=<no|mime|plain>]
join [digest=<no|mime|plain>] [[email protected]]
Join this mailing list.
<BLANKLINE>
You will be asked to confirm your subscription request and you may be
issued a provisional password.
<BLANKLINE>
By using the 'digest' option, you can specify whether you want digest
delivery or not. If not specified, the mailing list's default delivery
mode will be used.
delivery or not. If not specified, the mailing list's default
delivery mode will be used. You can use the 'address' option to
request subscription of an address other than the sender of the
command.
<BLANKLINE>
......@@ -24,9 +24,11 @@ The mail command ``join`` subscribes an email address to the mailing list.
<BLANKLINE>
By using the 'digest' option, you can specify whether you want digest
delivery or not. If not specified, the mailing list's default
delivery mode will be used.
delivery mode will be used. You can use the 'address' option to
request subscription of an address other than the sender of the command.
>>> print(join.argument_description)
[digest=<no|mime|plain>]
[digest=<no|mime|plain>] [[email protected]]
No address to join
......
......@@ -59,24 +59,29 @@ class Join:
name = 'join'
# XXX 2012-02-29 BAW: DeliveryMode.summary is not yet supported.
argument_description = '[digest=<no|mime|plain>]'
argument_description = ('[digest=<no|mime|plain>] '
'[[email protected]]')
description = _("""\
You will be asked to confirm your subscription request and you may be issued a
provisional password.
By using the 'digest' option, you can specify whether you want digest delivery
or not. If not specified, the mailing list's default delivery mode will be
used.
used. You can use the 'address' option to request subscription of an address
other than the sender of the command.
""")
short_description = _('Join this mailing list.')
def process(self, mlist, msg, msgdata, arguments, results):
"""See `IEmailCommand`."""
# Parse the arguments.
delivery_mode = self._parse_arguments(arguments, results)
delivery_mode, address = self._parse_arguments(arguments, results)
if delivery_mode is ContinueProcessing.no:
return ContinueProcessing.no
display_name, email = parseaddr(msg['from'])
if not address:
display_name, email = parseaddr(msg['from'])
else:
display_name, email = ('', address)
# Address could be None or the empty string.
if not email:
email = msg.sender
......@@ -95,7 +100,11 @@ used.
joins.add(email)
results.joins = joins
person = formataddr((display_name, email)) # noqa: F841
subscriber = match_subscriber(email, display_name)
try:
subscriber = match_subscriber(email, display_name)
except InvalidEmailAddressError as e:
print('Invalid email address: {}'.format(e), file=results)
return ContinueProcessing.yes
try:
ISubscriptionManager(mlist).register(subscriber)
except (AlreadySubscribedError, InvalidEmailAddressError,
......@@ -116,25 +125,30 @@ used.
:param arguments: The sequences of arguments as given to the
`process()` method.
:param results: The results object.
:return: The delivery mode, None, or ContinueProcessing.no on error.
:return: A tuple (delivery mode, address) or
(ContinueProcessing.no, None) on error.
"""
mode = DeliveryMode.regular
address = None
for argument in arguments:
parts = argument.split('=', 1)
if len(parts) != 2 or parts[0] != 'digest':
if len(parts) != 2 or parts[0] not in ('digest', 'address'):
print(self.name, _('bad argument: $argument'),
file=results)
return ContinueProcessing.no
mode = {
'no': DeliveryMode.regular,
'plain': DeliveryMode.plaintext_digests,
'mime': DeliveryMode.mime_digests,
}.get(parts[1])
if mode is None:
print(self.name, _('bad argument: $argument'),
file=results)
return ContinueProcessing.no
return mode
return (ContinueProcessing.no, None)
if parts[0] == 'digest':
mode = {
'no': DeliveryMode.regular,
'plain': DeliveryMode.plaintext_digests,
'mime': DeliveryMode.mime_digests,
}.get(parts[1])
if mode is None:
print(self.name, _('bad argument: $argument'),
file=results)
return (ContinueProcessing.no, None)
if parts[0] == 'address':
address = parts[1]
return (mode, address)
@public
......
......@@ -63,6 +63,67 @@ class TestJoin(unittest.TestCase):
self._mlist = create_list('[email protected]')
self._command = Join()
def test_join_successful(self):
# Subscribe a member via join.
msg = Message()
msg['From'] = '[email protected]'
results = Results()
self._command.process(self._mlist, msg, {}, (), results)
self.assertIn('Confirmation email sent to [email protected]',
str(results))
def test_join_digest(self):
# Subscribe a member to digest via join.
msg = Message()
msg['From'] = '[email protected]'
results = Results()
self._command.process(self._mlist, msg, {}, ('digest=mime',), results)
self.assertIn('Confirmation email sent to [email protected]',
str(results))
def test_join_other(self):
# Subscribe a different address via join.
msg = Message()
msg['From'] = '[email protected]'
results = Results()
self._command.process(self._mlist, msg, {},
('[email protected]',), results)
self.assertIn('Confirmation email sent to [email protected]',
str(results))
def test_join_other_bogus(self):
# Try to subscribe a bogus different address via join.
msg = Message()
msg['From'] = '[email protected]'
results = Results()
self._command.process(self._mlist, msg, {},
('address=bogus',), results)
self.assertIn('Invalid email address: bogus', str(results))
def test_join_bad_argument(self):
# Try to subscribe a member with a bad argument via join.
msg = Message()
msg['From'] = '[email protected]'
results = Results()
self._command.process(self._mlist, msg, {}, ('digest=bogus',), results)
self.assertIn('bad argument: digest=bogus', str(results))
def test_join_bad_argument_name(self):
# Try to subscribe a member with a bad argument via join.
msg = Message()
msg['From'] = '[email protected]'
results = Results()
self._command.process(self._mlist, msg, {}, ('reg=bogus',), results)
self.assertIn('bad argument: reg=bogus', str(results))
def test_join_bad_argument_no_equal(self):
# Try to subscribe a member with a bad argument via join.
msg = Message()
msg['From'] = '[email protected]'
results = Results()
self._command.process(self._mlist, msg, {}, ('digest',), results)
self.assertIn('bad argument: digest', str(results))
def test_join_already_a_member(self):
# Try to subscribe someone who is already a member. Anne is a real
# user, with a validated address, but she is not a member of the
......
......@@ -42,6 +42,8 @@ Others
* Add a new ``archive_rendering_mode`` attribute to ``MailingList`` to
configure what kind of rendering should Archivers use to render
Emails. (Closes #720)
* An ``address=`` option has been added to the email ``join`` command to allow
requesting subscription of other than the sender of the email. (Closes #721)
3.3.1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment