[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server/POP3 - IPOP3Message.py:1.1.2.1 IPOP3MessageList.py:1.1.2.1 POP3Message.py:1.1.2.1 POP3MessageList.py:1.1.2.1 IPOP3CommandHandler.py:1.1.2.2 POP3Server.py:1.1.2.2 POP3ServerChannel.py:1.1.2.2 POP3StatusMessages.py:1.1.2.2
Stephan Richter
srichter@cbu.edu
Sun, 7 Apr 2002 17:39:18 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Server/POP3
In directory cvs.zope.org:/tmp/cvs-serv25992/POP3
Modified Files:
Tag: Zope3-Server-Branch
IPOP3CommandHandler.py POP3Server.py POP3ServerChannel.py
POP3StatusMessages.py
Added Files:
Tag: Zope3-Server-Branch
IPOP3Message.py IPOP3MessageList.py POP3Message.py
POP3MessageList.py
Log Message:
I just finished the POP3 server implmentation. Right now it does only work
with Unix-like mailboxes, but is not limited to run on Unix I believe. It
will not make much sense to write the Zope connection until we have the
SMTP implemented and a MailMessageService has been written.
Please try the code and let me know what could be improved. BTW, I tested
the server with Eudora and it worked great, which included teh APOP authen-
tication mechanism!
=== Added File Zope3/lib/python/Zope/Server/POP3/IPOP3Message.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: IPOP3Message.py,v 1.1.2.1 2002/04/07 21:39:16 srichter Exp $
"""
from Interface import Interface
class IPOP3Message(Interface):
"""THis interface describes the methods that are expected of a
message by the POP3 server.
"""
def isDeleted():
"""Return the 'deleted' status of the message.
"""
def setDeleted(deleted=1):
"""Set the message as delted or not-deleted.
"""
def getEntireMessage():
"""Return the entire message, including headers.
"""
def getBody():
"""Return only the body of the message.
"""
def getSize():
"""Return the size of the message in octets.
"""
def getUID():
"""Get a unique id, following th eguidelines given in the POP3 RFC
in the UIDL section.
"""
=== Added File Zope3/lib/python/Zope/Server/POP3/IPOP3MessageList.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: IPOP3MessageList.py,v 1.1.2.1 2002/04/07 21:39:16 srichter Exp $
"""
from Interface import Interface
class IPOP3MessageList(Interface):
"""
"""
def open():
"""Open the mailbox and create the message list.
"""
def close():
"""Close the mailbox.
Here the messages that are marked as 'deleted' should be
removed before saving the list.
"""
def exists(index):
"""Check whether this index exists in this Message List.
"""
def getMessages():
"""Return a list of non-deleted messages.
"""
def getMessage(index):
"""Return the message of the given index.
"""
def getTotalSize():
"""Get the total size of all non-deleted messages.
"""
def getIndex(message):
"""Get the index of a particular method."""
def __getitem__(index):
"""Get the message wuth the specified 'index'.
"""
=== Added File Zope3/lib/python/Zope/Server/POP3/POP3Message.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: POP3Message.py,v 1.1.2.1 2002/04/07 21:39:16 srichter Exp $
"""
from Zope.Server.POP3.IPOP3Message import IPOP3Message
import md5
class POP3Message:
__implements__ = IPOP3Message
def __init__(self, rfc822_msg):
""" """
self.rfc822_msg = rfc822_msg
self._deleted = 0
############################################################
# Implementation methods for interface
# Zope.Server.POP3.IPOP3Message.
def isDeleted(self):
'See Zope.Server.POP3.IPOP3Message.IPOP3Message'
return self._deleted
def setDeleted(self, deleted=1):
'See Zope.Server.POP3.IPOP3Message.IPOP3Message'
self._deleted = deleted
def getEntireMessage(self):
'See Zope.Server.POP3.IPOP3Message.IPOP3Message'
self.rfc822_msg.fp.seek(0)
return self.rfc822_msg.fp.read()
def getBody(self):
'See Zope.Server.POP3.IPOP3Message.IPOP3Message'
return self.rfc822_msg.fp.read()
def getSize(self):
'See Zope.Server.POP3.IPOP3Message.IPOP3Message'
return len(self.getEntireMessage())
def getUID(self):
'See Zope.Server.POP3.IPOP3Message.IPOP3Message'
hash = md5.md5(self.getBody())
return hash.hexdigest()
#
############################################################
=== Added File Zope3/lib/python/Zope/Server/POP3/POP3MessageList.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: POP3MessageList.py,v 1.1.2.1 2002/04/07 21:39:16 srichter Exp $
"""
import mailbox
import os
from IPOP3MessageList import IPOP3MessageList
from POP3Message import POP3Message
class POP3MessageList:
__implements__ = IPOP3MessageList
def __init__(self, maildir, maildrop=None):
""" """
self.maildir = maildir
self.maildrop = maildrop
self._messagelist = []
self._mb = None
############################################################
# Implementation methods for interface
# Zope.Server.POP3.IPOP3MessageList.
def open(self, maildrop=None):
'See Zope.Server.POP3.IPOP3MessageList.IPOP3MessageList'
if maildrop is None:
maildrop = self.maildrop
else:
self.maildrop = maildrop
md_file = self.maildir.open(maildrop, 'r')
self._mb = mailbox.UnixMailbox(md_file)
msg = self._mb.next()
self._messagelist = []
while msg is not None:
self._messagelist.append(POP3Message(msg))
msg = self._mb.next()
def close(self):
'See Zope.Server.POP3.IPOP3MessageList.IPOP3MessageList'
mb_str = ''
for msg in self.getMessages():
mb_str += msg.getEntireMessage()
self._mb.fp.close()
file = self.maildir.open(self.maildrop, 'w')
file.write(mb_str)
file.close()
def exists(self, index):
'See Zope.Server.POP3.IPOP3MessageList.IPOP3MessageList'
if index > 0 and index <= len(self._messagelist):
return 1
return 0
def getMessages(self):
'See Zope.Server.POP3.IPOP3MessageList.IPOP3MessageList'
return filter(lambda msg: not msg.isDeleted(), self._messagelist)
def getMessage(self, index):
'See Zope.Server.POP3.IPOP3MessageList.IPOP3MessageList'
return self._messagelist[index-1]
def getTotalSize(self):
'See Zope.Server.POP3.IPOP3MessageList.IPOP3MessageList'
sizes = map(lambda msg: msg.getSize(), self.getMessages())
if sizes:
return reduce(lambda x, y: x+y, sizes)
else:
return 0
def getIndex(self, message):
'See Zope.Server.POP3.IPOP3MessageList.IPOP3MessageList'
return self._messagelist.index(message) + 1
def __getitem__(self, index):
'See Zope.Server.POP3.IPOP3MessageList.IPOP3MessageList'
return self.getMessage(index)
#
############################################################
=== Zope3/lib/python/Zope/Server/POP3/IPOP3CommandHandler.py 1.1.2.1 => 1.1.2.2 ===
class IPOP3CommandHandler(Interface):
- """
+ """This interface lists the implemented POP3 commands following
+ RFC 1939. Some advanced commands specified in RFC 2449 are also
+ listed.
"""
def cmd_apop(args):
@@ -111,6 +113,46 @@
"""
+ def cmd_capa(args):
+ """CAPA
+
+ Arguments: none
+
+ Restrictions: none
+
+ Discussion:
+ An -ERR response indicates the capability command
+ is not implemented and the client will have to
+ probe for capabilities as before.
+
+ An +OK response is followed by a list of
+ capabilities, one per line. Each capability name
+ MAY be followed by a single space and a
+ space-separated list of parameters. Each
+ capability line is limited to 512 octets
+ (including the CRLF). The capability list is
+ terminated by a line containing a termination
+ octet (".") and a CRLF pair.
+
+ Possible Responses:
+ +OK -ERR
+
+ Examples:
+ C: CAPA
+ S: +OK Capability list follows
+ S: TOP
+ S: USER
+ S: SASL CRAM-MD5 KERBEROS_V4
+ S: RESP-CODES
+ S: LOGIN-DELAY 900
+ S: PIPELINING
+ S: EXPIRE 60
+ S: UIDL
+ S: IMPLEMENTATION Shlemazle-Plotz-v302
+ S: .
+
+ """
+
def cmd_dele(args):
"""DELE msg
@@ -191,6 +233,28 @@
C: LIST 3
S: -ERR no such message, only 2 messages in maildrop
"""
+
+
+ def cmd_noop(args):
+ """NOOP
+
+ Arguments: none
+
+ Restrictions:
+ may only be given in the TRANSACTION state
+
+ Discussion:
+ The POP3 server does nothing, it merely replies with a
+ positive response.
+
+ Possible Responses:
+ +OK
+
+ Examples:
+ C: NOOP
+ S: +OK
+ """
+
def cmd_pass(args):
"""PASS string
=== Zope3/lib/python/Zope/Server/POP3/POP3Server.py 1.1.2.1 => 1.1.2.2 ===
from Zope.Server.ServerBase import ServerBase
+from Zope.Server.VFS.UnixFileSystem import UnixFileSystem
+from Zope.Server.Authentication.DictionaryAuthentication import \
+ DictionaryAuthentication
+
+
class POP3Server(ServerBase):
"""Generic FTP Server"""
@@ -25,11 +30,16 @@
SERVER_IDENT = 'Zope.Server.POP3Server'
- def __init__(self, ip, port, task_dispatcher=None, adj=None, start=1,
- hit_log=None, verbose=0, socket_map=None):
- super(FTPServer, self).__init__(ip, port, task_dispatcher,
- adj, start, hit_log,
- verbose, socket_map)
+ def __init__(self, ip, port, maildir, auth, task_dispatcher=None,
+ adj=None, start=1, hit_log=None, verbose=0,
+ socket_map=None):
+
+ self.auth_source = auth
+ self.maildir = UnixFileSystem(maildir)
+
+ super(POP3Server, self).__init__(ip, port, task_dispatcher,
+ adj, start, hit_log,
+ verbose, socket_map)
if __name__ == '__main__':
@@ -39,11 +49,12 @@
td = ThreadedTaskDispatcher()
td.setThreadCount(4)
- POP3Server('', 8110, task_dispatcher=td)
+ auth_source = DictionaryAuthentication({'foo': 'bar'})
+ POP3Server('', 110, '/var/mail', auth_source, task_dispatcher=td)
try:
while 1:
asyncore.poll(5)
- print 'active channels:', POP3ServerChannel.active_channels
+ # print 'active channels:', POP3ServerChannel.active_channels
except KeyboardInterrupt:
print 'shutting down...'
td.shutdown()
=== Zope3/lib/python/Zope/Server/POP3/POP3ServerChannel.py 1.1.2.1 => 1.1.2.2 ===
import stat
import socket
+import thread
import time
+import md5
from Zope.Server.LineReceiver.LineServerChannel import LineServerChannel
from POP3StatusMessages import status_msgs
-from FileProducer import FileProducer
+from POP3MessageList import POP3MessageList
from IPOP3CommandHandler import IPOP3CommandHandler
-from PassiveAcceptor import PassiveAcceptor
-from RecvChannel import RecvChannel
-from XmitChannel import XmitChannel
class POP3ServerChannel(LineServerChannel):
@@ -37,28 +36,46 @@
__implements__ = LineServerChannel.__implements__, IPOP3CommandHandler
-
# These are the commands that are allowed without the channel being in
# "Transaction State", as the POP3 RFC calls it.
- special_commands = ('cmd_quit', 'cmd_user', 'cmd_pass')
+ special_commands = ('cmd_quit', 'cmd_apop', 'cmd_capa',
+ 'cmd_user', 'cmd_pass')
# These are the commands that are accessing the filesystem.
# Since this could be also potentially a longer process, these commands
# are also the ones that are executed in a different thread.
- thread_commands = ('cmd_apop', 'cmd_dele', 'cmd_list', 'cmd_pass',
- 'cmd_retr', 'cmd_rset', 'cmd_stat', 'cmd_top',
- 'cmd_uidl')
+ # thread_commands = ('cmd_apop', 'cmd_dele', 'cmd_list', 'cmd_pass',
+ # 'cmd_retr', 'cmd_rset', 'cmd_stat', 'cmd_top',
+ # 'cmd_uidl')
# Define the status messages
status_messages = status_msgs
+ # Deifne the factory that will create a message list object
+ message_list_factory = POP3MessageList
+
+ # Define the error message that occurs, when the reply code was not found.
+ reply_error = '-ERR Reply Code unknown: %s'
+
+ # A list of this servers capabilities
+ capa_list = ('APOP MAILBOX MD5-DISGEST', 'CAPA', 'DELE MSG-INDEX',
+ 'LIST [MSG-INDEX]', 'NOOP', 'PASS PASSWORD', 'QUIT',
+ 'RETR MSG-INDEX', 'RSET', 'STAT', 'TOP MSG-INDEX NROFLINES',
+ 'UIDL [MESG-INDEX', 'USER MAILBOX')
+
def __init__(self, server, conn, addr, adj=None, socket_map=None):
super(POP3ServerChannel, self).__init__(server, conn, addr,
adj, socket_map)
self.username = ''
self.password = ''
- self.messagelist = []
+ self.messagelist = None
+
+ self.secret = "<%d.%d.%s@%s.%s>" %( os.getpid(), thread.get_ident(),
+ str(time.clock()),
+ socket.gethostname(),
+ str(id(self)) )
+ self.reply('OK_GREETING', self.secret)
############################################################
@@ -67,21 +84,48 @@
def cmd_apop(self, args):
'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
- pass
+ if self.authenticated:
+ return self.reply('ERR_INV_STATE')
+
+ # We require the username and the MD5 hash
+ if len(args.split()) != 2:
+ return self.reply('ERR_CMD_UNKNOWN')
+
+ # Get the username and check whether the user exists
+ auth = self.server.auth_source
+ self.username, hash = args.split()
+ if not auth.hasUser(self.username):
+ return self.reply('ERR_LOGIN_MISMATCH')
+
+ # See whether we got the right MD5 hash
+ self.password = auth.getPassword(self.username)
+ expected = md5.new(self.secret + self.password).hexdigest()
+ if expected != hash:
+ return self.reply('ERR_LOGIN_MISMATCH')
+
+ self.openMessageList()
+ self.reply('OK_LOGIN')
+ self.authenticated = 1
+
+
+ def cmd_capa(self, args):
+ 'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
+ self.reply('OK_CAPA')
+ self.write('\r\n'.join(self.capa_list))
+ self.write('\r\n.\r\n')
+ self.flush()
def cmd_dele(self, args):
'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
try:
- msg_index = int(args)-1
+ msg_index = int(args)
except:
return self.reply('ERR_MSG_UNKNOWN')
- msg_list = self.messagelist
-
- if msg_index >= 0 and msg_index < len(msg_list):
+ if self.messagelist.exists(msg_index):
# mark message as deleted
- self.msg_list[msg_index].deleted = 1
+ self.messagelist[msg_index].setDeleted()
return self.reply('OK_DELETE')
return self.reply('ERR_MSG_UNKNOWN')
@@ -89,43 +133,44 @@
def cmd_list(self, args):
'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
-
- msg_list = self.messagelist
-
if args:
# A message id was passed, so let's work with it.
try:
- msg_index = int(args)-1
+ msg_index = int(args)
except:
return self.reply('ERR_MSG_UNKNOWN')
- if msg_index >= 0 and msg_index < len(msg_list):
+ if not self.messagelist.exists(msg_index):
return self.reply('ERR_MSG_UNKNOWN')
- message = msg_list[msg_index]
- self.reply('OK_SINGLE_LIST', (msg_index+1, message.size)
+ message = self.messagelist[msg_index]
+ self.reply('OK_SINGLE_LIST', (msg_index, message.getSize()))
else:
- usedbytes = self.getTotalSize(msg_list)
- total_msgs = len(map(lambda msg: not msg.deleted, msg_list))
- self.reply('OK_MSG_LIST', (len(msg_list), usedbytes))
-
- for msg in msg_list:
- if msg.deleted: continue
- self.write("%d %d\r\n" % (msg_list.index(msg)+1, msg.size))
+ self.reply('OK_MSG_LIST', (len(self.messagelist.getMessages()),
+ self.messagelist.getTotalSize()))
+
+ for msg in self.messagelist.getMessages():
+ self.write("%d %d\r\n" % (self.messagelist.getIndex(msg),
+ msg.getSize()))
self.write('.\r\n')
self.flush()
- def cmd_pass(self, args):
+ def cmd_noop(self, args):
'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
+ self.reply('OK_GENERAL')
+
+ def cmd_pass(self, args):
+ 'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
self.password = args
if self.authenticated:
return self.reply('ERR_INV_STATE')
+ # No username was specified. Use USER first
if not self.username:
return self.reply('ERR_NO_USER')
@@ -133,53 +178,50 @@
self.authenticated, message = auth.authenticate(self.username,
self.password)
if self.authenticated:
+ self.openMessageList()
self.reply('OK_LOGIN')
else:
self.reply('ERR_LOGIN_MISMATCH')
- self.close_when_done()
+ self.close()
def cmd_quit(self, args):
'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
self.reply('OK_QUIT')
- # XXX Should de;ete messages
- self.close_when_done()
+ self.closeMessageList()
+ self.close()
def cmd_retr(self, args):
'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
-
try:
- msg_index = int(args)-1
+ msg_index = int(args)
except:
return self.reply('ERR_MSG_UNKNOWN')
- msg_list = self.messagelist
-
- if msg_index >= 0 and msg_index < len(msg_list):
- # mark message as deleted
- self.write(msg.body)
- return self.reply('OK_RETR')
-
- return self.reply('ERR_MSG_UNKNOWN')
+ # Output the message quickly, so we get done.
+ if self.messagelist.exists(msg_index):
+ msg = self.messagelist.getMessage(msg_index)
+ self.reply('OK_RETR', msg.getSize())
+ self.write(msg.getEntireMessage())
+ self.write('\r\n.\r\n')
+ else:
+ return self.reply('ERR_MSG_UNKNOWN')
def cmd_rset(self, args):
'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
-
- for msg in self.messagelist):
+ for msg in self.messagelist:
# mark all messages as not-deleted
- msg.deleted = 0
+ msg.setDeleted(0)
self.reply('OK_RSET')
def cmd_stat(self, args):
'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
- usedbytes = self.getTotalSize(msg_list)
- total_msgs = len(map(lambda msg: not msg.deleted, msg_list))
-
- self.reply('OK_STAT', (total_msgs, usedbytes))
+ self.reply('OK_STAT', (self.messagelist.getTotalSize(),
+ len(self.messagelist.getMessages())) )
def cmd_top(self, args):
@@ -187,35 +229,22 @@
try:
msg_index, nroflines = args.split()
- msg_index = int(args)-1
+ msg_index = int(msg_index)
nroflines = int(nroflines)
except:
return self.reply('ERR_MSG_UNKNOWN')
- msg_list = self.messagelist
-
- if msg_index >= 0 and msg_index < len(msg_list):
- # Split message body into lines/
- lines = self.messagelist[msg_index].body.split("\r\n")
-
- found, isHeader, line = -1, 1, 0
-
- # XXX: This is too complicated. It can be done easier.
-
- while line < len(nroflines):
- if isHeader:
- # skip header lines. Header lines have a :
- if lines[line].find(':') == 0:
- isHeader = 0
- else:
- found += 1
- if found == nroflines:
- break
+ if self.messagelist.exists(msg_index):
+ # Split message body into lines
+ lines = self.messagelist[msg_index].getBody().split('\n')
+
+ # Determine the true number of lines that will be returned
+ if nroflines <= len(lines):
+ lines = lines[:nroflines]
- self.reply('OK_TOP', line)
- lines = lines[:line]
+ self.reply('OK_TOP', len(lines))
self.write("\r\n".join(lines))
- self.write('.\r\n')
+ self.write('\r\n.\r\n')
self.flush()
else:
return self.reply('ERR_MSG_UNKNOWN')
@@ -223,7 +252,28 @@
def cmd_uidl(self, args):
'See Zope.Server.POP3.IPOP3CommandHandler.IPOP3CommandHandler'
- pass
+ if args:
+ # A message id was passed, so let's work with it.
+ try:
+ msg_index = int(args)
+ except:
+ return self.reply('ERR_MSG_UNKNOWN')
+
+ if not self.messagelist.exists(msg_index):
+ return self.reply('ERR_MSG_UNKNOWN')
+
+ message = self.messagelist[msg_index]
+ self.reply('OK_SINGLE_UIDL', (msg_index, message.getUID()))
+
+ else:
+ self.reply('OK_MSG_UIDL')
+
+ for msg in self.messagelist.getMessages():
+ self.write("%i %s\r\n" % (self.messagelist.getIndex(msg),
+ msg.getUID()))
+
+ self.write('.\r\n')
+ self.flush()
def cmd_user(self, args):
@@ -232,10 +282,21 @@
if self.authenticated:
return self.reply('ERR_INV_STATE')
- if self.auth.hasUser(args):
+ if self.server.auth_source.hasUser(args):
+ self.username = args
self.reply('OK_USER', args)
else:
self.reply('ERR_NOT_USER')
#
############################################################
+
+
+ def openMessageList(self):
+ self.messagelist = self.message_list_factory(self.server.maildir)
+ self.messagelist.open(self.username)
+
+
+ def closeMessageList(self):
+ if self.messagelist is not None:
+ self.messagelist.close()
=== Zope3/lib/python/Zope/Server/POP3/POP3StatusMessages.py 1.1.2.1 => 1.1.2.2 ===
status_msgs = {
- 'OK_GENERAL' : '+OK',
- 'OK_LOGIN' : '+OK login successful',
- 'OK_USER' : '+OK %s is a valid name box',
- 'OK_QUIT' : '+OK',
- 'OK_SINGLE_LIST' : '+OK %i %i',
- 'OK_MSG_LIST' : '+OK %i message (%i octets)',
- 'OK_DELETE' : '+OK The message was successfully deleted'
- 'OK_RETR' : '+OK message follows',
- 'OK_RSET' : '+OK Resetting all messages done',
- 'OKTOP' : '+OK top %i lines of message follows',
- 'OK_APOP' : '+OK maildrop locked and ready',
- 'OK_UIDL' : '+OK unique-id listing follows',
+ 'OK_GENERAL' : '+OK',
+ 'OK_GREETING' : '+OK Zope 3 POP3 server ready %s',
+ 'OK_LOGIN' : '+OK login successful',
+ 'OK_USER' : '+OK %s is a valid mailbox',
+ 'OK_QUIT' : '+OK Connection is closing.',
+ 'OK_SINGLE_LIST' : '+OK %i %i',
+ 'OK_MSG_LIST' : '+OK %i message (%i octets)',
+ 'OK_DELETE' : '+OK The message was successfully deleted',
+ 'OK_RETR' : '+OK message follows (%i octets)',
+ 'OK_RSET' : '+OK Resetting all messages done',
+ 'OK_STAT' : '+OK %i %i',
+ 'OK_TOP' : '+OK top %i lines of message follows',
+ 'OK_APOP' : '+OK maildrop locked and ready',
+ 'OK_SINGLE_UIDL' : '+OK %i %s',
+ 'OK_MSG_UIDL' : '+OK Unique message id list follows',
+ 'OK_CAPA' : '+OK Capability list follows',
- 'ERR_CMD_UNKNOWN' : '-ERR unknown command',
- 'ERR_MSG_UNKNOWN' : '-ERR unknown or invalid message id',
- 'ERR_INV_STATE' : '-ERR Invalid State',
- 'ERR_NO_USER' : '-ERR No user was yet specified'
- 'ERR_NOT_USER' : '-ERR never heard of mailbox name',
- 'ERR_LOGIN_MISMATH' : '-ERR username and password did not match',
+ 'ERR_CMD_UNKNOWN' : '-ERR unknown command',
+ 'ERR_MSG_UNKNOWN' : '-ERR unknown or invalid message id',
+ 'ERR_INV_STATE' : '-ERR Invalid State',
+ 'ERR_NO_USER' : '-ERR No user was yet specified',
+ 'ERR_NOT_USER' : '-ERR never heard of mailbox name',
+ 'ERR_LOGIN_MISMATCH' : '-ERR username and password did not match',
+
+ 'CMD_UNKNOWN' : '-ERR %s command unknown',
+ 'LOGIN_REQUIRED' : '-ERR Not yet logged in.',
}