← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~alvarocs/launchpad:remove-mailinglist-links into launchpad:master

 

Alvaro Crespo Serrano has proposed merging ~alvarocs/launchpad:remove-mailinglist-links into launchpad:master.

Commit message:
Remove mailing list portlet with links from team page and contact address page


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~alvarocs/launchpad/+git/launchpad/+merge/493207

- Team overview ~team: remove the mailing-list portlet so links are no longer shown.
- Team contact address form: remove the "set up a mailing list" link. Update warning message.
- Stories: remove doctests that depend on the now hidden UI.
- Tests: update test to to expect no subscribe link.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~alvarocs/launchpad:remove-mailinglist-links into launchpad:master.
diff --git a/lib/lp/registry/browser/tests/test_mailinglists.py b/lib/lp/registry/browser/tests/test_mailinglists.py
index 9493022..8bc50da 100644
--- a/lib/lp/registry/browser/tests/test_mailinglists.py
+++ b/lib/lp/registry/browser/tests/test_mailinglists.py
@@ -80,7 +80,7 @@ class MailingListSubscriptionControlsTestCase(TestCaseWithFactory):
         )
         content = view.render()
         link_tag = find_tag_by_id(content, "link-list-subscribe")
-        self.assertNotEqual(None, link_tag)
+        self.assertIsNone(link_tag)
 
     def test_subscribe_control_doesnt_render_for_non_member(self):
         other_person = self.factory.makePerson()
diff --git a/lib/lp/registry/stories/mailinglists/hosted-email-address.rst b/lib/lp/registry/stories/mailinglists/hosted-email-address.rst
deleted file mode 100644
index 428067c..0000000
--- a/lib/lp/registry/stories/mailinglists/hosted-email-address.rst
+++ /dev/null
@@ -1,84 +0,0 @@
-Changing from a hosted ML to an external address
-================================================
-
-Once made active, hosted mailing lists have their posting address stored in
-the EmailAddress table.  These are not deleted when a team's contact address
-is changed from a hosted ML to an external address, in order to ensure that
-the address is reserved for the team which owns the ML.
-
-    >>> login("foo.bar@xxxxxxxxxxxxx")
-    >>> team, mailing_list = factory.makeTeamAndMailingList(
-    ...     "aardvarks", "no-priv"
-    ... )
-    >>> transaction.commit()
-
-    >>> from lp.services.identity.model.emailaddress import EmailAddressSet
-    >>> email_set = EmailAddressSet()
-    >>> email_set.getByEmail(mailing_list.address)
-    <EmailAddress ...
-
-The team owner sets the contact address to the hosted mailing list.
-
-    >>> from lp.testing.pages import strip_label
-
-    >>> logout()
-    >>> user_browser.open("http://launchpad.test/~aardvarks/+edit";)
-    >>> user_browser.getLink(url="+contactaddress").click()
-    >>> user_browser.getControl("The Launchpad mailing list").selected = True
-    >>> user_browser.getControl("Change").click()
-    >>> user_browser.getLink(url="+contactaddress").click()
-    >>> control = user_browser.getControl(name="field.contact_method")
-    >>> [strip_label(label) for label in control.displayValue]
-    ['The Launchpad mailing list for this team...]
-
-The team owner sets the contact address to an external email address, and
-Launchpad sends that address a confirmation message.
-
-    >>> from lp.services.mail import stub
-    >>> stub.test_emails = []
-    >>> user_browser.getControl("Another email address").selected = True
-    >>> user_browser.getControl(name="field.contact_address").value = (
-    ...     "bar@xxxxxxxxxxx"
-    ... )
-    >>> user_browser.getControl("Change").click()
-    >>> print(user_browser.title)
-    Aardvarks in Launchpad
-    >>> print_feedback_messages(user_browser.contents)
-    A confirmation message has been sent to...
-    >>> from_addr, to_addrs, raw_msg = stub.test_emails.pop()
-    >>> stub.test_emails
-    []
-    >>> import email
-    >>> msg = email.message_from_bytes(raw_msg)
-    >>> print(msg["From"])
-    Launchpad Email Validator <noreply@xxxxxxxxxxxxx>
-    >>> print(msg["Subject"])
-    Launchpad: Validate your team's contact email address
-
-When the confirmation token url is followed, the external email address is
-confirmed.
-
-    >>> from lp.services.verification.tests.logintoken import (
-    ...     get_token_url_from_email,
-    ... )
-    >>> token_url = get_token_url_from_email(raw_msg)
-    >>> user_browser.open(token_url)
-    >>> print(user_browser.title)
-    Confirm email address
-    >>> user_browser.getControl("Continue").click()
-    >>> print(user_browser.title)
-    Aardvarks in Launchpad
-    >>> print_feedback_messages(user_browser.contents)
-    Email address successfully confirmed.
-
-    >>> user_browser.getLink(url="+contactaddress").click()
-    >>> control = user_browser.getControl(name="field.contact_method")
-    >>> [strip_label(label) for label in control.displayValue]
-    ['Another email address']
-
-The web UI will only display the team's contact address, but the
-EmailAddress object for that team's mailing list will still be in the
-database.
-
-    >>> email_set.getByEmail(mailing_list.address)
-    <EmailAddress ...
diff --git a/lib/lp/registry/stories/mailinglists/lifecycle.rst b/lib/lp/registry/stories/mailinglists/lifecycle.rst
deleted file mode 100644
index 10a092e..0000000
--- a/lib/lp/registry/stories/mailinglists/lifecycle.rst
+++ /dev/null
@@ -1,424 +0,0 @@
-======================
-Mailing list lifecycle
-======================
-
-Every team in Launchpad can have a mailing list, and every mailing list is
-associated with exactly one team.
-
-
-Hosted mailing list
-===================
-
-The owner of Landscape Developers cannot create a new mailing list.
-
-    >>> from zope.security.management import newInteraction, endInteraction
-    >>> from lp.testing.factory import LaunchpadObjectFactory
-
-    >>> browser = setupBrowser(auth="Basic test@xxxxxxxxxxxxx:test")
-    >>> browser.open(
-    ...     "http://launchpad.test/~landscape-developers/+mailinglist";
-    ... )
-    >>> from lp.services.helpers import backslashreplace
-    >>> print(backslashreplace(browser.title))
-    Mailing list configuration : \u201cLandscape Developers\u201d team
-    >>> print(
-    ...     extract_text(find_tag_by_id(browser.contents, "no_mailing_list"))
-    ... )
-    Launchpad no longer supports the creation of new mailing lists.
-    Read more about it here.
-
-    >>> browser.open("http://launchpad.test/~landscape-developers";)
-    >>> print(browser.title)
-    Landscape Developers in Launchpad
-
-    # Create a new mailing list for testing purposes.
-    >>> newInteraction()
-    >>> factory = LaunchpadObjectFactory()
-    >>> factory.makeTeamAndMailingList(
-    ...     "landscape-developers", "test"
-    ... )  # doctest: +ELLIPSIS
-    (<Person landscape-developers (Landscape Developers)>,
-    <MailingList for team "landscape-developers"; status=ACTIVE;
-    address=landscape-developers@xxxxxxxxxxxxxxxxxxxx at ...>)
-    >>> endInteraction()
-
-    >>> def mailing_list_status_message(contents):
-    ...     """Find out if a mailing list is in an unusual state."""
-    ...     tag = find_tag_by_id(contents, "mailing_list_status_message")
-    ...     if tag:
-    ...         return extract_text(tag.strong)
-    ...     else:
-    ...         return ""
-    ...
-
-Mailman helper function.
-
-    >>> from lp.registry.tests import mailinglists_helper
-    >>> def act():
-    ...     login("foo.bar@xxxxxxxxxxxxx")
-    ...     mailinglists_helper.mailman.act()
-    ...     transaction.commit()
-    ...     logout()
-    ...
-
-Once the team's mailing list is active, there is a link to its archive.  This
-is true even if no messages have yet been posted to the mailing list (since
-the archiver will display an informative message to that effect).
-
-    >>> browser.open("http://launchpad.test/~landscape-developers";)
-    >>> print(
-    ...     extract_link_from_tag(
-    ...         find_tag_by_id(browser.contents, "mailing-list-archive")
-    ...     )
-    ... )
-    http://lists.launchpad.test/landscape-developers
-
-The team's overview page also displays the posting address.
-
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(
-    ...             browser.contents, "mailing-list-posting-address"
-    ...         )
-    ...     )
-    ... )
-    landscape-developers@xxxxxxxxxxxxxxxxxxxx
-
-Now that the mailing list is active, it can be used as the team's contact
-address.
-
-    >>> from lp.testing.pages import strip_label
-
-    >>> browser.getLink(url="+mailinglist").click()
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(
-    ...             browser.contents, "mailing_list_not_contact_address"
-    ...         )
-    ...     )
-    ... )
-    The mailing list is not set as the team contact address. You can
-    set it.
-
-    >>> browser.getLink(url="+contactaddress").click()
-    >>> browser.getControl("The Launchpad mailing list").selected = True
-    >>> browser.getControl("Change").click()
-
-    >>> browser.getLink(url="+contactaddress").click()
-    >>> control = browser.getControl(name="field.contact_method")
-    >>> [strip_label(label) for label in control.displayValue]
-    ['The Launchpad mailing list for this team...]
-
-The mailing list's configuration screen is also now available.
-
-    >>> print(browser.getLink(url="+mailinglist").url)
-    http://launchpad.test/~landscape-developers/+mailinglist
-
-When the mailing list is not the team's contact address, the mailing
-list configuration screen displays a message to this effect.
-
-    >>> browser.getControl("Each member individually").selected = True
-    >>> browser.getControl("Change").click()
-
-    >>> browser.getLink(url="+mailinglist").click()
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(
-    ...             browser.contents, "mailing_list_not_contact_address"
-    ...         )
-    ...     )
-    ... )
-    The mailing list is not set as the team contact address. You can
-    set it.
-
-The message contains a link to the contact address screen.
-
-    >>> browser.getLink("set it").click()
-    >>> browser.getControl("The Launchpad mailing list").selected = True
-    >>> browser.getControl("Change").click()
-    >>> print(browser.title)
-    Landscape Developers in Launchpad
-
-When the mailing list is the team's contact address, the message does
-not show up.
-
-    >>> browser.getLink(url="+mailinglist").click()
-    >>> find_tag_by_id(
-    ...     browser.contents, "mailing_list_not_contact_address"
-    ... ) is None
-    True
-
-The contact address is now set to the mailing list address.
-
-    >>> browser.goBack()
-    >>> browser.getLink(url="+contactaddress").click()
-    >>> control = browser.getControl(name="field.contact_method")
-    >>> [strip_label(label) for label in control.displayValue]
-    ['The Launchpad mailing list for this team -
-      landscape-developers@xxxxxxxxxxxxxxxxxxxx']
-
-
-Deactivating and reactivating lists
-===================================
-
-An active mailing list can be deactivated. If the deactivated mailing
-list was the team contact method, the contact method will be changed
-to 'each user individually'.
-
-    >>> browser.open(
-    ...     "http://launchpad.test/~landscape-developers/+mailinglist";
-    ... )
-    >>> browser.getControl("Deactivate this Mailing List").click()
-    >>> browser.getLink(url="+contactaddress").click()
-    >>> control = browser.getControl(name="field.contact_method")
-    >>> [strip_label(label) for label in control.displayValue]
-    ['Each member individually']
-
-    >>> act()
-    >>> browser.open(
-    ...     "http://launchpad.test/~landscape-developers/+mailinglist";
-    ... )
-    >>> print(mailing_list_status_message(browser.contents))
-    This team's mailing list has been deactivated.
-
-A deactivated mailing list still has a link to its archive, because archives
-are never deleted.
-
-    >>> browser.open("http://launchpad.test/~landscape-developers";)
-    >>> print(
-    ...     extract_link_from_tag(
-    ...         find_tag_by_id(browser.contents, "mailing-list-archive")
-    ...     )
-    ... )
-    http://lists.launchpad.test/landscape-developers
-
-An inactive mailing list cannot be reactivated.
-
-    >>> browser.getLink(url="+mailinglist").click()
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(browser.contents, "mailing_list_reactivate")
-    ...     )
-    ... )
-    Launchpad no longer supports the reactivation of mailing lists.
-    Read more about it here.
-
-The archive link is only available for public mailing lists as shown above,
-and for private mailing lists for team members.
-
-    >>> from lp.registry.interfaces.person import PersonVisibility
-    >>> login("foo.bar@xxxxxxxxxxxxx")
-    >>> bassists = mailinglists_helper.new_team("bassists")
-    >>> bassists.visibility = PersonVisibility.PRIVATE
-    >>> bassists_list = mailinglists_helper.new_list_for_team(bassists)
-    >>> logout()
-
-The owner of the list can see archive link.
-
-    >>> user_browser.open("http://launchpad.test/~bassists";)
-    >>> print(
-    ...     extract_link_from_tag(
-    ...         find_tag_by_id(user_browser.contents, "mailing-list-archive")
-    ...     )
-    ... )
-    http://lists.launchpad.test/bassists
-
-Anonymous users cannot see the link, because they cannot even see the
-private team.
-
-    >>> anon_browser.open("http://launchpad.test/~bassists";)
-    Traceback (most recent call last):
-    ...
-    zope.publisher.interfaces.NotFound: Object: <...>, name: '~bassists'
-
-The same is true for normal users who are not team members.
-
-    >>> browser.open("http://launchpad.test/~bassists";)
-    Traceback (most recent call last):
-    ...
-    zope.publisher.interfaces.NotFound: Object: <...>, name: '~bassists'
-
-Members who are not owners can see the link.
-
-    >>> cprov_browser = setupBrowser(
-    ...     auth="Basic celso.providelo@xxxxxxxxxxxxx:test"
-    ... )
-    >>> cprov_browser.open("http://launchpad.test/~bassists";)
-    Traceback (most recent call last):
-    ...
-    zope.publisher.interfaces.NotFound: Object: <...>, name: '~bassists'
-
-    >>> admin_browser.open("http://launchpad.test/~bassists/+addmember";)
-    >>> admin_browser.getControl("New member").value = "cprov"
-    >>> admin_browser.getControl("Add Member").click()
-
-    >>> cprov_browser.open("http://launchpad.test/~bassists";)
-    >>> print(
-    ...     extract_link_from_tag(
-    ...         find_tag_by_id(cprov_browser.contents, "mailing-list-archive")
-    ...     )
-    ... )
-    http://lists.launchpad.test/bassists
-
-Admins who are not members of the team can see the link too.
-
-    >>> admin_browser.open("http://launchpad.test/~bassists";)
-    >>> print(
-    ...     extract_link_from_tag(
-    ...         find_tag_by_id(admin_browser.contents, "mailing-list-archive")
-    ...     )
-    ... )
-    http://lists.launchpad.test/bassists
-
-
-Purge permissions
-=================
-
-A mailing list may be 'purged' when it is in one of several safe states.
-By 'safe' we mean that there are no artifacts of the mailing list on the
-Mailman side that need to be preserved.  This is not guaranteed by the
-code, except by the state of the mailing list, so if for example we want
-to delete the archives of an INACTIVE list, this must be done manually.
-
-    # Create a team without a mailing list owned by no-priv so the owner of
-    # the team has no additional privileges.
-    >>> login("foo.bar@xxxxxxxxxxxxx")
-    >>> team = mailinglists_helper.new_team("aardvarks")
-    >>> logout()
-
-    >>> from zope.component import getUtility
-    >>> from lp.registry.interfaces.mailinglist import IMailingListSet
-    >>> def print_list_state(team_name="aardvarks"):
-    ...     login("foo.bar@xxxxxxxxxxxxx")
-    ...     mailing_list = getUtility(IMailingListSet).get(team_name)
-    ...     print(mailing_list.status.name)
-    ...     logout()
-    ...
-
-The team owner cannot create new mailing lists.
-
-    >>> user_browser.open("http://launchpad.test/~aardvarks/+mailinglist";)
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(user_browser.contents, "no_mailing_list")
-    ...     )
-    ... )
-    Launchpad no longer supports the creation of new mailing lists.
-    Read more about it here.
-
-    # Create a mailing list to test the deletion, purging, and reactivation
-    # options.
-    >>> newInteraction()
-    >>> mailinglists_helper.new_list_for_team(team)  # doctest: +ELLIPSIS
-    <MailingList for team "aardvarks"; status=ACTIVE;
-    address=aardvarks@xxxxxxxxxxxxxxxxxxxx at ...>
-    >>> endInteraction()
-
-The team owner can purge or deactivate mailing lists.
-
-    >>> user_browser.open("http://launchpad.test/~aardvarks/+mailinglist";)
-    >>> user_browser.getControl("Deactivate this Mailing List").click()
-    >>> act()
-    >>> print_list_state()
-    INACTIVE
-
-    >>> def purge_text(browser):
-    ...     tag = find_tag_by_id(browser.contents, "mailing_list_purge")
-    ...     if tag is None:
-    ...         return None
-    ...     return tag.p.contents[0].strip()
-    ...
-
-    >>> user_browser.getLink(url="+mailinglist").click()
-    >>> print(purge_text(user_browser))
-    You can purge this mailing list...
-
-The team owner cannot reactivate mailing lists.
-
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(
-    ...             user_browser.contents, "mailing_list_reactivate"
-    ...         )
-    ...     )
-    ... )
-    Launchpad no longer supports the reactivation of mailing lists.
-    Read more about it here.
-
-    >>> user_browser.getControl("Purge this Mailing List")
-    <SubmitControl name='field.actions.purge_list' type='submit'>
-
-Mailing list experts can also purge mailing lists.  Sample Person is
-trustworthy enough to become a mailing list expert, but not a Launchpad
-administrator.  They're given mailing list expert authority so that they can
-purge mailing lists.
-
-    >>> login("foo.bar@xxxxxxxxxxxxx")
-    >>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
-    >>> from lp.registry.interfaces.person import IPersonSet
-    >>> person_set = getUtility(IPersonSet)
-    >>> test = person_set.getByName("name12")
-    >>> experts = getUtility(ILaunchpadCelebrities).registry_experts
-    >>> ignored = experts.addMember(test, reviewer=experts.teamowner)
-    >>> logout()
-    >>> transaction.commit()
-
-Sample Person, who is now a mailing list expert but not a Launchpad
-administrator, can purge a list.
-
-    >>> expert_browser = setupBrowser("Basic test@xxxxxxxxxxxxx:test")
-    >>> expert_browser.open("http://launchpad.test/~aardvarks/+mailinglist";)
-    >>> print(purge_text(expert_browser))
-    You can purge this mailing list...
-
-A constructing, modified, updating, or deactivating or mod-failed list cannot
-be purged.
-
-    >>> from zope.security.proxy import removeSecurityProxy
-    >>> from lp.registry.interfaces.mailinglist import MailingListStatus
-
-    >>> def set_list_state(team_name, status):
-    ...     login("foo.bar@xxxxxxxxxxxxx")
-    ...     mailing_list = getUtility(IMailingListSet).get(team_name)
-    ...     naked_list = removeSecurityProxy(mailing_list)
-    ...     naked_list.status = status
-    ...     transaction.commit()
-    ...     logout()
-    ...
-
-    >>> def show_states(*states):
-    ...     url = "http://launchpad.test/~aardvarks/+mailinglist";
-    ...     for status in states:
-    ...         set_list_state("aardvarks", status)
-    ...         print_list_state()
-    ...         admin_browser.open(url)
-    ...         print(purge_text(admin_browser))
-    ...         expert_browser.open(url)
-    ...         print(purge_text(expert_browser))
-    ...
-
-A purged list acts as if it doesn't even exist.
-
-    >>> set_list_state("aardvarks", MailingListStatus.PURGED)
-    >>> print_list_state()
-    PURGED
-    >>> admin_browser.open("http://launchpad.test/~aardvarks/+mailinglist";)
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(admin_browser.contents, "no_mailing_list")
-    ...     )
-    ... )
-    Launchpad no longer supports the creation of new mailing lists.
-    Read more about it here.
-    >>> expert_browser.open("http://launchpad.test/~aardvarks/+mailinglist";)
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(expert_browser.contents, "no_mailing_list")
-    ...     )
-    ... )
-    Launchpad no longer supports the creation of new mailing lists.
-    Read more about it here.
-
-The team owner can see that an inactive list can be reactivated or purged.
-
-    >>> set_list_state("aardvarks", MailingListStatus.INACTIVE)
diff --git a/lib/lp/registry/stories/mailinglists/subscriptions.rst b/lib/lp/registry/stories/mailinglists/subscriptions.rst
deleted file mode 100644
index cb8db26..0000000
--- a/lib/lp/registry/stories/mailinglists/subscriptions.rst
+++ /dev/null
@@ -1,665 +0,0 @@
-====================================
-Mailing list subscription management
-====================================
-
-Teams can have mailing lists associated with them, and a member of a
-team with a usable mailing list can subscribe to that list. A person
-can subscribe to a mailing list using any of their email addresses, or a
-dynamic subscription which uses whichever email address is their
-preferred address at a given time.
-
-Non-team members can request a subscription to a mailing list at the
-same time as they sign up for a new team.  Their list membership is
-approved at the same time that they are approved for the team.
-
-
-Setup
-=====
-
-Carlos is a member of four teams: admins, rosetta-admins, testing-spanish-team
-and ubuntu-translators.  He has two email addresses, one of which is his
-preferred email address.  Both the admins and rosetta-admins teams are given
-mailing lists but only admins will actually use its mailing list as its
-contact address.
-
-    >>> from zope.security.management import newInteraction, endInteraction
-    >>> from lp.testing.factory import LaunchpadObjectFactory
-
-    >>> newInteraction()
-    >>> factory = LaunchpadObjectFactory()
-    >>> factory.makeTeamAndMailingList("admins", "foo")  # doctest: +ELLIPSIS
-    (<Person admins (Launchpad Administrators)>,
-    <MailingList for team "admins"; status=ACTIVE;
-    address=admins@xxxxxxxxxxxxxxxxxxxx at ...>)
-    >>> endInteraction()
-
-    >>> newInteraction()
-    >>> factory = LaunchpadObjectFactory()
-    >>> factory.makeTeamAndMailingList(
-    ...     "rosetta-admins", "foo"
-    ... )  # doctest: +ELLIPSIS
-    (<Person rosetta-admins (Rosetta Administrators)>,
-    <MailingList for team "rosetta-admins"; status=ACTIVE;
-    address=rosetta-admins@xxxxxxxxxxxxxxxxxxxx at ...>)
-    >>> endInteraction()
-
-    >>> admin_browser.open("http://launchpad.test/~admins/+edit";)
-    >>> admin_browser.getLink(url="+contactaddress").click()
-    >>> admin_browser.getControl("The Launchpad mailing list").selected = True
-    >>> admin_browser.getControl("Change").click()
-
-Carlos requests a mailing list for testing-spanish-team but it will not
-actually be approved (new mailing lists cannot be created).
-
-    >>> browser = setupBrowser(auth="Basic carlos@xxxxxxxxxxxxx:test")
-    >>> browser.open(
-    ...     "http://launchpad.test/~testing-spanish-team/+mailinglist";
-    ... )
-    >>> print(
-    ...     extract_text(find_tag_by_id(browser.contents, "no_mailing_list"))
-    ... )
-    Launchpad no longer supports the creation of new mailing lists.
-    Read more about it here.
-
-
-Subscribing
-===========
-
-Any team member can join the mailing list.
-
-    >>> admin_browser.open("http://launchpad.test/~rosetta-admins/+addmember";)
-    >>> admin_browser.getControl("New member").value = "no-team-memberships"
-    >>> admin_browser.getControl("Add Member").click()
-
-    >>> from lp.testing.pages import setupBrowserFreshLogin
-    >>> from zope.component import getUtility
-    >>> from lp.registry.interfaces.person import IPersonSet
-    >>> login(ANONYMOUS)
-    >>> person = getUtility(IPersonSet).getByEmail(
-    ...     "no-team-memberships@xxxxxxxx"
-    ... )
-    >>> logout()
-    >>> no_team_browser = setupBrowserFreshLogin(person)
-
-    >>> no_team_browser.open(
-    ...     "http://launchpad.test/people/+me/+editmailinglists";
-    ... )
-    >>> rosetta_admins = no_team_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-    >>> rosetta_admins.displayOptions
-    ['Preferred address', "Don't subscribe", 'no-team-memberships@xxxxxxxx']
-
-
-Subscription management
-=======================
-
-To subscribe to a mailing list, Carlos uses his subscription management
-screen, which shows a subscription control for the mailing lists of every team
-he's a member of.  Mailing lists show up in this list regardless of whether
-it's currently the team contact method.
-
-    >>> login(ANONYMOUS)
-    >>> carlos = getUtility(IPersonSet).getByName("carlos")
-    >>> logout()
-    >>> carlos_browser = setupBrowserFreshLogin(carlos)
-    >>> carlos_browser.open("http://launchpad.test/~carlos";)
-    >>> carlos_browser.getLink(url="+editmailinglists").click()
-
-    >>> from lp.services.helpers import backslashreplace
-    >>> print(backslashreplace(carlos_browser.title))
-    Change your mailing list subscriptions...
-
-    >>> admins = carlos_browser.getControl(name="field.subscription.admins")
-    >>> rosetta_admins = carlos_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-
-    >>> admins.displayOptions
-    ['Preferred address', "Don't subscribe",
-     'carlos@xxxxxxxxxxxxx', 'carlos@xxxxxxxx']
-
-    >>> print(admins.value)
-    ["Don't subscribe"]
-    >>> print(rosetta_admins.value)
-    ["Don't subscribe"]
-
-However, testing-spanish-team's list doesn't show up because its creation has
-not been completed (specifically, Mailman hasn't constructed it yet).
-
-    >>> carlos_browser.getControl(
-    ...     name="field.subscription.testing-spanish-team"
-    ... )
-    Traceback (most recent call last):
-    ...
-    LookupError: name ...'field.subscription.testing-spanish-team'
-    ...
-
-Carlos can subscribe to a list using his preferred email address.  Such
-subscriptions will track changes to his preferred address without requiring
-him to update his subscription.  So this is not the same as subscribing
-explicitly with whatever is his preferred email address.
-
-    >>> admins = carlos_browser.getControl(name="field.subscription.admins")
-    >>> admins.value = ["Preferred address"]
-    >>> carlos_browser.getControl("Update Subscriptions").click()
-
-    >>> print_feedback_messages(carlos_browser.contents)
-    Subscriptions updated.
-
-    >>> admins = carlos_browser.getControl(name="field.subscription.admins")
-    >>> rosetta_admins = carlos_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-    >>> print(admins.value)
-    ['Preferred address']
-    >>> print(rosetta_admins.value)
-    ["Don't subscribe"]
-
-Carlos can subscribe to a list using any of his validated addresses
-explicitly.
-
-    >>> admins.value = ["carlos@xxxxxxxxxxxxx"]
-    >>> rosetta_admins.value = ["carlos@xxxxxxxx"]
-    >>> carlos_browser.getControl("Update Subscriptions").click()
-
-    >>> admins = carlos_browser.getControl(name="field.subscription.admins")
-    >>> rosetta_admins = carlos_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-    >>> print(admins.value)
-    ['carlos@xxxxxxxxxxxxx']
-    >>> print(rosetta_admins.value)
-    ['carlos@xxxxxxxx']
-
-He can switch from one address to another, or from a specific address
-to the preferred address.
-
-    >>> admins.value = ["Preferred address"]
-    >>> rosetta_admins.value = ["carlos@xxxxxxxxxxxxx"]
-    >>> carlos_browser.getControl("Update Subscriptions").click()
-
-    >>> admins = carlos_browser.getControl(name="field.subscription.admins")
-    >>> rosetta_admins = carlos_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-    >>> print(admins.value)
-    ['Preferred address']
-    >>> print(rosetta_admins.value)
-    ['carlos@xxxxxxxxxxxxx']
-
-Finally, he can unsubscribe from any mailing list by setting the subscription
-menu item to "Don't subscribe".
-
-    >>> admins = carlos_browser.getControl(name="field.subscription.admins")
-    >>> rosetta_admins = carlos_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-    >>> admins.value = ["Don't subscribe"]
-    >>> rosetta_admins.value = ["Don't subscribe"]
-    >>> carlos_browser.getControl("Update Subscriptions").click()
-
-    >>> admins = carlos_browser.getControl(name="field.subscription.admins")
-    >>> rosetta_admins = carlos_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-    >>> print(admins.value)
-    ["Don't subscribe"]
-    >>> print(rosetta_admins.value)
-    ["Don't subscribe"]
-
-
-Subscription during team sign up
-================================
-
-Jdub is only a member of the ubuntu team.  He can request to be placed
-on another team's mailing list at the same time that he requests
-membership on the team.
-
-First we need to confirm that the desired team has a list to subscribe
-to.  We will use Carlos, as he is an administrator for the Rosetta
-Admins team, and he should know if the list is available.
-
-    >>> carlos_browser.open("http://launchpad.test/~carlos";)
-    >>> carlos_browser.getLink(url="+editmailinglists").click()
-    >>> print(backslashreplace(carlos_browser.title))
-    Change your mailing list subscriptions...
-
-    >>> rosetta_admins = carlos_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-    >>> rosetta_admins.displayOptions
-    ['Preferred address', "Don't subscribe",
-     'carlos@xxxxxxxxxxxxx', 'carlos@xxxxxxxx']
-
-Now Jdub can apply for team membership and mailing list access.
-
-    >>> browser = setupBrowser(auth="Basic jeff.waugh@xxxxxxxxxxxxxxx:test")
-    >>> browser.open("http://launchpad.test/~rosetta-admins";)
-    >>> browser.getLink("Join the team").click()
-    >>> browser.url
-    'http://launchpad.test/~rosetta-admins/+join'
-
-    >>> browser.getControl(name="field.mailinglist_subscribe").value = True
-    >>> browser.getControl(name="field.actions.join").click()
-    >>> browser.url
-    'http://launchpad.test/~rosetta-admins'
-
-    >>> for tag in find_tags_by_class(browser.contents, "informational"):
-    ...     print(tag.decode_contents())
-    ...
-    Your request to join Rosetta Administrators is awaiting approval.
-    Your mailing list subscription is awaiting approval.
-
-Jdub hasn't been approved for the team yet, so he is not subscribed to
-the list.  The list does not show up on his Subscription Management
-screen.
-
-    >>> login(ANONYMOUS)
-    >>> jdub = getUtility(IPersonSet).getByName("jdub")
-    >>> logout()
-    >>> jdub_browser = setupBrowserFreshLogin(jdub)
-    >>> jdub_browser.open("http://launchpad.test/~jdub";)
-    >>> jdub_browser.getLink(url="+editmailinglists").click()
-    >>> print(jdub_browser.title)
-    Change your mailing list subscriptions...
-
-    >>> jdub_browser.getControl(name="field.subscription.rosetta-admins")
-    Traceback (most recent call last):
-    ...
-    LookupError: name ...'field.subscription.rosetta-admins'
-    ...
-
-Jdub will become a member of the team's mailing list as soon as he has
-been approved for the team.
-
-    >>> admin_browser.open("http://launchpad.test/~rosetta-admins";)
-    >>> admin_browser.getLink("All members").click()
-    >>> admin_browser.getLink(url="/~rosetta-admins/+member/jdub").click()
-    >>> print(admin_browser.url)
-    http://launchpad.test/~rosetta-admins/+member/jdub
-    >>> admin_browser.getControl(name="approve").click()
-
-His mailing list subscription is now available to be managed.
-
-    >>> jdub_browser.open("http://launchpad.test/~jdub";)
-    >>> jdub_browser.getLink(url="+editmailinglists").click()
-    >>> print(jdub_browser.title)
-    Change your mailing list subscriptions...
-
-    >>> rosetta_team = jdub_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-
-    >>> rosetta_team.displayOptions
-    ['Preferred address', "Don't subscribe", 'jeff.waugh@xxxxxxxxxxxxxxx']
-
-Jdub's mailing list preferences are preserved when he leaves the team.
-When he requests to re-join, the option to re-subscribe to the mailing
-list is not presented.
-
-    >>> browser.open("http://launchpad.test/~rosetta-admins/+leave";)
-    >>> browser.getControl(name="field.actions.leave").click()
-
-    >>> browser.open("http://launchpad.test/~rosetta-admins";)
-    >>> browser.getLink("Join the team").click()
-    >>> print(browser.url)
-    http://launchpad.test/~rosetta-admins/+join
-
-    >>> browser.getControl(name="mailinglist_subscribe")
-    Traceback (most recent call last):
-    ...
-    LookupError: name ...'mailinglist_subscribe'
-    ...
-
-Of course, the option to subscribe to the mailing list isn't present
-for teams that don't have mailing lists.
-
-    >>> browser.open("http://launchpad.test/~testing-spanish-team";)
-    >>> browser.getLink("Join the team").click()
-    >>> print(browser.url)
-    http://launchpad.test/~testing-spanish-team/+join
-
-    >>> browser.getControl(name="mailinglist_subscribe")
-    Traceback (most recent call last):
-    ...
-    LookupError: name ...'mailinglist_subscribe'
-    ...
-
-And the option is also missing from the sign-up pages of teams that
-have restricted membership.  (Note that we can only see the join page
-if we visit the URL directly, as the link is not present on the Team
-Overview.)
-
-    >>> browser.open("http://launchpad.test/~launchpad/+join";)
-    >>> print(browser.url)
-    http://launchpad.test/~launchpad/+join
-
-    >>> browser.getControl(name="mailinglist_subscribe")
-    Traceback (most recent call last):
-    ...
-    LookupError: name ...'mailinglist_subscribe'
-    ...
-
-
-Team page quick-links
-=====================
-
-Links to subscribe and unsubscribe from the mailing lists are also
-available from the team's Overview page.
-
-Carlos can see the subscribe link on the admin team's Overview
-page, because he is not subscribed to the team mailing list.
-
-    >>> carlos_browser.open("http://launchpad.test/~admins";)
-    >>> carlos_browser.getLink("Subscribe to mailing list").click()
-    >>> print(carlos_browser.url)
-    http://launchpad.test/~carlos/+editmailinglists
-
-The unsubscribe link is visible for the rosetta admins team, which
-has an active mailing list.
-
-    # Subscribe to the list using the normal technique.
-    >>> carlos_browser.open("http://launchpad.test/~carlos";)
-    >>> carlos_browser.getLink(url="+editmailinglists").click()
-    >>> rosetta_admins = carlos_browser.getControl(
-    ...     name="field.subscription.rosetta-admins"
-    ... )
-    >>> rosetta_admins.value = ["Preferred address"]
-    >>> carlos_browser.getControl("Update Subscriptions").click()
-    >>> print(rosetta_admins.value)
-    ['Preferred address']
-    >>> for tag in find_tags_by_class(
-    ...     carlos_browser.contents, "informational"
-    ... ):
-    ...     print(tag.decode_contents())
-    Subscriptions updated.
-
-    >>> carlos_browser.open("http://launchpad.test/~rosetta-admins";)
-    >>> carlos_browser.getControl("Unsubscribe")
-    <SubmitControl name='unsubscribe' type='submit'>
-
-Clicking the link will unsubscribe you from the list immediately.
-
-    >>> carlos_browser.getControl("Unsubscribe").click()
-    >>> print_feedback_messages(carlos_browser.contents)
-    You have been unsubscribed from the team mailing list.
-
-    >>> carlos_browser.open("http://launchpad.test/~rosetta-admins";)
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(carlos_browser.contents, "mailing-lists")
-    ...     )
-    ... )
-    Mailing list...
-    Subscribe to mailing list...
-
-The Ubuntu translators team, which does not have any lists configured,
-does not show either link.
-
-    >>> carlos_browser.open("http://launchpad.test/~ubuntu-translators";)
-    >>> print(
-    ...     extract_text(
-    ...         find_portlet(carlos_browser.contents, "Mailing list")
-    ...     )
-    ... )
-    Mailing list
-    Launchpad no longer supports the creation of new mailing lists.
-    Read more about it here.
-
-    >>> carlos_browser.getLink("Subscribe")
-    Traceback (most recent call last):
-    ...
-    zope.testbrowser.browser.LinkNotFoundError
-
-    >>> carlos_browser.getLink("Unsubscribe")
-    Traceback (most recent call last):
-    ...
-    zope.testbrowser.browser.LinkNotFoundError
-
-
-Team page subscribers link
-==========================
-
-Team administrators can see a link to a page listing the team's
-mailing list subscribers, if there is an active mailing list.  The
-rosetta admins team has such a list and carlos is the owner.
-
-    >>> carlos_browser.open("http://launchpad.test/~rosetta-admins";)
-    >>> print(
-    ...     extract_text(
-    ...         find_portlet(carlos_browser.contents, "Mailing list")
-    ...     )
-    ... )
-    Mailing list
-    rosetta-admins@xxxxxxxxxxxxxxxxxxxx
-    Policy: You must be a team member to subscribe to the team mailing list.
-    Subscribe to mailing list
-    View public archive
-    View subscribers...
-
-The mailing list for Rosetta Admins has no subscribers.
-(Jeff Waugh has asked to subscribe but he's not considered a subscriber
-because his membership on Rosetta Admins hasn't been approved)
-
-    >>> carlos_browser.getLink("View subscribers").click()
-    >>> print(carlos_browser.title)
-    Mailing list subscribers for the Rosetta Administrators team...
-
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(carlos_browser.contents, "subscribers")
-    ...     )
-    ... )
-    Nobody has subscribed to this team's mailing list yet.
-
-If it had subscribers, though, they'd be shown on that page, in a batched
-list.
-
-    # Forge two new subscribers to the team's mailing list.
-    >>> from lp.services.config import config
-    >>> config.push(
-    ...     "default-batch-size",
-    ...     """
-    ... [launchpad]
-    ... default_batch_size: 1
-    ... """,
-    ... )
-    >>> login("foo.bar@xxxxxxxxxxxxx")
-
-    >>> person_set = getUtility(IPersonSet)
-    >>> jdub = person_set.getByName("jdub")
-    >>> mark = person_set.getByName("mark")
-    >>> salgado = person_set.getByName("salgado")
-    >>> jordi = person_set.getByName("jordi")
-    >>> rosetta_admins = person_set.getByName("rosetta-admins")
-    >>> ignored = rosetta_admins.addMember(salgado, reviewer=mark)
-    >>> rosetta_admins.mailing_list.subscribe(salgado)
-    >>> ignored = rosetta_admins.addMember(jordi, reviewer=mark)
-    >>> rosetta_admins.mailing_list.subscribe(jordi)
-    >>> logout()
-    >>> carlos_browser.reload()
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(carlos_browser.contents, "subscribers")
-    ...     )
-    ... )
-    The following people are subscribed...
-    Guilherme Salgado
-    1 of 2 results...
-
-    >>> carlos_browser.getLink("Next").click()
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(carlos_browser.contents, "subscribers")
-    ...     )
-    ... )
-    The following people are subscribed...
-    Jordi Mallach
-    2 of 2 results...
-
-    >>> config_data = config.pop("default-batch-size")
-
-If the team has no mailing list, then the archive and subscribers
-links are not present.
-
-    >>> admin_browser.open("http://launchpad.test/~commercial-admins";)
-    >>> summary_content = extract_text(
-    ...     find_portlet(admin_browser.contents, "Mailing list")
-    ... )
-    >>> "Mailing list archive" in summary_content
-    False
-    >>> "Mailing list subscribers" in summary_content
-    False
-
-
-Mailing list auto-subscription settings
-=======================================
-
-Launchpad may automatically subscribe a person to a team's mailing
-list based on a setting in the person's Email preferences page.
-
-    >>> carlos_browser.open("http://launchpad.test/~carlos";)
-    >>> carlos_browser.getLink(url="+editmailinglists").click()
-    >>> print(backslashreplace(carlos_browser.title))
-    Change your mailing list subscriptions...
-
-Carlos's default setting, 'Ask me when I join a team', is still in place.
-
-    >>> print_radio_button_field(
-    ...     carlos_browser.contents, "mailing_list_auto_subscribe_policy"
-    ... )
-    ( ) Never subscribe to mailing lists
-    (*) Ask me when I join a team
-    ( ) Always subscribe me to mailing lists
-
-Carlos can update the value at any time using his Email Preferences
-page.
-
-    # A convenient helper for setting and submitting a new
-    # auto-subscribe policy.
-    >>> def set_autosubscribe_policy_and_submit(newvalue, current_browser):
-    ...     control = current_browser.getControl(
-    ...         name="field.mailing_list_auto_subscribe_policy"
-    ...     )
-    ...     control.value = [newvalue]
-    ...     current_browser.getControl("Update Policy").click()
-    ...     print_radio_button_field(
-    ...         current_browser.contents, "mailing_list_auto_subscribe_policy"
-    ...     )
-    ...
-
-    >>> original_value = carlos_browser.getControl(
-    ...     name="field.mailing_list_auto_subscribe_policy"
-    ... ).value.pop()
-
-    >>> set_autosubscribe_policy_and_submit("ALWAYS", carlos_browser)
-    ( ) Never subscribe to mailing lists
-    ( ) Ask me when I join a team
-    (*) Always subscribe me to mailing lists
-
-    # We only need to check this once.
-    >>> print_feedback_messages(carlos_browser.contents)
-    Your auto-subscribe policy has been updated.
-
-    >>> set_autosubscribe_policy_and_submit("NEVER", carlos_browser)
-    (*) Never subscribe to mailing lists
-    ( ) Ask me when I join a team
-    ( ) Always subscribe me to mailing lists
-
-    >>> set_autosubscribe_policy_and_submit("ON_REGISTRATION", carlos_browser)
-    ( ) Never subscribe to mailing lists
-    (*) Ask me when I join a team
-    ( ) Always subscribe me to mailing lists
-
-Updating the value twice has no adverse affect.
-
-    # Restores the original value while performing the test.
-    >>> assert original_value == "ON_REGISTRATION"
-    >>> set_autosubscribe_policy_and_submit(original_value, carlos_browser)
-    ( ) Never subscribe to mailing lists
-    (*) Ask me when I join a team
-    ( ) Always subscribe me to mailing lists
-
-Regardless of this setting, users will always receive a notification when a
-team they are a member of creates a new mailing list.  This notification
-offers them to join the new mailing list.  This page informs them of this
-behaviour.
-
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(carlos_browser.contents, "notification-info")
-    ...     )
-    ... )
-    When a team you are a member of creates a new mailing list, you will
-    receive an email notification offering you the opportunity to join the new
-    mailing list. Launchpad can also automatically subscribe you to a team's
-    mailing list whenever you join a team.
-
-These settings also effect what a user sees when they go to join a new
-team.  The 'Team Join' page has a checkbox that allows a user to sign
-up for the team mailing list at the same time as joining the
-team. Users who have chosen the 'On registration' or 'Always'
-subscription settings will see the box checked by default.
-
-    >>> login(ANONYMOUS)
-    >>> james = getUtility(IPersonSet).getByEmail(
-    ...     "james.blackwell@xxxxxxxxxxxxxxx"
-    ... )
-    >>> logout()
-    >>> browser = setupBrowserFreshLogin(james)
-    >>> browser.open("http://launchpad.test/~jblack";)
-    >>> browser.getLink(url="+editmailinglists").click()
-    >>> print_radio_button_field(
-    ...     browser.contents, "mailing_list_auto_subscribe_policy"
-    ... )
-    ( ) Never subscribe to mailing lists
-    (*) Ask me when I join a team
-    ( ) Always subscribe me to mailing lists
-
-    >>> browser.open("http://launchpad.test/~rosetta-admins";)
-    >>> browser.getLink("Join the team").click()
-    >>> print(browser.url)
-    http://launchpad.test/~rosetta-admins/+join
-
-    >>> print(browser.getControl(name="field.mailinglist_subscribe").value)
-    True
-
-    # Change James' setting
-    >>> browser.open("http://launchpad.test/~jblack";)
-    >>> browser.getLink(url="+editmailinglists").click()
-    >>> set_autosubscribe_policy_and_submit("ALWAYS", browser)
-    ( ) Never subscribe to mailing lists
-    ( ) Ask me when I join a team
-    (*) Always subscribe me to mailing lists
-
-    >>> browser.open("http://launchpad.test/~rosetta-admins";)
-    >>> browser.getLink("Join the team").click()
-    >>> print(browser.getControl(name="field.mailinglist_subscribe").value)
-    True
-
-Users who have chosen to never be auto-subscribed to mailing
-lists will not have the box checked.
-
-    # Change James' setting
-    >>> browser.open("http://launchpad.test/~jblack";)
-    >>> browser.getLink(url="+editmailinglists").click()
-    >>> set_autosubscribe_policy_and_submit("NEVER", browser)
-    (*) Never subscribe to mailing lists
-    ( ) Ask me when I join a team
-    ( ) Always subscribe me to mailing lists
-
-    >>> browser.open("http://launchpad.test/~rosetta-admins";)
-    >>> browser.getLink("Join the team").click()
-    >>> print(
-    ...     bool(browser.getControl(name="field.mailinglist_subscribe").value)
-    ... )
-    False
-
-    # Restore James' setting.
-    >>> browser.open("http://launchpad.test/~jblack";)
-    >>> browser.getLink(url="+editmailinglists").click()
-    >>> set_autosubscribe_policy_and_submit("ON_REGISTRATION", browser)
-    ( ) Never subscribe to mailing lists
-    (*) Ask me when I join a team
-    ( ) Always subscribe me to mailing lists
diff --git a/lib/lp/registry/stories/mailinglists/welcome-message.rst b/lib/lp/registry/stories/mailinglists/welcome-message.rst
deleted file mode 100644
index f49663c..0000000
--- a/lib/lp/registry/stories/mailinglists/welcome-message.rst
+++ /dev/null
@@ -1,66 +0,0 @@
-Customizing the welcome message
-===============================
-
-A team mailing list can have a custom welcome message.  The welcome message is
-customizable whether or not the mailing list is currently the team's contact
-address.
-
-    >>> login("foo.bar@xxxxxxxxxxxxx")
-    >>> team, mailing_list = factory.makeTeamAndMailingList(
-    ...     "aardvarks", "no-priv"
-    ... )
-    >>> logout()
-    >>> transaction.commit()
-
-    >>> user_browser.open("http://launchpad.test/~aardvarks";)
-    >>> user_browser.getLink("Configure mailing list").click()
-    >>> welcome_message = user_browser.getControl("Welcome message")
-    >>> print(welcome_message.value)
-    >>> welcome_message.value = "Welcome to the Aardvarks."
-    >>> user_browser.getControl("Save").click()
-
-Changes to the welcome message take effect as soon as Mailman can act on it.
-
-    >>> user_browser.getLink("Configure mailing list").click()
-    >>> welcome_message = user_browser.getControl("Welcome message")
-    >>> print(welcome_message.value)
-    Welcome to the Aardvarks.
-
-    >>> from lp.registry.tests import mailinglists_helper
-    >>> login("foo.bar@xxxxxxxxxxxxx")
-    >>> mailinglists_helper.mailman.act()
-    >>> transaction.commit()
-    >>> logout()
-
-What if Mailman failed to apply the change?
-
-    >>> welcome_message.value = "This change will fail to propagate."
-    >>> user_browser.getControl("Save").click()
-
-    # Re-fetch the mailing list, this time from the utility.
-    >>> from lp.registry.interfaces.mailinglist import IMailingListSet
-    >>> login("foo.bar@xxxxxxxxxxxxx")
-    >>> from zope.component import getUtility
-    >>> mailing_list = getUtility(IMailingListSet).get("aardvarks")
-    >>> mailing_list.status
-    <DBItem MailingListStatus.MODIFIED, (8) Modified>
-
-    # Fake a failure on the Mailman side.
-    >>> from lp.registry.interfaces.mailinglist import MailingListStatus
-    >>> from zope.security.proxy import removeSecurityProxy
-    >>> naked_list = removeSecurityProxy(mailing_list)
-    >>> removeSecurityProxy(mailing_list).status = (
-    ...     MailingListStatus.MOD_FAILED
-    ... )
-    >>> transaction.commit()
-    >>> logout()
-
-    >>> user_browser.open("http://launchpad.test/~aardvarks/+mailinglist";)
-    >>> print(
-    ...     extract_text(
-    ...         find_tag_by_id(
-    ...             user_browser.contents, "mailing_list_status_message"
-    ...         ).strong
-    ...     )
-    ... )
-    This team's mailing list is in an inconsistent state...
diff --git a/lib/lp/registry/stories/team/xx-team-contactemail.rst b/lib/lp/registry/stories/team/xx-team-contactemail.rst
index cdb27fa..c5bf89b 100644
--- a/lib/lp/registry/stories/team/xx-team-contactemail.rst
+++ b/lib/lp/registry/stories/team/xx-team-contactemail.rst
@@ -28,7 +28,7 @@ or external contact address.
     >>> from lp.services.beautifulsoup import BeautifulSoup
     >>> soup = BeautifulSoup(browser.contents)
     >>> print(soup.find(id="email-warning").decode())
-    <p ... Email sent to a mailing list or external contact address may ...
+    <p ... Email sent to an external contact address may ...
 
 As we can see, the landscape-developers team has no contact address.
 
diff --git a/lib/lp/registry/templates/team-contactaddress.pt b/lib/lp/registry/templates/team-contactaddress.pt
index 3188a65..ee86a08 100644
--- a/lib/lp/registry/templates/team-contactaddress.pt
+++ b/lib/lp/registry/templates/team-contactaddress.pt
@@ -42,14 +42,9 @@
     </metal:widgets>
 
     <div metal:fill-slot="extra_bottom">
-    <p id="set-up-a-mailing-list">
-      If you <a href="+mailinglist">set up a mailing list for this
-      team</a>, you can use the mailing list as the team contact
-      address.
-    </p>
 
     <p id="email-warning" class="block-sprite large-warning">
-        Email sent to a mailing list or external contact address may
+        Email sent to an external contact address may
         be publicly accessible.<br/>If this team is subscribed to private
         bug or branches, private information may be disclosed.<br/>
         The safest option to avoid leaking private information is to
diff --git a/lib/lp/registry/templates/team-index.pt b/lib/lp/registry/templates/team-index.pt
index 25db8f5..eb29050 100644
--- a/lib/lp/registry/templates/team-index.pt
+++ b/lib/lp/registry/templates/team-index.pt
@@ -91,7 +91,6 @@
     <!-- First portlet column. -->
     <div class="first yui-u">
       <div tal:content="structure context/@@+portlet-ppas" />
-      <div tal:content="structure context/@@+portlet-mailinglist" />
     </div>
 
     <!-- Second portlet column. -->

Follow ups