There are several different exceptions that might be raised while you’re programming with smtplib
. They
are:
socket.gaierror
for errors looking up address information.socket.error
for general I/O and communication problems.socket.herror
for other addressing errors.smtplib.SMTPException
or a subclass of it for SMTP conversation problems.The smtplib
module also provides a way to get a series of detailed messages about the steps it takes
to send an e-mail. To enable that level of detail, you can call
smtpobj.set_debuglevel(1)
With this option, you should be able to track down any problems.
Take a a look at debug.py
for an
example program that provides basic error handling and debugging.
import sys, smtplib, socket
if len(sys.argv) < 4:
print "usage: %s server fromaddr toaddr [toaddr...]" % sys.argv[0]
sys.exit(2)
server, fromaddr, toaddrs = sys.argv[1], sys.argv[2], sys.argv[3:]
message = """To: %s
From: %s
Subject: Test Message from simple.py
Hello,
This is a test message sent to you from the debug.py program.
""" % (', '.join(toaddrs), fromaddr)
try:
s = smtplib.SMTP(server)
s.set_debuglevel(1)
s.sendmail(fromaddr, toaddrs, message)
except (socket.gaierror, socket.error, socket.herror,
smtplib.SMTPException), e:
print " *** Your message may not have been sent!"
print e
sys.exit(1)
else:
print "Message successfully sent to %d recipient(s)" % len(toaddrs)
This program looks similar to the last one. However, the output will be very different.
root@erlerobot:~/Python_files# python debug.py localhost [email protected] [email protected]
send: 'ehlo localhost\r\n'
reply: '250-localhost\r\n'
reply: '250-PIPELINING\r\n'
reply: '250-SIZE 20480000\r\n'
reply: '250-VRFY\r\n'
reply: '250-ETRN\r\n'
reply: '250-STARTTLS\r\n'
...
Message successfully sent to 1 recipient(s)
From this example, you can see the conversation that smtplib
is having with the SMTP server over
the network.Let’s look at what’s happening:
First, the client (the smtplib
library) sends an EHLO command (an “extended” successor to a more
ancient command that was named, more readably, HELO) with your hostname in it. The remote server
responds with its hostname, and lists any optional SMTP features that it supports.
Next, the client sends the mail from command, which states the “envelope sender” e-mail address
and the size of the message. The server at this moment has the opportunity to reject the message (for
example, because it thinks you are a spammer); but in this case, it responds with 250 Ok. (Note that in
this case, the code 250 is what matters; the remaining text is just a human-readable comment and varies
from server to server.)
Then the client sends a rcpt
to command, with the “envelope recipient” that we talked so much
about earlier in this chapter; you can finally see that, indeed, it is transmitted separately from the text of
the message itself when using the SMTP protocol. If you were sending the message to more than one
recipient, they would each be listed on the rcpt to line.
Finally, the client sends a data command, transmits the actual message (using verbose carriagereturn-
linefeed line endings, you will note, per the Internet e-mail standard), and finishes the
conversation.
The smtplib
module is doing all this automatically for you in this example. In the rest of the chapter,
we will look at how to take more control of the process so you can take advantage of some more
advanced features.