1 ==========================
2 Mailing list configuration
3 ==========================
5 Mailing lists can be configured via the REST API.
7 >>> mlist = create_list('ant@example.com')
8 >>> transaction.commit()
11 Reading a configuration
12 =======================
14 All readable attributes for a list are available on a sub-resource.
16 >>> dump_json('http://localhost:9001/3.0/lists/ant@example.com/config')
17 acceptable_aliases: []
18 admin_immed_notify: True
19 admin_notify_mchanges: False
22 allow_list_posts: True
24 archive_policy: public
25 autorespond_owner: none
26 autorespond_postings: none
27 autorespond_requests: none
28 autoresponse_grace_period: 90d
29 autoresponse_owner_text:
30 autoresponse_postings_text:
31 autoresponse_request_text:
32 bounces_address: ant-bounces@example.com
33 collapse_alternatives: True
34 convert_html_to_plaintext: False
36 default_member_action: defer
37 default_nonmember_action: hold
41 digest_last_sent_at: None
42 digest_send_periodic: True
43 digest_size_threshold: 30.0
44 digest_volume_frequency: monthly
48 first_strip_reply_to: False
50 fqdn_listname: ant@example.com
54 include_rfc2369_headers: True
55 join_address: ant-join@example.com
57 leave_address: ant-leave@example.com
59 mail_host: example.com
60 moderator_password: None
62 no_reply_address: noreply@example.com
63 owner_address: ant-owner@example.com
65 posting_address: ant@example.com
66 posting_pipeline: default-posting-pipeline
67 reply_goes_to_list: no_munging
69 request_address: ant-request@example.com
70 send_welcome_message: True
72 subscription_policy: confirm
77 Changing the full configuration
78 ===============================
80 Not all of the readable attributes can be set through the web interface. The
81 ones that can, can either be set via ``PUT`` or ``PATCH``. ``PUT`` changes
82 all the writable attributes in one request.
84 When using ``PUT``, all writable attributes must be included.
86 >>> dump_json('http://localhost:9001/3.0/lists/'
87 ... 'ant@example.com/config',
89 ... acceptable_aliases=['one@example.com', 'two@example.com'],
90 ... admin_immed_notify=False,
91 ... admin_notify_mchanges=True,
92 ... administrivia=False,
94 ... anonymous_list=True,
95 ... archive_policy='never',
96 ... autorespond_owner='respond_and_discard',
97 ... autorespond_postings='respond_and_continue',
98 ... autorespond_requests='respond_and_discard',
99 ... autoresponse_grace_period='45d',
100 ... autoresponse_owner_text='the owner',
101 ... autoresponse_postings_text='the mailing list',
102 ... autoresponse_request_text='the robot',
103 ... display_name='Fnords',
104 ... description='This is my mailing list',
105 ... include_rfc2369_headers=False,
106 ... allow_list_posts=False,
107 ... digest_send_periodic=False,
108 ... digest_size_threshold=10.5,
109 ... digest_volume_frequency='yearly',
110 ... digests_enabled=False,
111 ... posting_pipeline='virgin',
112 ... filter_content=True,
113 ... first_strip_reply_to=True,
114 ... convert_html_to_plaintext=True,
115 ... collapse_alternatives=False,
116 ... reply_goes_to_list='point_to_list',
117 ... reply_to_address='bee@example.com',
118 ... send_welcome_message=False,
119 ... subject_prefix='[ant]',
120 ... subscription_policy='moderate',
121 ... default_member_action='hold',
122 ... default_nonmember_action='discard',
123 ... moderator_password='password',
128 server: WSGIServer/...
131 These values are changed permanently.
133 >>> dump_json('http://localhost:9001/3.0/lists/'
134 ... 'ant@example.com/config')
135 acceptable_aliases: ['one@example.com', 'two@example.com']
136 admin_immed_notify: False
137 admin_notify_mchanges: True
140 allow_list_posts: False
142 archive_policy: never
143 autorespond_owner: respond_and_discard
144 autorespond_postings: respond_and_continue
145 autorespond_requests: respond_and_discard
146 autoresponse_grace_period: 45d
147 autoresponse_owner_text: the owner
148 autoresponse_postings_text: the mailing list
149 autoresponse_request_text: the robot
151 collapse_alternatives: False
152 convert_html_to_plaintext: True
154 default_member_action: hold
155 default_nonmember_action: discard
156 description: This is my mailing list
158 digest_send_periodic: False
159 digest_size_threshold: 10.5
160 digest_volume_frequency: yearly
161 digests_enabled: False
164 first_strip_reply_to: True
166 fqdn_listname: ant@example.com
168 include_rfc2369_headers: False
170 moderator_password: {plaintext}password
172 posting_pipeline: virgin
173 reply_goes_to_list: point_to_list
174 reply_to_address: bee@example.com
176 send_welcome_message: False
177 subject_prefix: [ant]
178 subscription_policy: moderate
182 Changing a partial configuration
183 ================================
185 Using ``PATCH``, you can change just one attribute.
187 >>> dump_json('http://localhost:9001/3.0/lists/'
188 ... 'ant@example.com/config',
189 ... dict(display_name='My List'),
196 These values are changed permanently.
198 >>> print(mlist.display_name)
205 Mailing list configuration variables are actually available as sub-resources
206 on the mailing list. Their values can be retrieved and set through the
213 You can view the current value of the sub-resource.
215 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
216 ... '/config/display_name')
217 display_name: My List
220 The resource can be changed by PUTting to it. Note that the value still
221 requires a dictionary, and that dictionary must have a single key matching the
222 name of the resource.
225 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
226 ... '/config/display_name',
227 ... dict(display_name='Your List'),
234 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
235 ... '/config/display_name')
236 display_name: Your List
239 PATCH works the same way, with the same effect, so you can choose to use
242 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
243 ... '/config/display_name',
244 ... dict(display_name='Their List'),
251 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
252 ... '/config/display_name')
253 display_name: Their List
260 These are recipient aliases that can be used in the ``To:`` and ``CC:``
261 headers instead of the posting address. They are often used in forwarded
262 emails. By default, a mailing list has no acceptable aliases.
264 >>> from mailman.interfaces.mailinglist import IAcceptableAliasSet
265 >>> IAcceptableAliasSet(mlist).clear()
266 >>> transaction.commit()
267 >>> dump_json('http://localhost:9001/3.0/lists/'
268 ... 'ant@example.com/config/acceptable_aliases')
269 acceptable_aliases: []
272 We can add a few by ``PUT``-ing them on the sub-resource. The keys in the
273 dictionary are ignored.
275 >>> dump_json('http://localhost:9001/3.0/lists/'
276 ... 'ant@example.com/config/acceptable_aliases',
277 ... dict(acceptable_aliases=['foo@example.com',
278 ... 'bar@example.net']),
282 server: WSGIServer/...
285 Aliases are returned as a list on the ``aliases`` key.
287 >>> response = call_http(
288 ... 'http://localhost:9001/3.0/lists/'
289 ... 'ant@example.com/config/acceptable_aliases')
290 >>> for alias in response['acceptable_aliases']:
295 The mailing list has its aliases set.
297 >>> from mailman.interfaces.mailinglist import IAcceptableAliasSet
298 >>> aliases = IAcceptableAliasSet(mlist)
299 >>> for alias in sorted(aliases.aliases):
308 Mailman can do pattern based header matching during its normal rule
309 processing. Each mailing list can also be configured with a set of header
310 matching regular expression rules. These can be used to impose list-specific
311 header filtering with the same semantics as the global ``[antispam]`` section,
312 or to have a different action.
314 The list of header matches for a mailing list are returned on the
315 ``header-matches`` child of this list.
317 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
318 ... '/header-matches')
323 New header matches can be created by POSTing to the resource.
326 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
327 ... '/header-matches', {
328 ... 'header': 'X-Spam-Flag',
329 ... 'pattern': '^Yes',
333 location: .../3.0/lists/ant.example.com/header-matches/0
337 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
338 ... '/header-matches/0')
343 self_link: http://localhost:9001/3.0/lists/ant.example.com/header-matches/0
345 To follow the global antispam action, the header match rule must not specify
346 an ``action`` key, which names the chain to jump to if the rule matches. If
347 the default antispam action is changed in the configuration file and Mailman
348 is restarted, those rules will get the new jump action. If a specific action
349 is desired, the ``action`` key must name a valid chain to jump to.
352 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
353 ... '/header-matches', {
354 ... 'header': 'X-Spam-Status',
355 ... 'pattern': '^Yes',
356 ... 'action': 'discard',
360 location: .../3.0/lists/ant.example.com/header-matches/1
364 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
365 ... '/header-matches/1')
367 header: x-spam-status
371 self_link: http://localhost:9001/3.0/lists/ant.example.com/header-matches/1
373 The resource can be changed by PATCHing it. The ``position`` key can be used
374 to change the priority of the header match in the list. If it is not supplied,
375 the priority is not changed.
378 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
379 ... '/header-matches/1',
380 ... dict(pattern='^No', action='accept'),
386 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
387 ... '/header-matches/1')
389 header: x-spam-status
393 self_link: http://localhost:9001/3.0/lists/ant.example.com/header-matches/1
395 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
396 ... '/header-matches/1',
397 ... dict(position=0),
403 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
404 ... '/header-matches')
407 header: x-spam-status
411 self_link: .../lists/ant.example.com/header-matches/0
417 self_link: .../lists/ant.example.com/header-matches/1
422 The PUT method can replace an entire header match. The ``position`` key is
423 optional; if it is omitted, the order will not be changed.
426 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
427 ... '/header-matches/1',
428 ... dict(header='X-Spam-Status',
437 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
438 ... '/header-matches/1')
440 header: x-spam-status
444 self_link: http://localhost:9001/3.0/lists/ant.example.com/header-matches/1
446 A header match can be removed using the DELETE method.
449 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
450 ... '/header-matches/1',
456 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
457 ... '/header-matches')
460 header: x-spam-status
464 self_link: .../lists/ant.example.com/header-matches/0
469 The mailing list's header matches can be cleared by issuing a DELETE request on
473 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
474 ... '/header-matches',
480 >>> dump_json('http://localhost:9001/3.0/lists/ant.example.com'
481 ... '/header-matches')