Thursday, August 4, 2011

The Case of Socket Timeout in smtplib in Python 2.6.4

In Python 2.6.4 (and probably earlier versions, and maybe some later versions too), it is extremely critical NOT to call connect again if you have passed the host, and port into smtplib's SMTP (and by virtue of inheritance, SMTP_SSL) contructor.

If host and port are supplied, the constructor will make a call to connect. In connect, self.socket is assigned a connected socket. Then self.getreply is called. Within getreply, if self.file is None then self.file is assigned a file object created from self.socket.

Therefore, when another call to connect is made, self.socket is reset to another (new) connected socket. However, self.file is not. The call to self.getreply still reads from the old self.file (old socket). And since the server has nothing more to send to the client (it has already sent everything in the previous connect), getreply blocks until the (old) socket is disconnected by the SMTP server due to timeout.

The fix is easy, reset self.file to None in connect.

No comments:

Post a Comment