Sending e-mails in Python

So once again I have stumbled upon a script where I needed to send notifications. E-mail comes as the default choice, but there are so many referneces and… what works on one machine does not seem to work on another. Why?.. Read on.

So let’s start with the “proper” secure way of sending. Here is a boilerplate code:

import smtplib, ssl

context = ssl.create_default_context()
server = smtplib.SMTP(smtp_server, port)
server.starttls(context=context)
server.login(sender_email, password)

I will not go into details on how where you get all variables from, they should be self-describing.

So once you have the piece above the sending the message is just another one-liner:

server.sendmail(sender_email, receiver_email, message)

But then you try to run it on your somewhat ancient Linux box, you realize you still have Python 2.x, you quickly install Python 3 and you get the following "happy" message:

AttributeError: 'module' object has no attribute 'create_default_context'

And here starts the "WTF session". After some digging around you realize the the code above does not work with somewhat older APIs, namely until Python 2.7.9 or 3.4. And what if you’re stuck with an older version and do not want to upgrade whe whole thing just to get the new Python (yet)? Or may be you cannot do it at all… Then you can fall back to the ol’, although unsecure way (if your provider allows it of course):

server = smtplib.SMTP(smtp_server)

But now you’re stuck with it. Not really. You can combine both, so you use the best one available depending on context:

if hasattr(ssl, 'create_default_context'):
    print('[d] Using secure SMTP login')
    context = ssl.create_default_context()
    server = smtplib.SMTP(smtp_server, port)
    server.starttls(context=context)
    server.login(sender_email, password)
else:
    print('[d] Using UNSECURE SMTP connection')
    server = smtplib.SMTP(smtp_server)

Well, I hope this helps, I definitely don’t want to repeat my research again.

Happy coding!