From 2fa21e92d57f05488bad732a4da3fb5131ee1ca1 Mon Sep 17 00:00:00 2001
From: Barry Warsaw
Date: Wed, 1 Jan 2014 09:59:42 -0500
Subject: Bump copyright years.
---
src/mailman/app/tests/test_bounces.py | 2 +-
src/mailman/app/tests/test_inject.py | 2 +-
src/mailman/app/tests/test_lifecycle.py | 2 +-
src/mailman/app/tests/test_membership.py | 2 +-
src/mailman/app/tests/test_moderation.py | 2 +-
src/mailman/app/tests/test_notifications.py | 2 +-
src/mailman/app/tests/test_subscriptions.py | 2 +-
src/mailman/app/tests/test_templates.py | 2 +-
8 files changed, 8 insertions(+), 8 deletions(-)
(limited to 'src/mailman/app/tests')
diff --git a/src/mailman/app/tests/test_bounces.py b/src/mailman/app/tests/test_bounces.py
index f6d5669a4..284ade92b 100644
--- a/src/mailman/app/tests/test_bounces.py
+++ b/src/mailman/app/tests/test_bounces.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2011-2013 by the Free Software Foundation, Inc.
+# Copyright (C) 2011-2014 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
diff --git a/src/mailman/app/tests/test_inject.py b/src/mailman/app/tests/test_inject.py
index 78204aae3..f7f750662 100644
--- a/src/mailman/app/tests/test_inject.py
+++ b/src/mailman/app/tests/test_inject.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2011-2013 by the Free Software Foundation, Inc.
+# Copyright (C) 2011-2014 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
diff --git a/src/mailman/app/tests/test_lifecycle.py b/src/mailman/app/tests/test_lifecycle.py
index cea06359d..555f4f238 100644
--- a/src/mailman/app/tests/test_lifecycle.py
+++ b/src/mailman/app/tests/test_lifecycle.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2012-2013 by the Free Software Foundation, Inc.
+# Copyright (C) 2012-2014 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
diff --git a/src/mailman/app/tests/test_membership.py b/src/mailman/app/tests/test_membership.py
index 07994f34d..b97944351 100644
--- a/src/mailman/app/tests/test_membership.py
+++ b/src/mailman/app/tests/test_membership.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2011-2013 by the Free Software Foundation, Inc.
+# Copyright (C) 2011-2014 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
diff --git a/src/mailman/app/tests/test_moderation.py b/src/mailman/app/tests/test_moderation.py
index 529116d35..edb6b8c28 100644
--- a/src/mailman/app/tests/test_moderation.py
+++ b/src/mailman/app/tests/test_moderation.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2011-2013 by the Free Software Foundation, Inc.
+# Copyright (C) 2011-2014 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
diff --git a/src/mailman/app/tests/test_notifications.py b/src/mailman/app/tests/test_notifications.py
index e49228d0a..d37bd2906 100644
--- a/src/mailman/app/tests/test_notifications.py
+++ b/src/mailman/app/tests/test_notifications.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2012-2013 by the Free Software Foundation, Inc.
+# Copyright (C) 2012-2014 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
diff --git a/src/mailman/app/tests/test_subscriptions.py b/src/mailman/app/tests/test_subscriptions.py
index 6d269ffac..e5aad18bc 100644
--- a/src/mailman/app/tests/test_subscriptions.py
+++ b/src/mailman/app/tests/test_subscriptions.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2011-2013 by the Free Software Foundation, Inc.
+# Copyright (C) 2011-2014 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
diff --git a/src/mailman/app/tests/test_templates.py b/src/mailman/app/tests/test_templates.py
index 77a0eb381..8b8897c15 100644
--- a/src/mailman/app/tests/test_templates.py
+++ b/src/mailman/app/tests/test_templates.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2012-2013 by the Free Software Foundation, Inc.
+# Copyright (C) 2012-2014 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
--
cgit v1.3.1
From d5aac006b6eed59999029605b037c6202fcf395e Mon Sep 17 00:00:00 2001
From: Barry Warsaw
Date: Mon, 6 Jan 2014 22:43:59 -0500
Subject: Several internal improvements:
* New events:
- ConfirmationNeededEvent is triggered when a pendable requiring
confirmation is created. This allows us to define an event handler for
this event which sends the user notification.
- SubscriptionEvent is triggered when a member is added to a mailing list.
This lets us define an event handler which sends the welcome message.
* send_welcome_message() now takes a member parameter instead of an address,
which lets us directly access the member's delivery mode and user display
name (if the member has a user, which it might not in some cases).
* Use the list id in the pendable record instead of the list name for
robustness (the latter can change but the former is permanent).
* Test more registration conditions.
* In the bin/runner command line switch handling, default `verbose` to None
instead of False. This makes it work better with nose's -E switch (log to
stderr).
* In call_api(), if a POST, PUT, or PATCH method is used and data is None,
encode the empty dictionary; seems like the behavior of urlencode() has
changed, so this is safer.
* Fix style and pyflakes warnings.
---
src/mailman/app/bounces.py | 2 +-
src/mailman/app/events.py | 11 ++-
src/mailman/app/membership.py | 26 +++++-
src/mailman/app/moderator.py | 5 +-
src/mailman/app/notifications.py | 32 +++----
src/mailman/app/registrar.py | 77 ++++++++--------
src/mailman/app/tests/test_bounces.py | 3 +
src/mailman/app/tests/test_notifications.py | 42 ++++++---
src/mailman/app/tests/test_registration.py | 132 ++++++++++++++++++++++++++++
src/mailman/bin/runner.py | 2 +-
src/mailman/commands/tests/test_confirm.py | 5 +-
src/mailman/core/initialize.py | 2 +-
src/mailman/handlers/docs/acknowledge.rst | 1 +
src/mailman/interfaces/registrar.py | 24 +++++
src/mailman/model/docs/registration.rst | 2 +-
src/mailman/rest/wsgiapp.py | 2 +-
src/mailman/runners/docs/digester.rst | 1 +
src/mailman/runners/tests/test_bounce.py | 1 +
src/mailman/runners/tests/test_join.py | 1 +
src/mailman/testing/helpers.py | 2 +
20 files changed, 290 insertions(+), 83 deletions(-)
create mode 100644 src/mailman/app/tests/test_registration.py
(limited to 'src/mailman/app/tests')
diff --git a/src/mailman/app/bounces.py b/src/mailman/app/bounces.py
index 186c16467..101d96f2a 100644
--- a/src/mailman/app/bounces.py
+++ b/src/mailman/app/bounces.py
@@ -196,7 +196,7 @@ def send_probe(member, msg):
member.mailing_list.list_id)
text = make('probe.txt', mlist, member.preferred_language.code,
listname=mlist.fqdn_listname,
- address= member.address.email,
+ address=member.address.email,
optionsurl=member.options_url,
owneraddr=mlist.owner_address,
)
diff --git a/src/mailman/app/events.py b/src/mailman/app/events.py
index 814d3df03..3730d5aad 100644
--- a/src/mailman/app/events.py
+++ b/src/mailman/app/events.py
@@ -27,7 +27,8 @@ __all__ = [
from zope import event
-from mailman.app import domain, moderator, subscriptions
+from mailman.app import (
+ domain, membership, moderator, registrar, subscriptions)
from mailman.core import i18n, switchboard
from mailman.languages import manager as language_manager
from mailman.styles import manager as style_manager
@@ -39,11 +40,13 @@ def initialize():
"""Initialize global event subscribers."""
event.subscribers.extend([
domain.handle_DomainDeletingEvent,
+ i18n.handle_ConfigurationUpdatedEvent,
+ language_manager.handle_ConfigurationUpdatedEvent,
+ membership.handle_SubscriptionEvent,
moderator.handle_ListDeletingEvent,
passwords.handle_ConfigurationUpdatedEvent,
+ registrar.handle_ConfirmationNeededEvent,
+ style_manager.handle_ConfigurationUpdatedEvent,
subscriptions.handle_ListDeletingEvent,
switchboard.handle_ConfigurationUpdatedEvent,
- i18n.handle_ConfigurationUpdatedEvent,
- style_manager.handle_ConfigurationUpdatedEvent,
- language_manager.handle_ConfigurationUpdatedEvent,
])
diff --git a/src/mailman/app/membership.py b/src/mailman/app/membership.py
index bbb921812..83c1b7f8b 100644
--- a/src/mailman/app/membership.py
+++ b/src/mailman/app/membership.py
@@ -23,20 +23,22 @@ __metaclass__ = type
__all__ = [
'add_member',
'delete_member',
+ 'handle_SubscriptionEvent',
]
from email.utils import formataddr
from zope.component import getUtility
-from mailman.app.notifications import send_goodbye_message
+from mailman.app.notifications import (
+ send_goodbye_message, send_welcome_message)
from mailman.config import config
from mailman.core.i18n import _
from mailman.email.message import OwnerNotification
from mailman.interfaces.address import IEmailValidator
from mailman.interfaces.bans import IBanManager
from mailman.interfaces.member import (
- MemberRole, MembershipIsBannedError, NotAMemberError)
+ MemberRole, MembershipIsBannedError, NotAMemberError, SubscriptionEvent)
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.i18n import make
@@ -156,3 +158,23 @@ def delete_member(mlist, email, admin_notif=None, userack=None):
msg = OwnerNotification(mlist, subject, text,
roster=mlist.administrators)
msg.send(mlist)
+
+
+
+def handle_SubscriptionEvent(event):
+ if not isinstance(event, SubscriptionEvent):
+ return
+ # Only send a notification message if the mailing list is configured to do
+ # so, and the member being added is a list member (as opposed to a
+ # moderator, non-member, or owner).
+ member = event.member
+ if member.role is not MemberRole.member:
+ return
+ mlist = member.mailing_list
+ if not mlist.send_welcome_message:
+ return
+ # What language should the welcome message be sent in?
+ language = member.preferred_language
+ if language is None:
+ language = mlist.preferred_language
+ send_welcome_message(mlist, member, language)
diff --git a/src/mailman/app/moderator.py b/src/mailman/app/moderator.py
index dabff068e..046450305 100644
--- a/src/mailman/app/moderator.py
+++ b/src/mailman/app/moderator.py
@@ -38,8 +38,7 @@ from email.utils import formataddr, formatdate, getaddresses, make_msgid
from zope.component import getUtility
from mailman.app.membership import add_member, delete_member
-from mailman.app.notifications import (
- send_admin_subscription_notice, send_welcome_message)
+from mailman.app.notifications import send_admin_subscription_notice
from mailman.config import config
from mailman.core.i18n import _
from mailman.email.message import UserNotification
@@ -259,8 +258,6 @@ def handle_subscription(mlist, id, action, comment=None):
# request was made and accepted.
pass
else:
- if mlist.send_welcome_message:
- send_welcome_message(mlist, address, language, delivery_mode)
if mlist.admin_notify_mchanges:
send_admin_subscription_notice(
mlist, address, display_name, language)
diff --git a/src/mailman/app/notifications.py b/src/mailman/app/notifications.py
index 2a803d5dc..1fa1fe01e 100644
--- a/src/mailman/app/notifications.py
+++ b/src/mailman/app/notifications.py
@@ -65,44 +65,36 @@ def _get_message(uri_template, mlist, language):
-def send_welcome_message(mlist, address, language, delivery_mode, text=''):
+def send_welcome_message(mlist, member, language, text=''):
"""Send a welcome message to a subscriber.
Prepending to the standard welcome message template is the mailing list's
welcome message, if there is one.
- :param mlist: the mailing list
+ :param mlist: The mailing list.
:type mlist: IMailingList
- :param address: The address to respond to
- :type address: string
- :param language: the language of the response
+ :param member: The member to send the welcome message to.
+ :param address: IMember
+ :param language: The language of the response.
:type language: ILanguage
- :param delivery_mode: the type of delivery the subscriber is getting
- :type delivery_mode: DeliveryMode
"""
- welcome_message = _get_message(mlist.welcome_message_uri,
- mlist, language)
- # Find the IMember object which is subscribed to the mailing list, because
- # from there, we can get the member's options url.
- member = mlist.members.get_member(address)
- user_name = member.user.display_name
+ welcome_message = _get_message(mlist.welcome_message_uri, mlist, language)
options_url = member.options_url
# Get the text from the template.
+ display_name = ('' if member.user is None else member.user.display_name)
text = expand(welcome_message, dict(
fqdn_listname=mlist.fqdn_listname,
list_name=mlist.display_name,
listinfo_uri=mlist.script_url('listinfo'),
list_requests=mlist.request_address,
- user_name=user_name,
- user_address=address,
+ user_name=display_name,
+ user_address=member.address.email,
user_options_uri=options_url,
))
- if delivery_mode is not DeliveryMode.regular:
- digmode = _(' (Digest mode)')
- else:
- digmode = ''
+ digmode = ('' if member.delivery_mode is DeliveryMode.regular
+ else _(' (Digest mode)'))
msg = UserNotification(
- formataddr((user_name, address)),
+ formataddr((display_name, member.address.email)),
mlist.request_address,
_('Welcome to the "$mlist.display_name" mailing list${digmode}'),
text, language)
diff --git a/src/mailman/app/registrar.py b/src/mailman/app/registrar.py
index 252c2cf2a..aa4e35483 100644
--- a/src/mailman/app/registrar.py
+++ b/src/mailman/app/registrar.py
@@ -22,22 +22,23 @@ from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'Registrar',
+ 'handle_ConfirmationNeededEvent',
]
import logging
from zope.component import getUtility
+from zope.event import notify
from zope.interface import implementer
-from mailman.app.notifications import send_welcome_message
from mailman.core.i18n import _
from mailman.email.message import UserNotification
from mailman.interfaces.address import IEmailValidator
from mailman.interfaces.listmanager import IListManager
from mailman.interfaces.member import DeliveryMode, MemberRole
from mailman.interfaces.pending import IPendable, IPendings
-from mailman.interfaces.registrar import IRegistrar
+from mailman.interfaces.registrar import ConfirmationNeededEvent, IRegistrar
from mailman.interfaces.templates import ITemplateLoader
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.datetime import now
@@ -69,29 +70,13 @@ class Registrar:
type=PendableRegistration.PEND_KEY,
email=email,
display_name=display_name,
- delivery_mode=delivery_mode.name)
- pendable['list_name'] = mlist.fqdn_listname
+ delivery_mode=delivery_mode.name,
+ list_id=mlist.list_id)
token = getUtility(IPendings).add(pendable)
- # There are three ways for a user to confirm their subscription. They
- # can reply to the original message and let the VERP'd return address
- # encode the token, they can reply to the robot and keep the token in
- # the Subject header, or they can click on the URL in the body of the
- # message and confirm through the web.
- subject = 'confirm ' + token
- confirm_address = mlist.confirm_address(token)
- # For i18n interpolation.
- confirm_url = mlist.domain.confirm_url(token)
- email_address = email
- domain_name = mlist.domain.mail_host
- contact_address = mlist.domain.contact_address
- # Send a verification email to the address.
- template = getUtility(ITemplateLoader).get(
- 'mailman:///{0}/{1}/confirm.txt'.format(
- mlist.fqdn_listname,
- mlist.preferred_language.code))
- text = _(template)
- msg = UserNotification(email, confirm_address, subject, text)
- msg.send(mlist)
+ # We now have everything we need to begin the confirmation dance.
+ # Trigger the event to start the ball rolling, and return the
+ # generated token.
+ notify(ConfirmationNeededEvent(mlist, pendable, token))
return token
def confirm(self, token):
@@ -103,7 +88,6 @@ class Registrar:
missing = object()
email = pendable.get('email', missing)
display_name = pendable.get('display_name', missing)
- list_name = pendable.get('list_name', missing)
pended_delivery_mode = pendable.get('delivery_mode', 'regular')
try:
delivery_mode = DeliveryMode[pended_delivery_mode]
@@ -151,20 +135,43 @@ class Registrar:
pass
address.verified_on = now()
# If this registration is tied to a mailing list, subscribe the person
- # to the list right now, and possibly send a welcome message.
- list_name = pendable.get('list_name')
- if list_name is not None:
- mlist = getUtility(IListManager).get(list_name)
- if mlist:
+ # to the list right now. That will generate a SubscriptionEvent,
+ # which can be used to send a welcome message.
+ list_id = pendable.get('list_id')
+ if list_id is not None:
+ mlist = getUtility(IListManager).get_by_list_id(list_id)
+ if mlist is not None:
member = mlist.subscribe(address, MemberRole.member)
member.preferences.delivery_mode = delivery_mode
- if mlist.send_welcome_message:
- send_welcome_message(mlist,
- address.email,
- mlist.preferred_language,
- delivery_mode)
return True
def discard(self, token):
# Throw the record away.
getUtility(IPendings).confirm(token)
+
+
+
+def handle_ConfirmationNeededEvent(event):
+ if not isinstance(event, ConfirmationNeededEvent):
+ return
+ # There are three ways for a user to confirm their subscription. They
+ # can reply to the original message and let the VERP'd return address
+ # encode the token, they can reply to the robot and keep the token in
+ # the Subject header, or they can click on the URL in the body of the
+ # message and confirm through the web.
+ subject = 'confirm ' + event.token
+ mlist = getUtility(IListManager).get_by_list_id(event.pendable['list_id'])
+ confirm_address = mlist.confirm_address(event.token)
+ # For i18n interpolation.
+ confirm_url = mlist.domain.confirm_url(event.token)
+ email_address = event.pendable['email']
+ domain_name = mlist.domain.mail_host
+ contact_address = mlist.domain.contact_address
+ # Send a verification email to the address.
+ template = getUtility(ITemplateLoader).get(
+ 'mailman:///{0}/{1}/confirm.txt'.format(
+ mlist.fqdn_listname,
+ mlist.preferred_language.code))
+ text = _(template)
+ msg = UserNotification(email_address, confirm_address, subject, text)
+ msg.send(mlist)
diff --git a/src/mailman/app/tests/test_bounces.py b/src/mailman/app/tests/test_bounces.py
index 284ade92b..5eb518786 100644
--- a/src/mailman/app/tests/test_bounces.py
+++ b/src/mailman/app/tests/test_bounces.py
@@ -198,6 +198,7 @@ class TestSendProbe(unittest.TestCase):
def setUp(self):
self._mlist = create_list('test@example.com')
+ self._mlist.send_welcome_message = False
self._member = add_member(self._mlist, 'anne@example.com',
'Anne Person', 'xxx',
DeliveryMode.regular, 'en')
@@ -355,6 +356,7 @@ class TestProbe(unittest.TestCase):
def setUp(self):
self._mlist = create_list('test@example.com')
+ self._mlist.send_welcome_message = False
self._member = add_member(self._mlist, 'anne@example.com',
'Anne Person', 'xxx',
DeliveryMode.regular, 'en')
@@ -395,6 +397,7 @@ class TestMaybeForward(unittest.TestCase):
site_owner: postmaster@example.com
""")
self._mlist = create_list('test@example.com')
+ self._mlist.send_welcome_message = False
self._msg = mfs("""\
From: bouncer@example.com
To: test-bounces@example.com
diff --git a/src/mailman/app/tests/test_notifications.py b/src/mailman/app/tests/test_notifications.py
index d37bd2906..4cdc1c01c 100644
--- a/src/mailman/app/tests/test_notifications.py
+++ b/src/mailman/app/tests/test_notifications.py
@@ -33,10 +33,9 @@ from zope.component import getUtility
from mailman.app.lifecycle import create_list
from mailman.app.membership import add_member
-from mailman.app.notifications import send_welcome_message
from mailman.config import config
from mailman.interfaces.languages import ILanguageManager
-from mailman.interfaces.member import DeliveryMode
+from mailman.interfaces.member import DeliveryMode, MemberRole
from mailman.testing.helpers import get_queue_messages
from mailman.testing.layers import ConfigLayer
@@ -82,11 +81,8 @@ Welcome to the $list_name mailing list.
shutil.rmtree(self.var_dir)
def test_welcome_message(self):
- en = getUtility(ILanguageManager).get('en')
add_member(self._mlist, 'anne@example.com', 'Anne Person',
'password', DeliveryMode.regular, 'en')
- send_welcome_message(self._mlist, 'anne@example.com', en,
- DeliveryMode.regular)
# Now there's one message in the virgin queue.
messages = get_queue_messages('virgin')
self.assertEqual(len(messages), 1)
@@ -110,16 +106,42 @@ Welcome to the Test List mailing list.
'mailman:///$listname/$language/welcome.txt')
# Add the xx language and subscribe Anne using it.
manager = getUtility(ILanguageManager)
- xx = manager.add('xx', 'us-ascii', 'Xlandia')
+ manager.add('xx', 'us-ascii', 'Xlandia')
add_member(self._mlist, 'anne@example.com', 'Anne Person',
'password', DeliveryMode.regular, 'xx')
- send_welcome_message(self._mlist, 'anne@example.com', xx,
- DeliveryMode.regular)
# Now there's one message in the virgin queue.
messages = get_queue_messages('virgin')
self.assertEqual(len(messages), 1)
message = messages[0].msg
self.assertEqual(str(message['subject']),
'Welcome to the "Test List" mailing list')
- self.assertEqual(message.get_payload(),
- 'You just joined the Test List mailing list!')
+ self.assertMultiLineEqual(
+ message.get_payload(),
+ 'You just joined the Test List mailing list!')
+
+ def test_no_welcome_message_to_owners(self):
+ # Welcome messages go only to mailing list members, not to owners.
+ add_member(self._mlist, 'anne@example.com', 'Anne Person',
+ 'password', DeliveryMode.regular, 'xx',
+ MemberRole.owner)
+ # There is no welcome message in the virgin queue.
+ messages = get_queue_messages('virgin')
+ self.assertEqual(len(messages), 0)
+
+ def test_no_welcome_message_to_nonmembers(self):
+ # Welcome messages go only to mailing list members, not to nonmembers.
+ add_member(self._mlist, 'anne@example.com', 'Anne Person',
+ 'password', DeliveryMode.regular, 'xx',
+ MemberRole.nonmember)
+ # There is no welcome message in the virgin queue.
+ messages = get_queue_messages('virgin')
+ self.assertEqual(len(messages), 0)
+
+ def test_no_welcome_message_to_moderators(self):
+ # Welcome messages go only to mailing list members, not to moderators.
+ add_member(self._mlist, 'anne@example.com', 'Anne Person',
+ 'password', DeliveryMode.regular, 'xx',
+ MemberRole.moderator)
+ # There is no welcome message in the virgin queue.
+ messages = get_queue_messages('virgin')
+ self.assertEqual(len(messages), 0)
diff --git a/src/mailman/app/tests/test_registration.py b/src/mailman/app/tests/test_registration.py
new file mode 100644
index 000000000..ff128ae6f
--- /dev/null
+++ b/src/mailman/app/tests/test_registration.py
@@ -0,0 +1,132 @@
+# Copyright (C) 2012 by the Free Software Foundation, Inc.
+#
+# 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 .
+
+"""Test email address registration."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestEmailValidation',
+ 'TestRegistration',
+ ]
+
+
+import unittest
+
+from zope.component import getUtility
+
+from mailman.app.lifecycle import create_list
+from mailman.interfaces.address import InvalidEmailAddressError
+from mailman.interfaces.pending import IPendings
+from mailman.interfaces.registrar import ConfirmationNeededEvent, IRegistrar
+from mailman.testing.helpers import event_subscribers
+from mailman.testing.layers import ConfigLayer
+
+
+
+class TestEmailValidation(unittest.TestCase):
+ """Test basic email validation."""
+
+ layer = ConfigLayer
+
+ def setUp(self):
+ self.registrar = getUtility(IRegistrar)
+ self.mlist = create_list('alpha@example.com')
+
+ def test_empty_string_is_invalid(self):
+ self.assertRaises(InvalidEmailAddressError,
+ self.registrar.register, self.mlist,
+ '')
+
+ def test_no_spaces_allowed(self):
+ self.assertRaises(InvalidEmailAddressError,
+ self.registrar.register, self.mlist,
+ 'some name@example.com')
+
+ def test_no_angle_brackets(self):
+ self.assertRaises(InvalidEmailAddressError,
+ self.registrar.register, self.mlist,
+ '