1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
# Copyright (C) 2007 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 message storage service."""
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. This store is responsible for providing unique identifiers for
every message stored in it. A message stored in this service must have at
least a Message-ID header and a Date header. These are not guaranteed to
be unique, so the service also provides a unique sequence number to every
message.
Storing a message returns the unique sequence number for the message.
This sequence number will be stored on the message's
X-List-Sequence-Number header. Any previous such header value will be
overwritten. An X-List-ID-Hash header will also be added, containing the
Base-32 encoded SHA1 hash of the message's Message-ID and Date headers.
The combination of the X-List-ID-Hash header and the
X-List-Sequence-Number header uniquely identify this message to the
storage service. A globally unique URL that addresses this message may be
crafted from these headers and the List-Archive header as follows. For a
message with the following headers:
Message-ID: <87myycy5eh.fsf@uwakimon.sk.tsukuba.ac.jp>
Date: Wed, 04 Jul 2007 16:49:58 +0900
List-Archive: http://archive.example.com/
X-List-ID-Hash: RXTJ357KFOTJP3NFJA6KMO65X7VQOHJI
X-List-Sequence-Number: 801
the globally unique URL would be:
http://archive.example.com/RXTJ357KFOTJP3NFJA6KMO65X7VQOHJI/801
"""
def add(message):
"""Add the message to the store.
:param message: An email.message.Message instance containing at least
a Message-ID header and a Date header. The message will be given
an X-List-ID-Hash header and an X-List-Sequence-Number header.
:returns: The message's sequence ID as an integer.
:raises ValueError: if the message is missing one of the required
headers.
"""
def get_messages_by_message_id(message_id):
"""Return the set of messages with the matching Message-ID.
:param message_id: The Message-ID header contents to search for.
:returns: An iterator over all the matching messages.
"""
def get_messages_by_hash(hash):
"""Return the set of messages with the matching X-List-ID-Hash.
:param hash: The X-List-ID-Hash header contents to search for.
:returns: An iterator over all the matching messages.
"""
def get_message(global_id):
"""Return the message with the matching hash and sequence number.
:param global_id: The global relative ID which uniquely addresses this
message, relative to the base address of the message store. This
must be a string of the X-List-ID-Hash followed by a single slash
character, followed by the X-List-Sequence-Number.
:returns: The matching message, or None if there is no match.
"""
def delete_message(global_id):
"""Remove the addressed message from the store.
:param global_id: The global relative ID which uniquely addresses the
message to delete.
:raises KeyError: if there is no such message.
"""
messages = Attribute(
"""An iterator over all messages in this message store.""")
class IMessage(Interface):
"""The representation of an email message."""
hash = Attribute("""The unique SHA1 hash of the message.""")
path = Attribute("""The filesystem path to the message object.""")
message_id = Attribute("""The message's Message-ID header.""")
|