On Fri, 2012-06-01 at 21:33 -0400, Barry Warsaw wrote: > * Look at the IMessageStore API. Is this complete? IOW, could you > build a purely Python-level archiver like HyperKitty on top of this > API? Here's where proper attachment handling would probably be > necessary.
With the help of wacky on #mailman this week-end we came up with this "patch". Attached is both the diff and the file itself. This way we can start discussing :) Pierre
=== modified file 'src/mailman/interfaces/messages.py' --- src/mailman/interfaces/messages.py 2012-01-01 19:14:46 +0000 +++ src/mailman/interfaces/messages.py 2012-06-03 16:23:46 +0000 @@ -65,35 +65,125 @@ def add(message): """Add the message to the store. - :param message: An email.message.Message instance containing at least - a unique Message-ID header. The message will be given an - X-Message-ID-Hash header, overriding any existing such header. - :returns: The calculated X-Message-ID-Hash header. - :raises ValueError: if the message is missing a Message-ID header. - The storage service is also allowed to raise this exception if it - find, but disallows collisions. - """ - - def get_message_by_id(message_id): - """Return the message with a matching Message-ID. - - :param message_id: The Message-ID header contents to search for. - :returns: The message, or None if no matching message was found. - """ - - def get_message_by_hash(message_id_hash): - """Return the message with the matching X-Message-ID-Hash. - - :param message_id_hash: The X-Message-ID-Hash header contents to - search for. - :returns: The message, or None if no matching message was found. + :param message: An email.message.Message instance containing at + least a unique Message-ID header. The message will be given + an X-Message-ID-Hash header, overriding any existing such + header. + :returns: The calculated X-Message-ID-Hash header. + :raises ValueError: if the message is missing a Message-ID + header. + The storage service is also allowed to raise this exception + if it find, but disallows collisions. + """ + + def add_to_list(list_name, message): + """Add the message to a specific list of the store. + + :param list_name: The fully qualified list name to which the + message should be added. + :param message: An email.message.Message instance containing at + least a unique Message-ID header. The message will be given + an X-Message-ID-Hash header, overriding any existing such + header. + :returns: The calculated X-Message-ID-Hash header. + :raises ValueError: if the message is missing a Message-ID + header. + The storage service is also allowed to raise this exception + if it find, but disallows collisions. """ def delete_message(message_id): """Remove the given message from the store. - :param message: The Message-ID of the mesage to delete from the store. - :raises LookupError: if there is no such message. + :param message: The Message-ID of the mesage to delete from the + store. + :raises LookupError: if there is no such message. + """ + + def delete_message_from_list(list_name, message_id): + """Remove the given message for a specific list from the store. + + :param list_name: The fully qualified list name to which the + message should be added. + :param message: The Message-ID of the mesage to delete from the + store. + :raises LookupError: if there is no such message. + """ + + def get_list_size(list_name): + """ Return the number of emails stored for a given mailing list. + + :arg list_name, name of the mailing list in which this email + should be searched. + """ + + def get_message_by_hash(message_id_hash): + """Return the message with the matching X-Message-ID-Hash. + + :param message_id_hash: The X-Message-ID-Hash header contents to + search for. + :returns: The message, or None if no matching message was found. + """ + + def get_message_by_hash_from_list(list_name, message_id_hash): + """Return the message with the matching X-Message-ID-Hash. + + :param message_id_hash: The X-Message-ID-Hash header contents to + search for. + :returns: The message, or None if no matching message was found. + """ + + def get_message_by_id(message_id): + """Return the message with a matching Message-ID. + + :param message_id: The Message-ID header contents to search for. + :returns: The message, or None if no matching message was found. + """ + + def get_message_by_id_from_list(list_name, message_id): + """Return the message with a matching Message-ID. + + :param list_name: The fully qualified list name to which the + message should be added. + :param message_id: The Message-ID header contents to search for. + :returns: The message, or None if no matching message was found. + """ + + def search_list_for_content(list_name, keyword): + """ Returns a list of email containing the specified keyword in + their content. + + :param list_name: name of the mailing list in which this email + should be searched. + :param keyword: keyword to search in the content of the emails. + """ + + def search_list_for_content_subject(list_name, keyword): + """ Returns a list of email containing the specified keyword in + their content or their subject. + + :param list_name: name of the mailing list in which this email + should be searched. + :param keyword: keyword to search in the content or subject of + the emails. + """ + + def search_list_for_sender(list_name, keyword): + """ Returns a list of email containing the specified keyword in + the name or email address of the sender of the email. + + :param list_name: name of the mailing list in which this email + should be searched. + :param keyword: keyword to search in the database. + """ + + def search_list_for_subject(list_name, keyword): + """ Returns a list of email containing the specified keyword in + their subject. + + :param list_name: name of the mailing list in which this email + should be searched. + :param keyword: keyword to search in the subject of the emails. """ messages = Attribute(
# Copyright (C) 2007-2012 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman 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 3 of the License, or (at your option) # any later version. # # GNU Mailman 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 # GNU Mailman. If not, see <http://www.gnu.org/licenses/>. """The message storage service.""" from __future__ import absolute_import, unicode_literals __metaclass__ = type __all__ = [ 'IMessage', 'IMessageStore', ] from zope.interface import Interface, Attribute class IMessageStore(Interface): """The interface of the global message storage service. All messages that are stored in the system live in the message storage service. A message stored in this service must have a Message-ID header. The store writes an X-Message-ID-Hash header which contains the Base32 encoded SHA1 hash of the message's Message-ID header. Any existing X-Message-ID-Hash header is overwritten. Either the Message-ID or the X-Message-ID-Hash header can be used to uniquely identify this message in the storage service. While it is possible to see duplicate Message-IDs, this is never correct and the service is allowed to drop any subsequent colliding messages, or overwrite earlier messages with later ones. The combination of the List-Archive header and either the Message-ID or X-Message-ID-Hash header can be used to retrieve the message from the internet facing interface for the message store. This can be considered a globally unique URI to the message. For example, a message with the following headers: Message-ID: <87myycy5eh....@uwakimon.sk.tsukuba.ac.jp> Date: Wed, 04 Jul 2007 16:49:58 +0900 List-Archive: http://archive.example.com/ X-Message-ID-Hash: RXTJ357KFOTJP3NFJA6KMO65X7VQOHJI the globally unique URI would be: http://archive.example.com/RXTJ357KFOTJP3NFJA6KMO65X7VQOHJI """ def add(message): """Add the message to the store. :param message: An email.message.Message instance containing at least a unique Message-ID header. The message will be given an X-Message-ID-Hash header, overriding any existing such header. :returns: The calculated X-Message-ID-Hash header. :raises ValueError: if the message is missing a Message-ID header. The storage service is also allowed to raise this exception if it find, but disallows collisions. """ def add_to_list(list_name, message): """Add the message to a specific list of the store. :param list_name: The fully qualified list name to which the message should be added. :param message: An email.message.Message instance containing at least a unique Message-ID header. The message will be given an X-Message-ID-Hash header, overriding any existing such header. :returns: The calculated X-Message-ID-Hash header. :raises ValueError: if the message is missing a Message-ID header. The storage service is also allowed to raise this exception if it find, but disallows collisions. """ def delete_message(message_id): """Remove the given message from the store. :param message: The Message-ID of the mesage to delete from the store. :raises LookupError: if there is no such message. """ def delete_message_from_list(list_name, message_id): """Remove the given message for a specific list from the store. :param list_name: The fully qualified list name to which the message should be added. :param message: The Message-ID of the mesage to delete from the store. :raises LookupError: if there is no such message. """ def get_list_size(list_name): """ Return the number of emails stored for a given mailing list. :arg list_name, name of the mailing list in which this email should be searched. """ def get_message_by_hash(message_id_hash): """Return the message with the matching X-Message-ID-Hash. :param message_id_hash: The X-Message-ID-Hash header contents to search for. :returns: The message, or None if no matching message was found. """ def get_message_by_hash_from_list(list_name, message_id_hash): """Return the message with the matching X-Message-ID-Hash. :param message_id_hash: The X-Message-ID-Hash header contents to search for. :returns: The message, or None if no matching message was found. """ def get_message_by_id(message_id): """Return the message with a matching Message-ID. :param message_id: The Message-ID header contents to search for. :returns: The message, or None if no matching message was found. """ def get_message_by_id_from_list(list_name, message_id): """Return the message with a matching Message-ID. :param list_name: The fully qualified list name to which the message should be added. :param message_id: The Message-ID header contents to search for. :returns: The message, or None if no matching message was found. """ def search_list_for_content(list_name, keyword): """ Returns a list of email containing the specified keyword in their content. :param list_name: name of the mailing list in which this email should be searched. :param keyword: keyword to search in the content of the emails. """ def search_list_for_content_subject(list_name, keyword): """ Returns a list of email containing the specified keyword in their content or their subject. :param list_name: name of the mailing list in which this email should be searched. :param keyword: keyword to search in the content or subject of the emails. """ def search_list_for_sender(list_name, keyword): """ Returns a list of email containing the specified keyword in the name or email address of the sender of the email. :param list_name: name of the mailing list in which this email should be searched. :param keyword: keyword to search in the database. """ def search_list_for_subject(list_name, keyword): """ Returns a list of email containing the specified keyword in their subject. :param list_name: name of the mailing list in which this email should be searched. :param keyword: keyword to search in the subject of the emails. """ messages = Attribute( """An iterator over all messages in this message store.""") class IMessage(Interface): """The representation of an email message.""" message_id = Attribute("""The message's Message-ID header.""") message_id_hash = Attribute("""The unique SHA1 hash of the message.""") path = Attribute("""The filesystem path to the message object.""")
_______________________________________________ Mailman-Developers mailing list Mailman-Developers@python.org http://mail.python.org/mailman/listinfo/mailman-developers Mailman FAQ: http://wiki.list.org/x/AgA3 Searchable Archives: http://www.mail-archive.com/mailman-developers%40python.org/ Unsubscribe: http://mail.python.org/mailman/options/mailman-developers/archive%40jab.org Security Policy: http://wiki.list.org/x/QIA9