Archives

Updating the archives with posted messages is handled by a separate queue, which allows for better memory management and prevents blocking the main delivery processes while messages are archived. This also allows external archivers to work in a separate process from the main Mailman delivery processes.

>>> from mailman.config import config
>>> handler = config.handlers['to-archive']
>>> from mailman.app.lifecycle import create_list
>>> mlist = create_list('_xtest@example.com')
>>> switchboard = config.switchboards['archive']

A helper function.

>>> def clear():
...     for filebase in switchboard.files:
...         msg, msgdata = switchboard.dequeue(filebase)
...         switchboard.finish(filebase)

The purpose of this handler is to make a simple decision as to whether the message should get archived and if so, to drop the message in the archiving queue. Really the most important things are to determine when a message should not get archived.

For example, no digests should ever get archived.

>>> from mailman.interfaces.archiver import ArchivePolicy
>>> mlist.archive_policy = ArchivePolicy.public
>>> from mailman.testing.helpers import (specialized_message_from_string
...   as message_from_string)
>>> msg = message_from_string("""\
... Subject: A sample message
...
... A message of great import.
... """)
>>> handler.process(mlist, msg, dict(isdigest=True))
>>> switchboard.files
[]

If the mailing list is not configured to archive, then even regular deliveries won’t be archived.

>>> mlist.archive_policy = ArchivePolicy.never
>>> handler.process(mlist, msg, {})
>>> switchboard.files
[]

There are two de-facto standards for a message to indicate that it does not want to be archived. We’ve seen both in the wild so both are supported. The X-No-Archive: header can be used to indicate that the message should not be archived. Confusingly, this header’s value is actually ignored.

>>> mlist.archive_policy = ArchivePolicy.public
>>> msg = message_from_string("""\
... Subject: A sample message
... X-No-Archive: YES
...
... A message of great import.
... """)
>>> handler.process(mlist, msg, dict(isdigest=True))
>>> switchboard.files
[]

Even a no value will stop the archiving of the message.

>>> msg = message_from_string("""\
... Subject: A sample message
... X-No-Archive: No
...
... A message of great import.
... """)
>>> handler.process(mlist, msg, dict(isdigest=True))
>>> switchboard.files
[]

Another header that’s been observed is the X-Archive: header. Here, the header’s case folded value must be no in order to prevent archiving.

>>> msg = message_from_string("""\
... Subject: A sample message
... X-Archive: No
...
... A message of great import.
... """)
>>> handler.process(mlist, msg, dict(isdigest=True))
>>> switchboard.files
[]

But if the value is yes, then the message will be archived.

>>> msg = message_from_string("""\
... Subject: A sample message
... X-Archive: Yes
...
... A message of great import.
... """)
>>> handler.process(mlist, msg, {})
>>> len(switchboard.files)
1
>>> filebase = switchboard.files[0]
>>> qmsg, qdata = switchboard.dequeue(filebase)
>>> switchboard.finish(filebase)
>>> print(qmsg.as_string())
Subject: A sample message
X-Archive: Yes

A message of great import.

>>> from mailman.testing.documentation import dump_msgdata
>>> dump_msgdata(qdata)
_parsemsg: False
version  : 3

Without either archiving header, and all other things being the same, the message will get archived.

>>> msg = message_from_string("""\
... Subject: A sample message
...
... A message of great import.
... """)
>>> handler.process(mlist, msg, {})
>>> len(switchboard.files)
1
>>> filebase = switchboard.files[0]
>>> qmsg, qdata = switchboard.dequeue(filebase)
>>> switchboard.finish(filebase)
>>> print(qmsg.as_string())
Subject: A sample message

A message of great import.

>>> dump_msgdata(qdata)
_parsemsg: False
version  : 3