Hier vielleicht mal ein kleiner Ausschnitt Code, falls es nützt. Momentan ist nur quit implementiert und wenn ich das clientseitig aufrufe hängt er. Also muss da ein Socket blockieren, was mir gar nicht lieb ist...
Es wird automatisch vom Server aus setup, dann handle und dann finish gerufen, aber das dürfte nebensache sein, da das der Server regelt (SocketServer.ThreadingTCPServer). In self.request steckt der Socket, der mit dem Client verbunden ist.
Code: Alles auswählen
class POP3Session(SocketServer.BaseRequestHandler):
"""One POP3 Session from login to quit"""
greeting="PyEC POP3 server ready"
goodbye="PyEC POP3 server signing off"
states = { "AUTHORIZATION":0, "TRANSACTION":1, "UPDATE":2 }
def echo(self,message):
"""override this to (for example) log to a file"""
pass
def _response(self,s):
self.request.send("%s%s" % (s, CRLF))
self.echo(s)
def _pos_response(self,s):
self._response("+OK %s" % s)
def _neg_response(self,s):
self._response("-ERR %s" % s)
def setup(self):
lookup= { "QUIT":(self.quit, (0,1,2)),
"STAT":(self.stat, (1,)),
"LIST":(self.list, (1,)),
"RETR":(self.retr, (1,)),
"DELE":(self.dele, (1,)),
"NOOP":(self.noop, (1,)),
"RSET":(self.rset, (1,)),
"TOP":(self.top, (1,)),
"UIDL":(self.uidl, (1,)),
"USER":(self.user, (0,)),
"PASS":(self.pass_, (0,)),
"APOP":(self.apop, (0,)) }
self.state=self.states["AUTHORIZATION"]
timestamp=md5.new(time.ctime())
for i in xrange(random.randint(1,11)):
timestamp.update(str(random.random()))
self.timestamp=timestamp.hexdigest()
del timestamp
self.lastcmd=""
self.state_of_last_cmd=""
self.request.settimeout(options.get("timeout",None))
self.rfile=self.request.makefile("rb",-1)
def handle(self):
self.echo("connected by %s on port %s\n" % self.client_address)
self._pos_response("%s <%s>" % (self.greeting, self.timestamp))
while 1:
command_line=self.rfile.readline()
if (not command_line): break # connection closed at client end?
command_split = command_line.split()
command = command_split[0].upper()
self.echo("%s: %s" % (self.peername, command_line))
if command == "QUIT":
self.quit()
break
# Do what the command asks, if there is a method to do it.
if self.lookup.has_key(command):
try:
handle_cmd, allowed_states = self.lookup[command]
if self.state in allowed_states:
self.state_of_last_cmd = handle_cmd(command_split[1:])
self.lastcmd=command
else:
self._neg_response('command "%s" not allowed in this state' % command)
except:
pass
else:
self._neg_response('unknown command: "%s"' % command)
return
def finish(self):
if self.state == self.states["UPDATE"]:
pass #update the mailbox by deleting markes emails
return
def quit(self):
self._pos_response(self.goodbye)
if self.state == self.states["TRANSACTION"]:
self.state = self.states["UPDATE"]