pop3proxy

Jp Calderone exarkun at divmod.com
Mon May 2 10:30:38 EDT 2005


On Mon, 02 May 2005 16:05:13 +0200, BrokenClock <brokenclock at free.fr> wrote:
>Hello every body,
>
>Here is a python newbie! I've choose it to make a pop3 proxy - I want to
>filter content between a pop3 client and a pop3 server, and I have no
>control on the server...
>First, I wanted to do an non-filtering, just logging, mono-thread proxy
>to make some test..
>Based on the RFC 1939 (http://www.faqs.org/rfcs/rfc1939.html) (in
>particular the item 5), I was expecting some output, but did not get it...
>In fact, I expected to see the message, but I did not see it... only the
>  command to retrieve it. On the other hand, the message is well receipt
>in my mail client.
>An other point is that all this seems to work well with short messages,
>but difficulties appear when messages go bigger. I think it is due to
>the parameter of recv, but I don't know how to set it.
>So here are my two questions:
>1-why do not I see the message in my output, and how could I do to see
>and handle it?
>2-how should I set the parameter of recv to handle big messages?

  Regardless of how large you set the parameter, you will still have to issue multiple recv() calls.  TCP is stream oriented, not packet oriented.  There are no guarantees about how many bytes recv() will return.  You may get the entire chunk of bytes written by your peer, or you may get a small fraction of them, or you may get two byte chunks written separately merged together.

  The only way to be sure you've received everything is to include logic in your application which can examine the bytes and determine based on the protocol whether or not more bytes should be coming.

  For this reason, you cannot simply recv() on one socket and then send() on the next, alternating.  You need some actual POP3 logic to determine whether a recv() returned all the expected bytes, or whether you need to recv() on the same socket again.

  Another approach is to use non-blocking sockets, select(), and issue a recv() on either socket whenever select() indicates there are bytes to be read.  This is the approach taken by various libraries, including asyncore in the stdlib, as well as by Twisted.  As a bonus, Twisted (<http://www.twistedmatrix.com>) also includes client and server POP3 protocol implementations.

>
>Any help would we very appreciate.
>
>Cheers,
>
>Brokenclock
>
>Here is the code:
> >
>import socket
>
>LOCALHOST = '192.168.31.202'		# This is me
>REMOTEHOST = 'pop.fr.oleane.com'	# The remote host
>PORT = 110				# pop3 port
>while 1:
>	SocketServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>	SocketServer.bind((LOCALHOST, PORT))
>	SocketServer.listen(1)
>	Connexion2Client, ClientAddress = SocketServer.accept()
>	print '#', ClientAddress,' connected'
>	ClientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>	ClientSocket.connect((REMOTEHOST, PORT))
>	print '#', REMOTEHOST, ' connected'
>	while 1:
>		DataFromServer = ClientSocket.recv(5896230)
>		print REMOTEHOST,'> ',DataFromServer

>		Connexion2Client.send(DataFromServer)

  You can't just call send() like this.  It may not write all the bytes you pass it.  It will return the number of bytes written, and you must then call send again with the remaining bytes (and again test the return value, etc).

>		DataFromClient = Connexion2Client.recv(5896230)
>		print ClientAddress,'> ',DataFromClient
>		if DataFromClient==" QUIT": print 'QUIT received from client'

  Since you may receive "Q", "U", "I", and "T" in separate recv() results, the above will not work reliably.  You will need to buffer bytes and test for the presence of QUIT in the buffer.  Additionally, you need to maintain information about the state of connection, since "QUIT" is perfectly legitimate as part of a message body and should not be interpreted the same as a QUIT outside a message body.

>		ClientSocket.send(DataFromClient)

  Same comments about send() as above.

>		if not DataFromClient: break
>	ClientSocket.close()
>	Connexion2Client.close()
> >eof
>
>
> [snip output]

  Jp



More information about the Python-list mailing list