Post Moderation
Messages which are held for approval can be accepted, rejected, discarded, or deferred by the list moderators.
Viewing the list of held messages
Held messages can be moderated through the REST API. A mailing list starts with no held messages.
>>> from mailman.app.lifecycle import create_list
>>> ant = create_list('ant@example.com')
>>> from mailman.config import config
>>> transaction = config.db
>>> transaction.commit()
>>> from mailman.testing.documentation import dump_json
>>> dump_json('http://localhost:9001/3.0/lists/ant@example.com/held')
http_etag: "..."
start: 0
total_size: 0
When a message gets held for moderator approval, it shows up in this list.
>>> from mailman.testing.helpers import (specialized_message_from_string
... as message_from_string)
>>> msg = message_from_string("""\
... From: anne@example.com
... To: ant@example.com
... Subject: Something
... Message-ID: <alpha>
...
... Something else.
... """)
>>> from mailman.app.moderator import hold_message
>>> request_id = hold_message(ant, msg, {'extra': 7}, 'Because')
>>> transaction.commit()
>>> dump_json('http://localhost:9001/3.0/lists/ant@example.com/held')
entry 0:
extra: 7
hold_date: 2005-08-01T07:49:23
http_etag: "..."
message_id: <alpha>
msg: From: anne@example.com
To: ant@example.com
Subject: Something
Message-ID: <alpha>
Message-ID-Hash: XZ3DGG4V37BZTTLXNUX4NABB4DNQHTCP
X-Message-ID-Hash: XZ3DGG4V37BZTTLXNUX4NABB4DNQHTCP
Something else.
original_subject: Something
reason: Because
request_id: 1
self_link: http://localhost:9001/3.0/lists/ant.example.com/held/1
sender: anne@example.com
subject: Something
http_etag: "..."
start: 0
total_size: 1
A simple count of the held messages is also available:
>>> dump_json('http://localhost:9001/3.0/lists/ant@example.com/held/count')
count: 1
http_etag: "..."
You can get an individual held message by providing the request id for that message. This will include the text of the message.
>>> def url(request_id):
... return ('http://localhost:9001/3.0/lists/'
... 'ant@example.com/held/{0}'.format(request_id))
>>> dump_json(url(request_id))
extra: 7
hold_date: 2005-08-01T07:49:23
http_etag: "..."
message_id: <alpha>
msg: From: anne@example.com
To: ant@example.com
Subject: Something
Message-ID: <alpha>
Message-ID-Hash: XZ3DGG4V37BZTTLXNUX4NABB4DNQHTCP
X-Message-ID-Hash: XZ3DGG4V37BZTTLXNUX4NABB4DNQHTCP
Something else.
original_subject: Something
reason: Because
request_id: 1
self_link: http://localhost:9001/3.0/lists/ant.example.com/held/1
sender: anne@example.com
subject: Something
Disposing of held messages
Individual messages can be moderated through the API by POSTing back to the held message’s resource. The POST data requires an action of one of the following:
discard - throw the message away.
reject - bounces the message back to the original author.
defer - defer any action on the message (continue to hold it)
accept - accept the message for posting.
Let’s see what happens when the above message is deferred.
>>> dump_json(url(request_id), {
... 'action': 'defer',
... })
date: ...
server: ...
status: 204
The message is still in the moderation queue.
>>> dump_json(url(request_id))
extra: 7
hold_date: 2005-08-01T07:49:23
http_etag: "..."
message_id: <alpha>
msg: From: anne@example.com
To: ant@example.com
Subject: Something
Message-ID: <alpha>
Message-ID-Hash: XZ3DGG4V37BZTTLXNUX4NABB4DNQHTCP
X-Message-ID-Hash: XZ3DGG4V37BZTTLXNUX4NABB4DNQHTCP
Something else.
original_subject: Something
reason: Because
request_id: 1
self_link: http://localhost:9001/3.0/lists/ant.example.com/held/1
sender: anne@example.com
subject: Something
The held message can be discarded.
>>> dump_json(url(request_id), {
... 'action': 'discard',
... })
date: ...
server: ...
status: 204
Messages can also be accepted via the REST API. Let’s hold a new message for moderation.
>>> del msg['message-id']
>>> msg['Message-ID'] = '<bravo>'
>>> request_id = hold_message(ant, msg)
>>> transaction.commit()
>>> from mailman.testing.documentation import call_http
>>> results = call_http(url(request_id))
>>> print(results['message_id'])
<bravo>
>>> dump_json(url(request_id), {
... 'action': 'accept',
... })
date: ...
server: ...
status: 204
>>> from mailman.testing.helpers import get_queue_messages
>>> messages = get_queue_messages('pipeline')
>>> len(messages)
1
>>> print(messages[0].msg['message-id'])
<bravo>
Messages can be rejected via the REST API too. These bounce the message back to the original author.
>>> del msg['message-id']
>>> msg['Message-ID'] = '<charlie>'
>>> request_id = hold_message(ant, msg)
>>> transaction.commit()
>>> results = call_http(url(request_id))
>>> print(results['message_id'])
<charlie>
>>> dump_json(url(request_id), {
... 'action': 'reject',
... })
date: ...
server: ...
status: 204
>>> from mailman.testing.helpers import get_queue_messages
>>> messages = get_queue_messages('virgin')
>>> len(messages)
1
>>> print(messages[0].msg['subject'])
Request to mailing list "Ant" rejected
The subject of the message is decoded and the original subject is accessible
under original_subject
.
>>> msg = message_from_string("""\
... From: anne@example.com
... To: ant@example.com
... Subject: =?iso-8859-1?q?p=F6stal?=
... Message-ID: <beta>
...
... Something else.
... """)
>>> from mailman.app.moderator import hold_message
>>> request_id = hold_message(ant, msg, {'extra': 7}, 'Because')
>>> transaction.commit()
>>> results = call_http(url(request_id))
>>> print(results['subject'])
pöstal
>>> print(results['original_subject'])
=?iso-8859-1?q?p=F6stal?=
Forwarding of Held message
When disposing held message, the message can be forwarded to a different address.
>>> msg = message_from_string("""\
... From: anne@example.com
... To: ant@example.com
... Subject: =?iso-8859-1?q?p=F6stal?=
... Message-ID: <beta>
...
... Something else.
... """)
>>> from mailman.app.moderator import hold_message
>>> request_id = hold_message(ant, msg, {'extra': 7}, 'Because')
>>> transaction.commit()
Now, when handling the request, we can forward the message to bee@example.com
>>> dump_json(url(request_id), {
... 'action': 'discard',
... 'forward': ['bee@example.com']
... })
date: ...
server: ...
status: 204
>>> messages = get_queue_messages('virgin')
>>> len(messages)
1
>>> print(messages[0].msg['subject'])
Forward of moderated message
>>> print(messages[0].msg['To'])
bee@example.com