========= Archivers ========= Mailman supports pluggable archivers, and it comes with several default archivers. >>> mlist = create_list('test@example.com') >>> msg = message_from_string("""\ ... From: aperson@example.org ... To: test@example.com ... Subject: An archived message ... Message-ID: <12345> ... ... Here is an archived message. ... """) Archivers support an interface which provides the RFC 2369 List-Archive header, and one that provides a 'permalink' to the specific message object in the archive. This latter is appropriate for the message footer or for the RFC 5064 Archived-At header. Pipermail does not support a permalink, so that interface returns None. Mailman defines a draft spec for how list servers and archivers can interoperate. >>> archivers = {} >>> from operator import attrgetter >>> for archiver in sorted(config.archivers, key=attrgetter('name')): ... print archiver.name ... print ' ', archiver.list_url(mlist) ... print ' ', archiver.permalink(mlist, msg) ... archivers[archiver.name] = archiver mail-archive http://go.mail-archive.dev/test%40example.com http://go.mail-archive.dev/ZaXPPxRMM9_hFZL4vTRlQlBx8pc= mhonarc http://lists.example.com/.../test@example.com http://lists.example.com/.../RSZCG7IGPHFIRW3EMTVMMDNJMNCVCOLE pipermail http://www.example.com/pipermail/test@example.com None prototype http://lists.example.com http://lists.example.com/RSZCG7IGPHFIRW3EMTVMMDNJMNCVCOLE Sending the message to the archiver =================================== The archiver is also able to archive the message. >>> archivers['pipermail'].archive_message(mlist, msg) >>> import os >>> from mailman.interfaces.archiver import IPipermailMailingList >>> pckpath = os.path.join( ... IPipermailMailingList(mlist).archive_dir(), ... 'pipermail.pck') >>> os.path.exists(pckpath) True Note however that the prototype archiver can't archive messages. >>> archivers['prototype'].archive_message(mlist, msg) Traceback (most recent call last): ... NotImplementedError The Mail-Archive.com ==================== The Mail-Archive is a public archiver that can be used to archive message for free. Mailman comes with a plugin for this archiver; by enabling it messages to public lists will get sent there automatically. >>> archiver = archivers['mail-archive'] >>> print archiver.list_url(mlist) http://go.mail-archive.dev/test%40example.com >>> print archiver.permalink(mlist, msg) http://go.mail-archive.dev/ZaXPPxRMM9_hFZL4vTRlQlBx8pc= To archive the message, the archiver actually mails the message to a special address at the Mail-Archive. The message gets no header or footer decoration. >>> archiver.archive_message(mlist, msg) >>> from mailman.queue.outgoing import OutgoingRunner >>> from mailman.testing.helpers import make_testable_runner >>> outgoing = make_testable_runner(OutgoingRunner, 'out') >>> outgoing.run() >>> from operator import itemgetter >>> messages = list(smtpd.messages) >>> len(messages) 1 >>> print messages[0].as_string() From: aperson@example.org To: test@example.com Subject: An archived message Message-ID: <12345> X-Message-ID-Hash: ZaXPPxRMM9_hFZL4vTRlQlBx8pc= Sender: test-bounces@example.com Errors-To: test-bounces@example.com X-Peer: 127.0.0.1:... X-MailFrom: test-bounces@example.com X-RcptTo: archive@mail-archive.dev Here is an archived message. >>> smtpd.clear() However, if the mailing list is not public, the message will never be archived at this service. >>> mlist.archive_private = True >>> print archiver.list_url(mlist) None >>> print archiver.permalink(mlist, msg) None >>> archiver.archive_message(mlist, msg) >>> list(smtpd.messages) [] Additionally, this archiver can handle malformed Message-IDs. >>> mlist.archive_private = False >>> del msg['message-id'] >>> msg['Message-ID'] = '12345>' >>> print archiver.permalink(mlist, msg) http://go.mail-archive.dev/bXvG32YzcDEIVDaDLaUSVQekfo8= >>> del msg['message-id'] >>> msg['Message-ID'] = '<12345' >>> print archiver.permalink(mlist, msg) http://go.mail-archive.dev/9rockPrT1Mm-jOsLWS6_hseR_OY= >>> del msg['message-id'] >>> msg['Message-ID'] = '12345' >>> print archiver.permalink(mlist, msg) http://go.mail-archive.dev/ZaXPPxRMM9_hFZL4vTRlQlBx8pc= >>> del msg['message-id'] >>> msg['Message-ID'] = ' 12345 ' >>> print archiver.permalink(mlist, msg) http://go.mail-archive.dev/ZaXPPxRMM9_hFZL4vTRlQlBx8pc= MHonArc ======= The MHonArc archiver is also available. >>> archiver = archivers['mhonarc'] >>> print archiver.name mhonarc Messages sent to a local MHonArc instance are added to its archive via a subprocess call. >>> archiver.archive_message(mlist, msg) >>> archive_log = open(os.path.join(config.LOG_DIR, 'archiver')) >>> try: ... contents = archive_log.read() ... finally: ... archive_log.close() >>> print 'LOG:', contents LOG: ... /usr/bin/mhonarc -add -dbfile /.../private/test@example.com.mbox/mhonarc.db -outdir /.../mhonarc/test@example.com -stderr /.../logs/mhonarc -stdout /.../logs/mhonarc -spammode -umask 022 ...