Capture debug output from Python smtplib

10,157

Solution 1

It can be done by redirecting stderr to a file:

import tempfile, smtplib, os, sys

# Find an available file descriptor                                                                                              
t = tempfile.TemporaryFile()
available_fd = t.fileno()
t.close()

# now make a copy of stderr                                                                                                      
os.dup2(2,available_fd)

# Now create a new tempfile and make Python's stderr go to that file                                                             
t = tempfile.TemporaryFile()
os.dup2(t.fileno(),2)

# Now run the task that logs to stderr                                                                                           
s = smtplib.SMTP("mx10.comcast.com")
s.set_debuglevel(1)
s.sendmail("[email protected]",["[email protected]"],"""                                                     
from: [email protected]                                                                                                 
to: [email protected]                                                                                                 
subject: no such message                                                                                                         

This message won't be delivered to anybody.                                                                                      
""")

# Grab the stderr from the temp file                                                                                             
sys.stderr.flush()
t.flush()
t.seek(0)
stderr_output = t.read()
t.close()

# Put back stderr                                                                                                                
os.dup2(available_fd,2)
os.close(available_fd)


# Finally, demonstrate that we have the output:                                                                                  
print("STDERR:")
count = 0
for line in stderr_output.decode('utf-8').split("\n"):
    count += 1
    print("{:3} {}".format(count,line))

Solution 2

Study the error:

a = None
try:
    s.sendmail("[email protected]"   ["[email protected]"],"""
    from: [email protected]
    to: [email protected]
    subject: no such message

    This message won't be delivered to anybody.
    """)
except smtplib.SMTPRecipientsRefused as e:
    a = e

Now you can look at how to extract it:

a.args

({'[email protected]': (550, b'5.1.1 Recipient address rejected: {Gateway}')},)

a.args[0]['[email protected]'][1]

b'5.1.1 Recipient address rejected: {Gateway}'

And here is your message!

So to extract it:

message = None
try:
    s.sendmail("...")

except smtplib.SMTPException as e:
    message = e.args[0]['[email protected]'][1]
Share:
10,157
Ami
Author by

Ami

my about me is currently blank.

Updated on July 26, 2022

Comments

  • Ami
    Ami almost 2 years

    How do I capture the debug output from the Python smtplib library?

    Here is my test program:

    import smtplib
    s = smtplib.SMTP("mx10.comcast.com")
    s.set_debuglevel(1)
    s.sendmail("[email protected]",["[email protected]"],"""
    from: [email protected]
    to: [email protected]
    subject: no such message
    
    This message won't be delivered to anybody.
    """)
    

    Here is the output:

    send: 'ehlo dance.local\r\n'
    reply: '250-mx10.comcast.com says EHLO to 129.6.220.67:57015\r\n'
    reply: '250-SIZE 40000000\r\n'
    reply: '250-PIPELINING\r\n'
    reply: '250-ENHANCEDSTATUSCODES\r\n'
    reply: '250-8BITMIME\r\n'
    reply: '250 XXXXXXXA\r\n'
    reply: retcode (250); Msg: mx10.comcast.com says EHLO to 129.6.220.67:57015
    SIZE 40000000
    PIPELINING
    ENHANCEDSTATUSCODES
    8BITMIME
    XXXXXXXA
    send: 'mail FROM:<[email protected]> size=137\r\n'
    reply: '250 2.0.0 MAIL FROM accepted\r\n'
    reply: retcode (250); Msg: 2.0.0 MAIL FROM accepted
    send: 'rcpt TO:<[email protected]>\r\n'
    reply: '550 5.1.1 Recipient address rejected: {Gateway}\r\n'
    reply: retcode (550); Msg: 5.1.1 Recipient address rejected: {Gateway}
    send: 'rset\r\n'
    reply: '250 2.0.0 RSET OK\r\n'
    reply: retcode (250); Msg: 2.0.0 RSET OK
    Traceback (most recent call last):
      File "/Users/simsong/x.py", line 11, in <module>
        """)
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/smtplib.py", line 742, in sendmail
        raise SMTPRecipientsRefused(senderrs)
    smtplib.SMTPRecipientsRefused: {'[email protected]': (550, '5.1.1 Recipient address rejected: {Gateway}')}
    

    I want the output in a variable, output. Specifically, I want all of the lines that begin with send: and reply:.