There are quite a few ways to send email with python, either through a third party library like with boto and ses, or through an email protocol like smtp. While the topic of using python to send email may seem like it has been done ad nauseam, there are so many different ways to do it and so many problems that can arise. I thought it would be useful to write a tutorial on how to send emails with gmail as the provider using python.
the smtp protocol
This may not come as a surprise, but of course python already has a library that allows you to connect to an smtp server, like the one used by gmail. this library is called, unsurprisingly, smtplib and is included with python.
smtp (simple mail transfer protocol) is an application layer protocol (in addition to tcp) used to communicate with external service mail servers, such as an email client on your phone. smtp is just a delivery protocol, so you can’t actually retrieve email with it, you can only send email, which is what we’ll focus on in this article. if you want to retrieve email instead, you’ll want to look at imap (internet message access protocol).
I should note that many email services, such as gmail, do not typically use smtp on their internal mail servers. smtp is usually only provided as an external interface to your service through the smtp.gmail.com server. this is primarily intended to be used by email clients on your phone or computer (such as outlook, thunderbird, etc.).
open connection
as already mentioned, python conveniently comes with smtplib, which handles all the different parts of the protocol, like connecting, authentication, validation, and of course sending emails.
Using this library, there are a few different ways to create a connection to your mail server. in this section, we’ll focus on creating a simple, insecure connection (which should rarely, if ever, be used). this connection is not encrypted and defaults to port 25. however, the protocol for sending mail actually uses 587, which is what we will use.
These connections are very easy to create with smtplib. the unencrypted version can be created with:
and that’s it. There really isn’t much more to it than passing the server address, port, and calling .helo(), which identifies you to the smtp server. Using this server object, you can now send email over an unsecured connection.
Note: You may not be ready to send email yet. gmail imposes some restrictions on smtp connections like this. see the “authenticate with gmail” section below for more information.
using a secure connection
when an smtp connection is secured via tls/ssl, it is done via port 465 and is usually referred to as smtps. It goes without saying that you should always use a secure connection.
There are a few different ways to secure your smtp connections in the smtplib library. the first way is to create an insecure connection first and then upgrade to tls. this is done using the .starttls() method.
Notice that while this is very similar to the previous insecure connection we created, the only difference is that we are using the .starttls() method to update the connection to secure.
Your other option is to create an ssl connection from scratch. in this case, you’ll want to use the .smtp_ssl() method instead:
Among other slight differences, we use the smtps port (465) right out of the box, although you can leave the port parameter out of this and smtplib will default to 465 anyway.
Now that we have our connection, let’s create an email.
creating the email
Emails, at their core, are just strings of text connected by newline characters. most emails will have at least “from”, “to”, “subject” and body fields. here is a simple example:
As you can see, each line contains a new field with your data. no binary protocol, no xml, no json, just line separated strings.
an easy way to parameterize these fields is to use string formatting in python:
now all you have to do is pass the email_text string to smtplib, which we’ll show in the next section, and you’re good to go.
authentication with gmail
There are a few steps you need to take before you can send email through gmail with smtp, and it has to do with authentication. if you use gmail as your provider, you’ll need to tell google to allow you to connect via smtp, which is considered a “less secure” method.
You can’t really blame google for setting it up this way, as your app (or some other 3rd party app) will need to have your plaintext password for this to work, which is definitely not ideal. It’s not like the oauth protocol where a revocable token is issued, so they have to find another way to ensure that no unauthorized party accesses their data.
For many other email providers, you won’t need to do any of the extra steps I describe here.
First, you’ll want to allow less secure apps to access your account. for detailed instructions on how to do this, see this page:
Allow less secure apps to access your account
If you have two-step verification enabled on your account, you’ll need to create a specific password for less secure apps like this one. in that case, you will need to follow the instructions here:
log in with app passwords
and finally, if you still get an smt authentication error with an error code of 534, you’ll need to take one more step to get this to work.
show unlock captcha
I haven’t had to do this last step for my own accounts, but I’ve read that it doesn’t actually work out of the box. Apparently, after enabling less secure apps, you may need to wait a few minutes before trying the ‘show unlock captcha’ link. If you run into this problem and find a good way to fix it, please let us know in the comments!
As for the actual python code, all you need to do is call the login method:
sending the email
Now that you have your smtp connection set up and authorized your app with google, you can finally use python to send email with gmail.
Using the email string we built above and the connected/authenticated server object, you need to call the .sendmail() method. here is the complete code, including the methods to close the connection:
conclusion
Apart from the gmail-specific authorization steps (involving less secure apps, etc.), this code should work for almost any other email provider that supports smtp access, assuming you have the server address and the correct port. If you find that other providers place special restrictions on SMTP access like Google does, please let us know! we would like to include as much information as possible here.
send emails programmatically with smtp? What kind of applications do you use it for? tell us in the comments!
resources
- https://docs.python.org/3.5/library/smtplib.html
- http://stackoverflow.com/a/27515833/2684304
edit: Thanks to cropr (in the comments) for pointing out that gmail imposes a number of restrictions on people sending email with smtp. free accounts are limited to 500 emails per day and have a speed limit of approximately 20 emails per second.
If you think you will exceed these limits, you can set up your own smtp server or use services like aws ses or sendgrid.