~launchpad-pqm/launchpad/devel

8137.17.26 by Barry Warsaw
When Mailman requests a mailing list for a team that Launchpad doesn't know
1
XMLRPC access to mailing list memberships
2
=========================================
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
3
4
Just like the creation and deactivation of mailing lists, membership changes
5
to mailing lists must be communicated to Mailman over XMLRPC.  Because the
6
bandwidth involved is not expected to be overwhelming, a simplified interface
7
was chosen.
8
9
The communication pattern is initiated by Mailman in all cases; in other
10
words, Mailman polls Launchpad to see if there is any work for Mailman to do.
11
12
    >>> # Note that this test is run multiple times, with the harness
4897.4.15 by Barry Warsaw
Get rid of the magic globals in the mailing list tests, except for the
13
    >>> # providing `mailinglist_api` and `commit` for impedance matching.
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
14
15
8137.17.26 by Barry Warsaw
When Mailman requests a mailing list for a team that Launchpad doesn't know
16
Requesting membership information
17
---------------------------------
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
18
19
Mailman requests membership information for specific list of teams.  Let's
20
create and populate some teams to demonstrate.
21
6130.6.3 by Maris Fogels
Rewrote the team join pages and the mailing list doctests to take the new behaviour into account.
22
    # login() as an admin so that we can call join() on anyone
23
    # and change their mailing list auto-subscription settings.
24
    >>> login('foo.bar@canonical.com')
25
7675.110.3 by Curtis Hovey
Ran the migration script to move registry code to lp.registry.
26
    >>> from lp.registry.tests.mailinglists_helper import new_team
7315.6.1 by Barry Warsaw
Refactor by moving mailinglists_helper.new_person ->
27
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
28
    >>> team_one, list_one = new_team('team-one', with_list=True)
7315.6.1 by Barry Warsaw
Refactor by moving mailinglists_helper.new_person ->
29
    >>> anne = factory.makePersonByName('Anne')
30
    >>> bart = factory.makePersonByName('Bart')
31
    >>> cris = factory.makePersonByName('Cris')
32
    >>> dirk = factory.makePersonByName('Dirk')
33
    >>> elle = factory.makePersonByName('Elle')
34
    >>> fred = factory.makePersonByName('Fred')
35
    >>> gwen = factory.makePersonByName('Gwen')
36
    >>> hank = factory.makePersonByName('Hank')
4897.3.9 by Barry Warsaw
Merge parent branch changes and similar to the parent branch, don't use sample
37
    >>> people = [anne, bart, cris, dirk, elle, fred, gwen, hank]
5643.1.1 by Guilherme Salgado
Allow the join() method to be called on teams so that team admins can propose/add their teams as members of other teams.
38
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
39
    >>> for person in people:
40
    ...     person.join(team_one)
41
    ...     list_one.subscribe(person)
8137.17.16 by Barry Warsaw
Address the XXX where we had to use the MASTER_FLAVOR in a read-only query.
42
43
    # The IMailingListSet APIs use the SLAVE_FLAVOR since they are read-only.
44
    # Commit the transaction so that the changes are visible there.
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
45
    >>> transaction.commit()
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
46
47
Asking for the membership information for team-one's list returns all the
5440.2.3 by Barry Warsaw
Fix the XMLRPC subscription tests so that the status for the subscribed
48
above people.  We want to see all the email addresses for all the people
49
subscribed to the mailing list, along with their full name. We'll also print
50
the address's flags (which will currently always be zero), and the address's
6700.3.1 by barry at canonical
Implementation of bug 193495. The substantive change is in the
51
delivery status.  A status of RECIPIENT means the address will receive
52
messages posted to the list.  A status of X means that delivery to this
53
address is suppressed.  The important point is that all addresses regardless
54
of status, will be able to post to the mailing list.
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
55
56
    >>> info = mailinglist_api.getMembershipInformation(('team-one',))
7675.110.3 by Curtis Hovey
Ran the migration script to move registry code to lp.registry.
57
    >>> from lp.registry.tests.mailinglists_helper import print_info
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
58
    >>> print_info(info)
59
    team-one
6700.3.1 by barry at canonical
Implementation of bug 193495. The substantive change is in the
60
        anne.person@example.com Anne Person             0 RECIPIENT
61
        aperson@example.org     Anne Person             0 X
62
        bart.person@example.com Bart Person             0 RECIPIENT
63
        bperson@example.org     Bart Person             0 X
64
        cperson@example.org     Cris Person             0 X
65
        cris.person@example.com Cris Person             0 RECIPIENT
66
        dirk.person@example.com Dirk Person             0 RECIPIENT
67
        dperson@example.org     Dirk Person             0 X
68
        elle.person@example.com Elle Person             0 RECIPIENT
69
        eperson@example.org     Elle Person             0 X
70
        fperson@example.org     Fred Person             0 X
71
        fred.person@example.com Fred Person             0 RECIPIENT
72
        gperson@example.org     Gwen Person             0 X
73
        gwen.person@example.com Gwen Person             0 RECIPIENT
74
        hank.person@example.com Hank Person             0 RECIPIENT
75
        hperson@example.org     Hank Person             0 X
76
        no-priv@canonical.com   No Privileges Person    0 X
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
77
78
We can also ask for the membership information for more than one mailing list
79
at a time.  Mix things up for the fun of it.
80
81
    >>> team_two, list_two = new_team('team-two', with_list=True)
4897.3.9 by Barry Warsaw
Merge parent branch changes and similar to the parent branch, don't use sample
82
    >>> fred.leave(team_one)
83
    >>> gwen.leave(team_one)
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
84
    >>> for person in people:
4897.3.9 by Barry Warsaw
Merge parent branch changes and similar to the parent branch, don't use sample
85
    ...     if person is bart:
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
86
    ...         continue
87
    ...     person.join(team_two)
88
    ...     list_two.subscribe(person)
8137.17.16 by Barry Warsaw
Address the XXX where we had to use the MASTER_FLAVOR in a read-only query.
89
    >>> transaction.commit()
90
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
91
    >>> info = mailinglist_api.getMembershipInformation(
92
    ...     ('team-one', 'team-two'))
93
    >>> print_info(info)
4897.3.9 by Barry Warsaw
Merge parent branch changes and similar to the parent branch, don't use sample
94
    team-one
6700.3.1 by barry at canonical
Implementation of bug 193495. The substantive change is in the
95
        anne.person@example.com Anne Person             0 RECIPIENT
96
        aperson@example.org     Anne Person             0 X
97
        bart.person@example.com Bart Person             0 RECIPIENT
98
        bperson@example.org     Bart Person             0 X
99
        cperson@example.org     Cris Person             0 X
100
        cris.person@example.com Cris Person             0 RECIPIENT
101
        dirk.person@example.com Dirk Person             0 RECIPIENT
102
        dperson@example.org     Dirk Person             0 X
103
        elle.person@example.com Elle Person             0 RECIPIENT
104
        eperson@example.org     Elle Person             0 X
105
        hank.person@example.com Hank Person             0 RECIPIENT
106
        hperson@example.org     Hank Person             0 X
107
        no-priv@canonical.com   No Privileges Person    0 X
4897.3.9 by Barry Warsaw
Merge parent branch changes and similar to the parent branch, don't use sample
108
    team-two
6700.3.1 by barry at canonical
Implementation of bug 193495. The substantive change is in the
109
        anne.person@example.com Anne Person             0 RECIPIENT
110
        aperson@example.org     Anne Person             0 X
111
        cperson@example.org     Cris Person             0 X
112
        cris.person@example.com Cris Person             0 RECIPIENT
113
        dirk.person@example.com Dirk Person             0 RECIPIENT
114
        dperson@example.org     Dirk Person             0 X
115
        elle.person@example.com Elle Person             0 RECIPIENT
116
        eperson@example.org     Elle Person             0 X
117
        fperson@example.org     Fred Person             0 X
118
        fred.person@example.com Fred Person             0 RECIPIENT
119
        gperson@example.org     Gwen Person             0 X
120
        gwen.person@example.com Gwen Person             0 RECIPIENT
121
        hank.person@example.com Hank Person             0 RECIPIENT
122
        hperson@example.org     Hank Person             0 X
123
        no-priv@canonical.com   No Privileges Person    0 X
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
124
125
8137.17.26 by Barry Warsaw
When Mailman requests a mailing list for a team that Launchpad doesn't know
126
Membership tests
127
----------------
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
128
129
Mailman may also occasionally ask whether a specific email address is
130
registered with Launchpad.  It does this as a simple line-of-defense against
131
spam.  Email from addresses not registered with Launchpad are summarily
132
discarded.
133
4897.3.12 by Barry Warsaw
Updates in response to reviewer comments.
134
    >>> mailinglist_api.isRegisteredInLaunchpad('dirk.person@example.com')
135
    True
136
    >>> mailinglist_api.isRegisteredInLaunchpad('dperson@example.org')
137
    True
138
    >>> mailinglist_api.isRegisteredInLaunchpad('geddy.lee@canonical.com')
139
    False
140
141
Similarly, email addresses with an unvalidated status are not considered
142
registered either.
143
14538.1.2 by Curtis Hovey
Moved account and email address to lp.services.identity.
144
    >>> from lp.services.identity.interfaces.emailaddress import IEmailAddressSet
4897.3.12 by Barry Warsaw
Updates in response to reviewer comments.
145
    >>> emailset = getUtility(IEmailAddressSet)
14632.1.1 by William Grant
EmailAddressSet.new now infers account from person where possible. Fix redundant tests.
146
    >>> new_address = emailset.new('frederick@example.com', fred)
6246.3.18 by Guilherme Salgado
Expose attributes of IEmailAddress, IWikiName, IJabberID and IIrcID
147
    >>> new_address.email, new_address.status.title
4897.3.12 by Barry Warsaw
Updates in response to reviewer comments.
148
    (u'frederick@example.com', 'New Email Address')
6246.3.18 by Guilherme Salgado
Expose attributes of IEmailAddress, IWikiName, IJabberID and IIrcID
149
    >>> sorted((email_address.email, email_address.status.title)
4897.3.12 by Barry Warsaw
Updates in response to reviewer comments.
150
    ...        for email_address in emailset.getByPerson(fred))
151
    [(u'fperson@example.org', 'Validated Email Address'),
152
     (u'fred.person@example.com', 'Preferred Email Address'),
153
     (u'frederick@example.com', 'New Email Address')]
154
    >>> mailinglist_api.isRegisteredInLaunchpad('frederick@example.com')
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
155
    False
156
157
8137.17.26 by Barry Warsaw
When Mailman requests a mailing list for a team that Launchpad doesn't know
158
Standing tests
159
--------------
5773.2.2 by Barry Warsaw
Added IMailingListAPIView.inGoodStanding(), along with an implementation and
160
161
Mailman may also occasionally ask whether a specific email address is a
162
Launchpad member in good (or better) standing.  It does this when a non-member
163
of a mailing list tries to post to the mailing list.  By default, an address
164
not registered in Launchpad is not in good standing (even though the previous
165
membership test should always take precedence).
166
167
    >>> mailinglist_api.inGoodStanding('frederick@example.com')
168
    False
169
170
Since standing makes no sense for teams, an email address assigned to a team
171
is also not in good standing.
172
173
    >>> team_address = list(emailset.getByPerson(team_one))[0]
174
    >>> mailinglist_api.inGoodStanding(team_address.email)
175
    False
176
177
By default, Launchpad members have an unknown, and thus not good, standing.
178
179
    >>> anne.personal_standing
180
    <DBItem PersonalStanding.UNKNOWN...
181
    >>> mailinglist_api.inGoodStanding('anne.person@example.com')
182
    False
183
184
Anne is a bad person and the Launchpad administrator assigns her a poor
185
standing.
186
11692.6.2 by Curtis Hovey
Use deglober to fixing simple glob imports in doctests.
187
    >>> from lp.registry.interfaces.person import PersonalStanding
5773.2.2 by Barry Warsaw
Added IMailingListAPIView.inGoodStanding(), along with an implementation and
188
    >>> anne.personal_standing = PersonalStanding.POOR
8137.17.16 by Barry Warsaw
Address the XXX where we had to use the MASTER_FLAVOR in a read-only query.
189
    >>> transaction.commit()
190
5773.2.2 by Barry Warsaw
Added IMailingListAPIView.inGoodStanding(), along with an implementation and
191
    >>> mailinglist_api.inGoodStanding('anne.person@example.com')
192
    False
193
194
Anne makes amends and the Launchpad administrator improves her standing.
195
196
    >>> anne.personal_standing = PersonalStanding.GOOD
8137.17.16 by Barry Warsaw
Address the XXX where we had to use the MASTER_FLAVOR in a read-only query.
197
    >>> transaction.commit()
198
5773.2.2 by Barry Warsaw
Added IMailingListAPIView.inGoodStanding(), along with an implementation and
199
    >>> mailinglist_api.inGoodStanding('anne.person@example.com')
200
    True
201
202
It turns out that Anne is a wonderful person!  Her standing is really
203
excellent.
204
205
    >>> anne.personal_standing = PersonalStanding.EXCELLENT
8137.17.16 by Barry Warsaw
Address the XXX where we had to use the MASTER_FLAVOR in a read-only query.
206
    >>> transaction.commit()
207
5773.2.2 by Barry Warsaw
Added IMailingListAPIView.inGoodStanding(), along with an implementation and
208
    >>> mailinglist_api.inGoodStanding('anne.person@example.com')
209
    True
210
211
8137.17.26 by Barry Warsaw
When Mailman requests a mailing list for a team that Launchpad doesn't know
212
The archive address
213
-------------------
5440.2.7 by Barry Warsaw
Bug 181771; add archive@mail-archive.com to all team mailing list recipients
214
215
We archive messages by sending them to The Mail Archive
216
<http://www.mail-archive.com>.  They automatically determine which list a
217
message is posted to so all we need to do is include them in the recipients
218
list and the rest is taken care of.
219
14605.1.1 by Curtis Hovey
Moved canonical.config to lp.services.
220
    >>> from lp.services.config import config
5440.2.7 by Barry Warsaw
Bug 181771; add archive@mail-archive.com to all team mailing list recipients
221
    >>> config.mailman.archive_address
222
    'archive@mail-archive.dev'
223
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
224
Every public team should have this address as an enabled recipient.  There is
225
no real name for this member.
5440.2.7 by Barry Warsaw
Bug 181771; add archive@mail-archive.com to all team mailing list recipients
226
6514.1.2 by Barry Warsaw
Add a couple of tests for IMailingList.is_public.
227
    >>> list_one.is_public
228
    True
229
    >>> list_two.is_public
230
    True
5440.2.7 by Barry Warsaw
Bug 181771; add archive@mail-archive.com to all team mailing list recipients
231
    >>> info = mailinglist_api.getMembershipInformation(
232
    ...     ('team-one', 'team-two'))
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
233
    >>> print_info(info, full=True)
234
    team-one
6700.3.1 by barry at canonical
Implementation of bug 193495. The substantive change is in the
235
        anne.person@example.com   Anne Person           0 RECIPIENT
236
        aperson@example.org       Anne Person           0 X
237
        archive@mail-archive.dev  (n/a)                 0 RECIPIENT
238
        bart.person@example.com   Bart Person           0 RECIPIENT
239
        bperson@example.org       Bart Person           0 X
240
        cperson@example.org       Cris Person           0 X
241
        cris.person@example.com   Cris Person           0 RECIPIENT
242
        dirk.person@example.com   Dirk Person           0 RECIPIENT
243
        dperson@example.org       Dirk Person           0 X
244
        elle.person@example.com   Elle Person           0 RECIPIENT
245
        eperson@example.org       Elle Person           0 X
246
        hank.person@example.com   Hank Person           0 RECIPIENT
247
        hperson@example.org       Hank Person           0 X
248
        no-priv@canonical.com     No Privileges Person  0 X
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
249
    team-two
6700.3.1 by barry at canonical
Implementation of bug 193495. The substantive change is in the
250
        anne.person@example.com   Anne Person           0 RECIPIENT
251
        aperson@example.org       Anne Person           0 X
252
        archive@mail-archive.dev  (n/a)                 0 RECIPIENT
253
        cperson@example.org       Cris Person           0 X
254
        cris.person@example.com   Cris Person           0 RECIPIENT
255
        dirk.person@example.com   Dirk Person           0 RECIPIENT
256
        dperson@example.org       Dirk Person           0 X
257
        elle.person@example.com   Elle Person           0 RECIPIENT
258
        eperson@example.org       Elle Person           0 X
259
        fperson@example.org       Fred Person           0 X
260
        fred.person@example.com   Fred Person           0 RECIPIENT
261
        gperson@example.org       Gwen Person           0 X
262
        gwen.person@example.com   Gwen Person           0 RECIPIENT
263
        hank.person@example.com   Hank Person           0 RECIPIENT
264
        hperson@example.org       Hank Person           0 X
265
        no-priv@canonical.com     No Privileges Person  0 X
5440.2.7 by Barry Warsaw
Bug 181771; add archive@mail-archive.com to all team mailing list recipients
266
267
However, in order to prevent this address from being used to forge spam onto
268
the lists, the archive address is hard-coded to not be registered in
269
Launchpad.
270
11118.2.8 by Brad Crittenden
Fixed lint
271
    >>> mailinglist_api.isRegisteredInLaunchpad(
272
    ...     config.mailman.archive_address)
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
273
    False
5440.2.7 by Barry Warsaw
Bug 181771; add archive@mail-archive.com to all team mailing list recipients
274
275
This is true even if by dumb luck the address actually gets registered in
276
Launchpad.
277
14538.1.2 by Curtis Hovey
Moved account and email address to lp.services.identity.
278
    >>> from lp.services.identity.interfaces.emailaddress import EmailAddressStatus
5440.2.7 by Barry Warsaw
Bug 181771; add archive@mail-archive.com to all team mailing list recipients
279
    >>> new_address = emailset.new(
280
    ...     config.mailman.archive_address, fred,
14632.1.1 by William Grant
EmailAddressSet.new now infers account from person where possible. Fix redundant tests.
281
    ...     EmailAddressStatus.VALIDATED)
8137.17.16 by Barry Warsaw
Address the XXX where we had to use the MASTER_FLAVOR in a read-only query.
282
    >>> transaction.commit()
283
11118.2.8 by Brad Crittenden
Fixed lint
284
    >>> mailinglist_api.isRegisteredInLaunchpad(
285
    ...     config.mailman.archive_address)
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
286
    False
287
288
The Mail Archive is only used for public team mailing lists.  If the team
289
itself is private, so is its archive, and then messages are not sent to the
6514.2.3 by Barry Warsaw
Reviewer responses.
290
archiver email address.
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
291
11716.1.12 by Curtis Hovey
Sorted imports in doctests.
292
    >>> from zope.component import queryAdapter
14606.4.12 by William Grant
privacy -> lp.services.privacy.
293
    >>> from lp.services.privacy.interfaces import IObjectPrivacy
7675.110.3 by Curtis Hovey
Ran the migration script to move registry code to lp.registry.
294
    >>> from lp.registry.interfaces.person import PersonVisibility
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
295
    >>> team_three = new_team('team-three')
296
    >>> queryAdapter(team_three, IObjectPrivacy).is_private
297
    False
6514.2.3 by Barry Warsaw
Reviewer responses.
298
299
Teams with mailing lists cannot change visibility, so the team must be made
300
private before its mailing list is created.
301
11118.2.2 by Brad Crittenden
Fixed failing tests due to removal of PMTs
302
    >>> team_three.visibility = PersonVisibility.PRIVATE
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
303
    >>> queryAdapter(team_three, IObjectPrivacy).is_private
304
    True
305
6514.2.3 by Barry Warsaw
Reviewer responses.
306
When Anne subscribes to the team-three mailing list, her validated addresses
307
are the only recipients in the list's membership information.  Because the
308
team is private, the special archive@mail-archive.dev address is not
309
included.
310
7675.110.3 by Curtis Hovey
Ran the migration script to move registry code to lp.registry.
311
    >>> from lp.registry.tests.mailinglists_helper import (
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
312
    ...     new_list_for_team)
313
    >>> list_three = new_list_for_team(team_three)
6514.1.2 by Barry Warsaw
Add a couple of tests for IMailingList.is_public.
314
    >>> list_three.is_public
315
    False
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
316
    >>> anne.join(team_three)
317
    >>> list_three.subscribe(anne)
8137.17.16 by Barry Warsaw
Address the XXX where we had to use the MASTER_FLAVOR in a read-only query.
318
    >>> transaction.commit()
319
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
320
    >>> info = mailinglist_api.getMembershipInformation(
321
    ...     ('team-one', 'team-two', 'team-three'))
322
    >>> print_info(info, full=True)
323
    team-one
6700.3.1 by barry at canonical
Implementation of bug 193495. The substantive change is in the
324
        anne.person@example.com   Anne Person           0 RECIPIENT
325
        aperson@example.org       Anne Person           0 X
326
        archive@mail-archive.dev  (n/a)                 0 RECIPIENT
327
        bart.person@example.com   Bart Person           0 RECIPIENT
328
        bperson@example.org       Bart Person           0 X
329
        cperson@example.org       Cris Person           0 X
330
        cris.person@example.com   Cris Person           0 RECIPIENT
331
        dirk.person@example.com   Dirk Person           0 RECIPIENT
332
        dperson@example.org       Dirk Person           0 X
333
        elle.person@example.com   Elle Person           0 RECIPIENT
334
        eperson@example.org       Elle Person           0 X
335
        hank.person@example.com   Hank Person           0 RECIPIENT
336
        hperson@example.org       Hank Person           0 X
337
        no-priv@canonical.com     No Privileges Person  0 X
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
338
    team-three
6700.3.1 by barry at canonical
Implementation of bug 193495. The substantive change is in the
339
        anne.person@example.com   Anne Person           0 RECIPIENT
340
        aperson@example.org       Anne Person           0 X
341
        no-priv@canonical.com     No Privileges Person  0 X
6514.1.1 by Barry Warsaw
Allow private teams to have mailing lists.
342
    team-two
6700.3.1 by barry at canonical
Implementation of bug 193495. The substantive change is in the
343
        anne.person@example.com   Anne Person           0 RECIPIENT
344
        aperson@example.org       Anne Person           0 X
345
        archive@mail-archive.dev  (n/a)                 0 RECIPIENT
346
        cperson@example.org       Cris Person           0 X
347
        cris.person@example.com   Cris Person           0 RECIPIENT
348
        dirk.person@example.com   Dirk Person           0 RECIPIENT
349
        dperson@example.org       Dirk Person           0 X
350
        elle.person@example.com   Elle Person           0 RECIPIENT
351
        eperson@example.org       Elle Person           0 X
352
        fperson@example.org       Fred Person           0 X
353
        fred.person@example.com   Fred Person           0 RECIPIENT
354
        gperson@example.org       Gwen Person           0 X
355
        gwen.person@example.com   Gwen Person           0 RECIPIENT
356
        hank.person@example.com   Hank Person           0 RECIPIENT
357
        hperson@example.org       Hank Person           0 X
358
        no-priv@canonical.com     No Privileges Person  0 X
5440.2.7 by Barry Warsaw
Bug 181771; add archive@mail-archive.com to all team mailing list recipients
359
360
8137.17.26 by Barry Warsaw
When Mailman requests a mailing list for a team that Launchpad doesn't know
361
Error cases
362
-----------
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
363
364
If Mailman requests the membership information for a team that doesn't exist,
8137.17.26 by Barry Warsaw
When Mailman requests a mailing list for a team that Launchpad doesn't know
365
the team name will have a value of None in the resulting dictionary.
4897.3.7 by Barry Warsaw
Flesh out the doctest for the mailing list subscription xmlrpc interface. Add the necessary implementation.
366
367
    >>> mailinglist_api.getMembershipInformation(('no-such-team',))
8137.17.26 by Barry Warsaw
When Mailman requests a mailing list for a team that Launchpad doesn't know
368
    {'no-such-team': None}