Reputation: 8418
I am using smtplib
and I am sending notification emails from my application. However I noticed that sometimes (especially when there is a lot of idle time between mail sending) I get a SMTPServerDisconnected
error.
I guess there are 2 solutions for this (know none of them, though)
I think 2nd solution seems more elegant. But how can I do that?
edit: I am adding the code
from smtplib import SMTP
smtp = SMTP()
smtp.connect('smtp.server.com')
smtp.login('username','password')
def notifyUser():
smtp.sendmail(from_email, to_email, msg.as_string())
Upvotes: 13
Views: 24034
Reputation: 4995
Yes, you can check if the connection is open. To do this, issue a NOOP command and test for status == 250. If not, then open the connection before sending out your mail.
def test_conn_open(conn):
try:
status = conn.noop()[0]
except: # smtplib.SMTPServerDisconnected
status = -1
return True if status == 250 else False
def send_email(conn, from_email, to_email, msg):
if not test_conn_open(conn):
conn = create_conn()
conn.sendmail(from_email, to_email, msg.as_string())
return conn # as you want are trying to reuse it.
Note that you are doing this as opening a connection, say with gmail, consumes time, like 2-3 secs. Subsequently, to optimize on sending multiple emails that you may have at hand, then you should also follow Pedro's response (last part).
Upvotes: 17
Reputation: 11203
If your use case is sending a single message at a time, the solution that seems most correct to me, would be to create a new SMTP session for each message:
from smtplib import SMTP
smtp = SMTP('smtp.server.com')
def notifyUser(smtp, smtp_user, smtp_password, from_email, to_email, msg):
smtp.login(smtp_user, smtp_password)
smtp.sendmail(from_email, to_email, msg.as_string())
smtp.quit()
If your SMTP server doesn't required that you authenticate yourself (a common case), this can be further simplified to:
from smtplib import SMTP
smtp = SMTP('smtp.server.com')
def notifyUser(smtp, from_email, to_email, msg):
smtp.sendmail(from_email, to_email, msg.as_string())
smtp.quit()
If it is common to have more than one message to send at once, and you want to optimise this case by reusing the same SMTP session for the group of messages (can be simplified as above if you don't need to login to the SMTP server):
from smtplib import SMTP
smtp = SMTP('smtp.server.com')
def notifyUsers(smtp, smtp_user, smtp_password, from_to_msgs):
"""
:param from_to_msgs: iterable of tuples with `(from_email, to_email, msg)`
"""
smtp.login(smtp_user, smtp_password)
for from_email, to_email, msg in from_to_msgs:
smtp.sendmail(from_email, to_email, msg.as_string())
smtp.quit()
Upvotes: 9