Python smtplib progress indication
A few days ago I was in wanted to send an email with attachments through Python's smtplib, when I realised there was no way of keeping track of the sending progress.
After some analysis of smtplib, I finally made the choice to subclass and extend the smtplib.SMTP class.
It feels like a big dirty hack and I just wanted to throw it out there to see if anyone knows of a better way to accomplish this.
from smtplib import SMTP, quotedata, CRLF, SMTPDataError
from sys import stderr
class ExtendedSMTP(SMTP):
def data(self,msg):
"""
This is a modified copy of smtplib.SMTP.data()
Sending data in chunks and calling self.callback
to keep track of progress,
"""
self.putcmd("data")
(code,repl)=self.getreply()
if self.debuglevel >0 : print>>stderr, "data:", (code,repl)
if code != 354:
raise SMTPDataError(code,repl)
else:
q = quotedata(msg)
if q[-2:] != CRLF:
q = q + CRLF
q = q + "." + CRLF
# begin modified send code
chunk_size = 2048
bytes_sent = 0
while bytes_sent != len(q):
chunk = q[bytes_sent:bytes_sent+chunk_size]
self.send(chunk)
bytes_sent += len(chunk)
if hasattr(self, "callback"):
self.callback(bytes_sent, len(q)):
# end modified send code
(code,msg)=self.getreply()
if self.debuglevel >0 : print>>stderr, "data:", (code,msg)
return (code,msg)
To use this, we instantiate the class as normal and attach a callback function to it, which will be called by the data() method.
def callback(progress, total):
print "%s bytes sent of %s" % (progress, total)
s = ExtendedSMTP() # instead of smtplib.SMTP()
s.callback = callback
s.sendmail("billg@microsoft.com", "steveb@microsoft.com", msg)
s.quit()
Let me know if there are better ways to do this.
