5/10/22, 0:02 Sending Emails With Python – The Apps blaster
Python Projects
Sending Emails With Python
CloudClub • December 7, 2021 4 minutes read
Sending a Plain-Text Email
Before we dive into sending emails with HTML content and attachments, you’ll
learn to send plain-text emails using Python. These are emails that you could
write up in a simple text editor. There’s no fancy stuff like text formatting or
hyperlinks. You’ll learn that a bit later.
Starting a Secure SMTP Connection
When you send emails through Python, you should make sure that your SMTP
connection is encrypted, so that your message and login credentials are not
easily accessed by others. SSL (Secure Sockets Layer) and TLS (Transport Layer
Security) are two protocols that can be used to encrypt an SMTP connection.
It’s not necessary to use either of these when using a local debugging server.
There are two ways to start a secure connection with your email server:
https://theappsblaster.com/?p=7386 1/6
5/10/22, 0:02 Sending Emails With Python – The Apps blaster
Start an SMTP connection that is secured from the beginning
using SMTP_SSL() .
Start an unsecured SMTP connection that can then be encrypted
using .starttls() .
In both instances, Gmail will encrypt emails using TLS, as this is the more
secure successor of SSL. As per Python’s Security considerations, it is highly
recommended that you use create_default_context() from the ssl module.
This will load the system’s trusted CA certificates, enable host name checking
and certificate validation, and try to choose reasonably secure protocol and
cipher settings.
If you want to check the encryption for an email in your Gmail inbox, go
to More → Show original to see the encryption type listed under
the Received header.
smtplib is Python’s built-in module for sending emails to any Internet machine
with an SMTP or ESMTP listener daemon.
I’ll show you how to use SMTP_SSL() first, as it instantiates a connection that is
secure from the outset and is slightly more concise than
the .starttls() alternative. Keep in mind that Gmail requires that you connect
to port 465 if using SMTP_SSL() , and to port 587 when using .starttls() .
Option 1: Using SMTP_SSL()
The code example below creates a secure connection with Gmail’s SMTP server,
using the SMTP_SSL() of smtplib to initiate a TLS-encrypted connection. The
default context of ssl validates the host name and its certificates and
optimizes the security of the connection. Make sure to fill in your own email
address instead of
[email protected] :
import smtplib, ssl
port = 465 # For SSL
password = input("Type your password and press enter: ")
# Create a secure SSL context
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", port, context=context) as
server:
https://theappsblaster.com/?p=7386 2/6
5/10/22, 0:02 Sending Emails With Python – The Apps blaster
server.login("[email protected]", password)
# TODO: Send email here
Using with smtplib.SMTP_SSL() as server: makes sure that the connection is
automatically closed at the end of the indented code block. If port is zero, or
not specified, .SMTP_SSL() will use the standard port for SMTP over SSL (port
465).
It’s not safe practice to store your email password in your code, especially if
you intend to share it with others. Instead, use input() to let the user type in
their password when running the script, as in the example above. If you don’t
want your password to show on your screen when you type it, you can import
the getpass module and use .getpass() instead for blind input of your
password.
Option 2: Using .starttls()
Instead of using .SMTP_SSL() to create a connection that is secure from the
outset, we can create an unsecured SMTP connection and encrypt it
using .starttls() .
To do this, create an instance of smtplib.SMTP , which encapsulates an SMTP
connection and allows you access to its methods. I recommend defining your
SMTP server and port at the beginning of your script to configure them easily.
The code snippet below uses the construction server = SMTP() , rather than
the format with SMTP() as server: which we used in the previous example. To
make sure that your code doesn’t crash when something goes wrong, put your
main code in a try block, and let an except block print any error messages
to stdout :
import smtplib, ssl
smtp_server = "smtp.gmail.com"
port = 587 # For starttls
sender_email = "[email protected]"
password = input("Type your password and press enter: ")
# Create a secure SSL context
context = ssl.create_default_context()
# Try to log in to server and send email
try:
https://theappsblaster.com/?p=7386 3/6
5/10/22, 0:02 Sending Emails With Python – The Apps blaster
server = smtplib.SMTP(smtp_server,port)
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
server.login(sender_email, password)
# TODO: Send email here
except Exception as e:
# Print any error messages to stdout
print(e)
finally:
server.quit()
To identify yourself to the server, .helo() (SMTP) or .ehlo() (ESMTP) should
be called after creating an .SMTP() object, and again after .starttls() . This
function is implicitly called by .starttls() and .sendmail() if needed, so
unless you want to check the SMTP service extensions of the server, it is not
necessary to use .helo() or .ehlo() explicitly.
Sending Your Plain-text Email
After you initiated a secure SMTP connection using either of the above
methods, you can send your email using .sendmail() , which pretty much does
what it says on the tin:
server.sendmail(sender_email, receiver_email, message)
I recommend defining the email addresses and message content at the top of
your script, after the imports, so you can change them easily:
sender_email = "[email protected]"
receiver_email = "[email protected]"
message = """\
Subject: Hi there
This message is sent from Python."""
# Send email here
The message string starts with "Subject: Hi there" followed by two newlines
( \n ). This ensures Hi there shows up as the subject of the email, and the text
following the newlines will be treated as the message body.
https://theappsblaster.com/?p=7386 4/6
5/10/22, 0:02 Sending Emails With Python – The Apps blaster
The code example below sends a plain-text email using SMTP_SSL() :
import smtplib, ssl
port = 465 # For SSL
smtp_server = "smtp.gmail.com"
sender_email = "[email protected]" # Enter your address
receiver_email = "[email protected]" # Enter receiver address
password = input("Type your password and press enter: ")
message = """\
Subject: Hi there
This message is sent from Python."""
context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message)
For comparison, here is a code example that sends a plain-text email over an
SMTP connection secured with .starttls() . The server.ehlo() lines may be
omitted, as they are called implicitly by .starttls() and .sendmail() , if
required:
import smtplib, ssl
port = 587 # For starttls
smtp_server = "smtp.gmail.com"
sender_email = "[email protected]"
receiver_email = "[email protected]"
password = input("Type your password and press enter:")
message = """\
Subject: Hi there
This message is sent from Python."""
context = ssl.create_default_context()
with smtplib.SMTP(smtp_server, port) as server:
server.ehlo() # Can be omitted
server.starttls(context=context)
server.ehlo() # Can be omitted
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, message)
https://theappsblaster.com/?p=7386 5/6
5/10/22, 0:02 Sending Emails With Python – The Apps blaster
https://theappsblaster.com/?p=7386 6/6