summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2008-07-05 11:06:37 -0400
committerBarry Warsaw2008-07-05 11:06:37 -0400
commit08400a46afb740a0e49058707969462fa7e7dddf (patch)
tree42d18be4b2bda21680e88d5a0b19495282d4aa19
parentdda21fc619518344dfc44081c64674f6374fe404 (diff)
downloadmailman-08400a46afb740a0e49058707969462fa7e7dddf.tar.gz
mailman-08400a46afb740a0e49058707969462fa7e7dddf.tar.zst
mailman-08400a46afb740a0e49058707969462fa7e7dddf.zip
-rw-r--r--mailman/archiving/__init__.py31
-rw-r--r--mailman/archiving/mailarchive.py86
-rw-r--r--mailman/archiving/pipermail.py (renamed from mailman/app/archiving.py)100
-rw-r--r--mailman/archiving/prototype.py73
-rw-r--r--mailman/configuration.py1
-rw-r--r--mailman/docs/archivers.txt14
-rw-r--r--mailman/docs/pipelines.txt3
-rw-r--r--mailman/initialize.py2
-rw-r--r--mailman/pipeline/docs/cook-headers.txt1
-rw-r--r--mailman/tests/test_documentation.py3
-rw-r--r--setup.py8
11 files changed, 209 insertions, 113 deletions
diff --git a/mailman/archiving/__init__.py b/mailman/archiving/__init__.py
new file mode 100644
index 000000000..b9ef686a1
--- /dev/null
+++ b/mailman/archiving/__init__.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2008 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+__metaclass__ = type
+__all__ = [
+ 'initialize',
+ ]
+
+
+from mailman.app.plugins import get_plugins
+from mailman.configuration import config
+
+
+def initialize():
+ """Initialize archivers."""
+ for archiver in get_plugins('mailman.archiver'):
+ config.archivers[archiver.name] = archiver
diff --git a/mailman/archiving/mailarchive.py b/mailman/archiving/mailarchive.py
new file mode 100644
index 000000000..e1405acee
--- /dev/null
+++ b/mailman/archiving/mailarchive.py
@@ -0,0 +1,86 @@
+# Copyright (C) 2008 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+"""The Mail-Archive.com archiver."""
+
+__metaclass__ = type
+__all__ = [
+ 'MailArchive',
+ ]
+
+
+import hashlib
+
+from base64 import urlsafe_b64encode
+from urllib import quote
+from urlparse import urljoin
+from zope.interface import implements
+
+from mailman.configuration import config
+from mailman.interfaces.archiver import IArchiver
+from mailman.queue import Switchboard
+
+
+
+class MailArchive:
+ """Public archiver at the Mail-Archive.com.
+
+ Messages get archived at http://go.mail-archive.com.
+ """
+
+ implements(IArchiver)
+
+ name = 'mail-archive'
+ is_enabled = False
+
+ @staticmethod
+ def list_url(mlist):
+ """See `IArchiver`."""
+ if mlist.archive_private:
+ return None
+ return urljoin(config.MAIL_ARCHIVE_BASEURL,
+ quote(mlist.posting_address))
+
+ @staticmethod
+ def permalink(mlist, msg):
+ """See `IArchiver`."""
+ if mlist.archive_private:
+ return None
+ message_id = msg.get('message-id')
+ # It is not the archiver's job to ensure the message has a Message-ID.
+ assert message_id is not None, 'No Message-ID found'
+ # The angle brackets are not part of the Message-ID. See RFC 2822.
+ start = (1 if message_id.startswith('<') else 0)
+ end = (-1 if message_id.endswith('>') else None)
+ message_id = message_id[start:end]
+ sha = hashlib.sha1(message_id)
+ sha.update(str(mlist.post_id))
+ message_id_hash = urlsafe_b64encode(sha.digest())
+ del msg['x-message-id-hash']
+ msg['X-Message-ID-Hash'] = message_id_hash
+ return urljoin(config.MAIL_ARCHIVE_BASEURL, message_id_hash)
+
+ @staticmethod
+ def archive_message(mlist, msg):
+ """See `IArchiver`."""
+ if mlist.archive_private:
+ return
+ outq = Switchboard(config.OUTQUEUE_DIR)
+ outq.enqueue(
+ msg,
+ listname=mlist.fqdn_listname,
+ recips=[config.MAIL_ARCHIVE_RECIPIENT])
diff --git a/mailman/app/archiving.py b/mailman/archiving/pipermail.py
index 3a8e428d1..1e8f4f28e 100644
--- a/mailman/app/archiving.py
+++ b/mailman/archiving/pipermail.py
@@ -15,31 +15,24 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
-"""Application level archiving support."""
+"""Pipermail archiver."""
__metaclass__ = type
__all__ = [
'Pipermail',
- 'Prototype',
]
import os
-import hashlib
-from base64 import b32encode, urlsafe_b64encode
from cStringIO import StringIO
-from email.utils import make_msgid
from string import Template
-from urllib import quote
-from urlparse import urljoin
from zope.interface import implements
from zope.interface.interface import adapter_hooks
from mailman.configuration import config
from mailman.interfaces.archiver import IArchiver, IPipermailMailingList
from mailman.interfaces.mailinglist import IMailingList
-from mailman.queue import Switchboard
from mailman.Archiver.HyperArch import HyperArchive
@@ -114,94 +107,3 @@ class Pipermail:
fileobj.close()
# There's no good way to know the url for the archived message.
return None
-
-
-
-class Prototype:
- """A prototype of a third party archiver.
-
- Mailman proposes a draft specification for interoperability between list
- servers and archivers: <http://wiki.list.org/display/DEV/Stable+URLs>.
- """
-
- implements(IArchiver)
-
- name = 'prototype'
- is_enabled = False
-
- @staticmethod
- def list_url(mlist):
- """See `IArchiver`."""
- web_host = config.domains.get(mlist.host_name, mlist.host_name)
- return 'http://' + web_host
-
- @staticmethod
- def permalink(mlist, msg):
- """See `IArchiver`."""
- message_id = msg.get('message-id')
- # It is not the archiver's job to ensure the message has a Message-ID.
- assert message_id is not None, 'No Message-ID found'
- # The angle brackets are not part of the Message-ID. See RFC 2822.
- if message_id.startswith('<') and message_id.endswith('>'):
- message_id = message_id[1:-1]
- digest = hashlib.sha1(message_id).digest()
- message_id_hash = b32encode(digest)
- del msg['x-message-id-hash']
- msg['X-Message-ID-Hash'] = message_id_hash
- return urljoin(Prototype.list_url(mlist), message_id_hash)
-
- @staticmethod
- def archive_message(mlist, message):
- """See `IArchiver`."""
- raise NotImplementedError
-
-
-
-class MailArchive:
- """Public archiver at the Mail-Archive.com.
-
- Messages get archived at http://go.mail-archive.com.
- """
-
- implements(IArchiver)
-
- name = 'mail-archive'
- is_enabled = False
-
- @staticmethod
- def list_url(mlist):
- """See `IArchiver`."""
- if mlist.archive_private:
- return None
- return urljoin(config.MAIL_ARCHIVE_BASEURL,
- quote(mlist.posting_address))
-
- @staticmethod
- def permalink(mlist, msg):
- """See `IArchiver`."""
- if mlist.archive_private:
- return None
- message_id = msg.get('message-id')
- # It is not the archiver's job to ensure the message has a Message-ID.
- assert message_id is not None, 'No Message-ID found'
- # The angle brackets are not part of the Message-ID. See RFC 2822.
- start = (1 if message_id.startswith('<') else 0)
- end = (-1 if message_id.endswith('>') else None)
- message_id = message_id[start:end]
- sha = hashlib.sha1(message_id)
- sha.update(str(mlist.post_id))
- message_id_hash = urlsafe_b64encode(sha.digest())
- del msg['x-message-id-hash']
- msg['X-Message-ID-Hash'] = message_id_hash
- return urljoin(config.MAIL_ARCHIVE_BASEURL, message_id_hash)
-
- @staticmethod
- def archive_message(mlist, msg):
- """See `IArchiver`."""
- if mlist.archive_private:
- return
- outq = Switchboard(config.OUTQUEUE_DIR)
- outq.enqueue(
- msg,
- listname=mlist.fqdn_listname,
- recips=[config.MAIL_ARCHIVE_RECIPIENT])
diff --git a/mailman/archiving/prototype.py b/mailman/archiving/prototype.py
new file mode 100644
index 000000000..b2efbc5e0
--- /dev/null
+++ b/mailman/archiving/prototype.py
@@ -0,0 +1,73 @@
+# Copyright (C) 2008 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+"""Prototypical permalinking archiver."""
+
+__metaclass__ = type
+__all__ = [
+ 'Prototype',
+ ]
+
+
+import hashlib
+
+from base64 import b32encode
+from urlparse import urljoin
+from zope.interface import implements
+
+from mailman.configuration import config
+from mailman.interfaces.archiver import IArchiver
+
+
+
+class Prototype:
+ """A prototype of a third party archiver.
+
+ Mailman proposes a draft specification for interoperability between list
+ servers and archivers: <http://wiki.list.org/display/DEV/Stable+URLs>.
+ """
+
+ implements(IArchiver)
+
+ name = 'prototype'
+ is_enabled = False
+
+ @staticmethod
+ def list_url(mlist):
+ """See `IArchiver`."""
+ web_host = config.domains.get(mlist.host_name, mlist.host_name)
+ return 'http://' + web_host
+
+ @staticmethod
+ def permalink(mlist, msg):
+ """See `IArchiver`."""
+ message_id = msg.get('message-id')
+ # It is not the archiver's job to ensure the message has a Message-ID.
+ assert message_id is not None, 'No Message-ID found'
+ # The angle brackets are not part of the Message-ID. See RFC 2822.
+ if message_id.startswith('<') and message_id.endswith('>'):
+ message_id = message_id[1:-1]
+ digest = hashlib.sha1(message_id).digest()
+ message_id_hash = b32encode(digest)
+ del msg['x-message-id-hash']
+ msg['X-Message-ID-Hash'] = message_id_hash
+ return urljoin(Prototype.list_url(mlist), message_id_hash)
+
+ @staticmethod
+ def archive_message(mlist, message):
+ """See `IArchiver`."""
+ raise NotImplementedError
diff --git a/mailman/configuration.py b/mailman/configuration.py
index 2f682d114..8a702c457 100644
--- a/mailman/configuration.py
+++ b/mailman/configuration.py
@@ -174,6 +174,7 @@ class Configuration(object):
code = self.DEFAULT_SERVER_LANGUAGE
self.languages.enable_language(code)
# Create various registries.
+ self.archivers = {}
self.chains = {}
self.rules = {}
self.handlers = {}
diff --git a/mailman/docs/archivers.txt b/mailman/docs/archivers.txt
index 56f81b98a..edd82ba1e 100644
--- a/mailman/docs/archivers.txt
+++ b/mailman/docs/archivers.txt
@@ -24,15 +24,11 @@ Pipermail does not support a permalink, so that interface returns None.
Mailman defines a draft spec for how list servers and archivers can
interoperate.
- >>> from operator import attrgetter
- >>> name = attrgetter('name')
- >>> from mailman.app.plugins import get_plugins
- >>> archivers = {}
- >>> for archiver in sorted(get_plugins('mailman.archiver'), key=name):
+ >>> from mailman.configuration import config
+ >>> for archiver_name, archiver in sorted(config.archivers.items()):
... 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/7ekn-OQjGKjbAsD3StwtnhZ3Azk=
@@ -50,7 +46,7 @@ Sending the message to the archiver
The archiver is also able to archive the message.
>>> mlist.web_page_url = u'http://lists.example.com/'
- >>> archivers['pipermail'].archive_message(mlist, msg)
+ >>> config.archivers['pipermail'].archive_message(mlist, msg)
>>> import os
>>> from mailman.interfaces.archiver import IPipermailMailingList
@@ -62,7 +58,7 @@ The archiver is also able to archive the message.
Note however that the prototype archiver can't archive messages.
- >>> archivers['prototype'].archive_message(mlist, msg)
+ >>> config.archivers['prototype'].archive_message(mlist, msg)
Traceback (most recent call last):
...
NotImplementedError
@@ -76,7 +72,7 @@ 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']
+ >>> archiver = config.archivers['mail-archive']
>>> archiver.list_url(mlist)
'http://go.mail-archive.dev/test%40example.com'
diff --git a/mailman/docs/pipelines.txt b/mailman/docs/pipelines.txt
index 0fe51e0e4..c4f8488a1 100644
--- a/mailman/docs/pipelines.txt
+++ b/mailman/docs/pipelines.txt
@@ -21,6 +21,8 @@ Processing a message
Messages hit the pipeline after they've been accepted for posting.
+ >>> from mailman.configuration import config
+ >>> config.archivers['pipermail'].is_enabled = True
>>> msg = message_from_string("""\
... From: aperson@example.com
... To: xtest@example.com
@@ -69,7 +71,6 @@ However there are currently no recipients for this message.
And the message is now sitting in various other processing queues.
>>> from mailman.testing.helpers import get_queue_messages
- >>> from mailman.configuration import config
>>> messages = get_queue_messages(config.ARCHQUEUE_DIR)
>>> len(messages)
1
diff --git a/mailman/initialize.py b/mailman/initialize.py
index 6c2a5a8f4..d8dc0d69d 100644
--- a/mailman/initialize.py
+++ b/mailman/initialize.py
@@ -65,10 +65,12 @@ def initialize_2(debug=False):
mailman.configuration.config.db = database
# Initialize the rules and chains. Do the imports here so as to avoid
# circular imports.
+ from mailman.archiving import initialize as initialize_archivers
from mailman.app.chains import initialize as initialize_chains
from mailman.app.rules import initialize as initialize_rules
from mailman.app.pipelines import initialize as initialize_pipelines
from mailman.app.commands import initialize as initialize_commands
+ initialize_archivers()
initialize_rules()
initialize_chains()
initialize_pipelines()
diff --git a/mailman/pipeline/docs/cook-headers.txt b/mailman/pipeline/docs/cook-headers.txt
index d764bd796..4fbdf58bb 100644
--- a/mailman/pipeline/docs/cook-headers.txt
+++ b/mailman/pipeline/docs/cook-headers.txt
@@ -184,6 +184,7 @@ But normally, a list will include these headers.
>>> mlist.include_rfc2369_headers = True
>>> mlist.include_list_post_header = True
>>> mlist.preferred_language = u'en'
+ >>> config.archivers['pipermail'].is_enabled = True
>>> msg = message_from_string("""\
... From: aperson@example.com
... Message-ID: <12345>
diff --git a/mailman/tests/test_documentation.py b/mailman/tests/test_documentation.py
index e805b10fa..48c2c491c 100644
--- a/mailman/tests/test_documentation.py
+++ b/mailman/tests/test_documentation.py
@@ -79,6 +79,9 @@ def cleaning_teardown(testobj):
for message in config.db.message_store.messages:
config.db.message_store.delete_message(message['message-id'])
config.db.commit()
+ # Reset all archivers by disabling them.
+ for archiver in config.archivers.values():
+ archiver.is_enabled = False
diff --git a/setup.py b/setup.py
index e0c3a6ebc..b3523e2c7 100644
--- a/setup.py
+++ b/setup.py
@@ -91,11 +91,11 @@ Any other spelling is incorrect.""",
'console_scripts': list(scripts),
# Entry point for plugging in different database backends.
'mailman.archiver' : [
- 'pipermail = mailman.app.archiving:Pipermail',
- 'prototype = mailman.app.archiving:Prototype',
- 'mail-archive = mailman.app.archiving:MailArchive',
+ 'pipermail = mailman.archiving.pipermail:Pipermail',
+ 'prototype = mailman.archiving.prototype:Prototype',
+ 'mail-archive = mailman.archiving.mailarchive:MailArchive',
],
- 'mailman.scrubber' : 'stock = mailman.app.archiving:Pipermail',
+ 'mailman.scrubber' : 'stock = mailman.archiving.pipermail:Pipermail',
'mailman.commands' : list(commands),
'mailman.database' : 'stock = mailman.database:StockDatabase',
'mailman.mta' : 'stock = mailman.MTA:Manual',