Moderator requests

Various actions will be held for moderator approval, such as subscriptions to closed lists, or postings by non-members. The requests database is the low level interface to these actions requiring approval.

An application level interface for holding messages and membership changes is also available.

Mailing list-centric

A set of requests are always related to a particular mailing list. Adapt the mailing list to get its requests.

>>> from mailman.interfaces.requests import IListRequests
>>> from zope.interface.verify import verifyObject

>>> mlist = create_list('')
>>> requests = IListRequests(mlist)
>>> verifyObject(IListRequests, requests)
>>> requests.mailing_list
<mailing list "" at ...>

Holding requests

The list’s requests database starts out empty.

>>> print(requests.count)
>>> dump_list(requests.held_requests)

At the lowest level, the requests database is very simple. Holding a request requires a request type (as an enum value), a key, and an optional dictionary of associated data. The request database assigns no semantics to the held data, except for the request type.

>>> from mailman.interfaces.requests import RequestType

We can hold messages for moderator approval.

>>> requests.hold_request(RequestType.held_message, 'hold_1')

We can hold subscription requests for moderator approval.

>>> requests.hold_request(RequestType.subscription, 'hold_2')

We can hold unsubscription requests for moderator approval.

>>> requests.hold_request(RequestType.unsubscription, 'hold_3')

Getting requests

We can see the total number of requests being held.

>>> print(requests.count)

We can also see the number of requests being held by request type.

>>> print(requests.count_of(RequestType.subscription))
>>> print(requests.count_of(RequestType.unsubscription))

We can also see when there are multiple held requests of a particular type.

>>> print(requests.hold_request(RequestType.held_message, 'hold_4'))
>>> print(requests.count_of(RequestType.held_message))

We can ask the requests database for a specific request, by providing the id of the request data we want. This returns a 2-tuple of the key and data we originally held.

>>> key, data = requests.get_request(2)
>>> print(key)

There was no additional data associated with request 2.

>>> print(data)

If we ask for a request that is not in the database, we get None back.

>>> print(requests.get_request(801))

Additional data

When a request is held, additional data can be associated with it, in the form of a dictionary with string values.

>>> data = dict(foo='yes', bar='no')
>>> requests.hold_request(RequestType.held_message, 'hold_5', data)

The data is returned when the request is retrieved. The dictionary will have an additional key which holds the name of the request type.

>>> key, data = requests.get_request(5)
>>> print(key)
>>> dump_msgdata(data)
_request_type: held_message
bar          : no
foo          : yes

Iterating over requests

To make it easier to find specific requests, the list requests can be iterated over by type.

>>> print(requests.count_of(RequestType.held_message))
>>> for request in requests.of_type(RequestType.held_message):
...     key, data = requests.get_request(
...     print(, request.request_type, key)
...     if data is not None:
...         for key in sorted(data):
...             print('    {0}: {1}'.format(key, data[key]))
1 RequestType.held_message hold_1
4 RequestType.held_message hold_4
5 RequestType.held_message hold_5
    _request_type: held_message
    bar: no
    foo: yes

Deleting requests

Once a specific request has been handled, it can be deleted from the requests database.

>>> print(requests.count)
>>> requests.delete_request(2)
>>> print(requests.count)

Request 2 is no longer in the database.

>>> print(requests.get_request(2))
>>> for request in requests.held_requests:
...     requests.delete_request(
>>> print(requests.count)