In this tutorial, we’ll show you how to send emails using Python.
We can easily automate the process of sending emails using Python. It’s handy when you are sending similar content over and over again. This automation could reduce human errors and free your time as well!
For example, if you need to update a list of contacts based on new daily data, you can use Python to create a new report and share it with them by sending emails. Or, if you have a Python program that takes a long time to run, you can ask Python to send you a reminder email when it’s done.
Following this tutorial, you’ll learn with examples:
- How to connect securely to your email’s SMTP server
- How to send Plain Text emails (with Subject, To, multiple recipients)
- How to send fancy HTML content emails (with attachments / images)
- And more!
We’ll show you how to use Python modules, including smtplib
and email
, with plenty of examples.
If you want to send emails using Python, this tutorial will take you a long way!
Further learning: to generate reports using Python as Excel, HTML, PDF, check out our tutorial How to generate Reports with Python.
Let’s dive in!
To follow this tutorial, you need to know:
- Python basics, which you can learn with our FREE Python crash course: breaking into Data Science.
- HTML basics, which you can get a quick overview with HTML Introduction from W3 Schools.
Overview of Sending Emails using Python
Before we start, let’s look at an overview of the tools for sending emails using Python. This depends on the formats of emails you are sending.
Below are the two main types of emails and the Python libraries we’ll use in this tutorial. Don’t worry about all the new technical terms. You only need to know them at a high level.
- Plain Text
smtplib
: this library defines a Simple Mail Transfer Protocol (SMTP) client session object that can be used to send mail to any Internet machine with an SMTP or ESMTP listener daemon.
What is SMTP? It is an internet standard communication protocol for electronic mail transmission.
In short, this modulesmtplib
enables Python to use such a protocol to send emails reliably and efficiently. So it’s a foundation library for sending emails using Python.ssl
: this module provides access to Transport Layer Security (TLS, also known as SSL) encryption and peer authentication facilities for network sockets.
In short, such a protocol makes communications over the computer network more secure.
- HTML (with attachments)
smtplib
: to send HTML content emails, we still needsmtplib
.ssl
: to send HTML content emails, we still needssl
.email
: use theemail
module if we want to send fancy emails.
This library makes managing email messages easier. We don’t have to know all the details behind the scenes when constructing complicated emails.
For example, we’ll use theemail.mime
module to add HTML, and attach documents to the email. You can learn more about the Multipurpose Internet Mail Extensions (MIME) standard here.
All right!
By this point, you might be overwhelmed with all these new terms. But don’t worry, it will be more clear with examples.
One more thing before programming, we strongly suggest you create a new email account for testing purposes.
Set up your new Gmail account
For this tutorial, we created a new Gmail account. There are a couple of reasons for that. For example, we don’t want to expose our login information accidentally. Plus, the easiest way to allow access from Python to your Gmail account is to modify its security settings.
So it is good to have a new account for testing sending emails using Python, before applying it using your existing account. After the development stage, if you don’t want to lower the security setting of your existing Gmail account, you can search for a solution within the Gmail API section. But for now, let’s create a new Gmail account to keep things simple.
Here are the 2 steps procedure to set up your test Gmail account:
- Create a Gmail account
- Allow less secure apps: turn the switch ON to give Python access to your account
Please make sure you are changing the setting of the new account
If you don’t change this setting, when running the code later, you’ll get an error message like below:
SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8 https://support.google.com/mail/?p=BadCredentials - gsmtp')
Update: from May 30, 2022, the Less secure app access setting is no longer available for Gmail. But it might be available for other mail service providers.
To fix the problems with our tutorial on Gmail, please set up an App Password. The general steps are go to your Google Account -> Security -> turn on 2-Step Verification -> Security -> set up an App password. For more details, please visit here.
Then, you can use such a password to send emails in Python.
Note: Even though we use Gmail in our examples, you can follow similar procedures using other mail service providers.
If you are working in a large corporation, you might not have access to your SMTP server. In that case, you need to contact your IT team for support.
Now you should have your Gmail test account set up. We are ready to send emails using Python!
Send Plain Text Emails
We’ll start from the most basic email, with only plain text. Please don’t skip this section, since we need this basic knowledge in the later sections.
Send your first email with secure SMTP server connection
To send emails using Python, we need to connect securely to Gmail’s SMTP server, and send an email message through it.
Below are the details of this procedure. As mentioned in the overview, we use two Python modules: smtplib
and ssl
.
- Create a secure default settings context
Use thessl.create_default_context
function to return a new SSLContext object with default security settings. This ensures our communication with the mailbox server is encrypted and secure. - Connect to Gmail’s SMTP Outgoing Mail server with such context
Use thesmtplib.SMTP_SSL
function
You can find out about Gmail’s SMTP server (smtp.gmail.com
) and port (465
) here. If you are using a different email service, please look up and switch to their information. - With such connection, we provide Gmail’s login information, and send a mail with the message as a Python string (plain text)
We use thewith
statement to connect, so that the connection automatically quits when thewith
statement exits.
Combining everything, below is the script to send a basic plain text email using Python. Please make sure to remove your password if you are sharing the code with others.
After running it successfully, you should get a mail in your receiver mailbox like below.

Congrats! You’ve sent your first email using Python.
If you click the small arrow to expand the details of the email, you can see that the security says Standard encryption (TLS). This confirms that we sent the message via a secure connection.

Add multiple recipients, Subject, To
As you might have noticed, the first email we’ve sent has no Subject. Also, the To field that usually shows the recipients’ email address is empty. We can add both by changing the email message. Plus, what if we want to send to multiple email addresses? Let’s add them as well.
Below is the code modified based on the previous example. The changes we’ve made are:
- Adding multiple recipients as a list
Python will send emails to all the email addresses listed. But Python will not automatically show these addresses in the To field. - Adding Subject and To fields
We must have the Subject, To, and email message on separate lines. So please define the f-string as a multiline string with triple quotes (''').
Again, since Python does not automatically show the recipient emails in the To field, we must print them manually. The code','.join(email_to)
joins all the recipient emails stored inemail_to
, using the string of comma (,)
as the separator. So it returns a string ofreceiver_email1@gmail.com,receiver_email2@yahoo.com
, which will be printed as the To field in the email.
After running successfully, you should see an email like below, in all of the recipients’ mailboxes. And you should see the email with Subject as ‘A plain text email’, and To field as the recipient addresses.

Send HTML with attachment Emails
While plain text emails are good to share some information, we often want to add more to an email. For example, we might want to format the text with HTML so it’s easier for the recipients to read, or we might want to add more content to the email, such as a PDF document.
To include HTML content and attachments, we’ll use another Python module called email
. More specifically, we’ll use the email
.mime
module to build these more fancy emails: the Multipurpose Internet Mail Extensions (MIME) standard emails.
The general procedure of creating a MIME email in our examples is:
- Create a
MIMEMultipart
class - Attach extra
MIME
classes (e.g.,MIMEText
with the email message,MIMEApplication
with attachments) to it
Let’s explore some examples below.
Send HTML content with the email.mime
module
HTML is the standard markup language for web pages. So there’s lots of content and formatting we could do with HTML. For example, we can make the text as headings, paragraphs, bold, or italic; we can also include other HTML elements such as data tables, images, etc. With HTML as the email message, we can display information-rich and well-structured content.
Below is an example of a basic HTML content email:
- Import modules
Besidessmtplib
andssl
, we also need some functions to create MIME subclasses fromemail.mime
. You can research different MIME classes here.
We also import thepandas
library since we want to include the current date in the Subject, which is optional for sending emails. - Define the HTML document
We only include a simple doc with anh1
and ap
element. But you can include other elements such astable
.
If you are coming from How to generate Reports with Python tutorial, you can try to render thehtml
report we’ve generated, except for theimg
element. Theimg
element needs some extra work to render, which will be shown soon. - Set up the email addresses and password
Please note that you can also include multiple recipients as the plain text example. - Create a
MIMEMultipart
class, and set up the From, To, Subject fields
Note that theemail.mime
module makes it easier to set up the From, To, Subject fields. We don’t have to put each field on a separate line in the message string. Instead, we define them separately in a more clear way. - Attach the
html
doc defined earlier, as aMIMEText
html content type to the MIME message
Note that the default content type is ‘plain’, which won’t render the HTML document properly. - Convert the
email_message
as string - Connect to the Gmail SMTP server and send Email, which is the same as before
By the end, you should receive an email like below. As you can see, the text is better formatted.

Now that you’ve learned how to send HTML emails using Python, you can modify the HTML document to include other elements such as table
as well!
Add attachments
Besides basic HTML content, we often want to include attachments to emails as well.
Based on the previous example, you can use the below code to include attachments to the email:
- Add a new MIME subclass for adding attachments
We can use theMIMEApplication
class to hold attachments. - Define a function to attach files as
MIMEApplication
to the email
Since adding attachments is complicated, it’s better to write it as a function for reuse.
Please see the details in the comments. - Attach more (documents) to email, by applying the function
We attach three documents: 1 PNG, 1 Excel, 1 PDF.
You can try to attach your files. Please make sure they are saved under the current working directory, if you don’t want to specify the path.
If you are coming from How to generate Reports with Python tutorial, you can now attach the chart, Excel, and PDF reports we’ve generated.
If you run the code, you should be able to receive an email like below, with the attachment files of your choice.

Add image to email body
Now, what if we want to include the chart in our email message? We need to include it as an img
element in the HTML content. But the email sent using Python doesn’t render the image without extra processing. So as one last example in this tutorial, we’ll render an image within the HTML email message.
Based on the previous example, here are the changes to include the image in HTML:
- Add an
img
element withsrc
as cid (Content ID) being myimageid
You can set the cid to other values if you’d like. - Within the function to add attachments, add another input
extra_headers
This input has a default value of None:
– If it’s None, the function attaches the file as the previous example
– If this input is not None, i.e., when we set it to a specific value, it will add thisextra_header
‘s value as header to the object, which can be used to set the cid forimg
- Apply function with
extra_header
onchart.png
The Content-ID of myimageid matches with theimg
element inhtml
. This renders thechart.png
on the HTML content.
If you run the code now, you should get an email like below. The chart.png
or a chart of your choice is shown in the HTML content, rather than shown as an attachment.

This is great!
In this tutorial, you’ve learned how to send emails using Python, from the most basic plain text emails, to more fancy HTML emails with attachments.
Hope you can now automate the process of sending emails via Python!
Besides these foundation Python modules, there are also other libraries or products that help with sending emails using Python. For example, you can check out:
- yagmail: this module is in particular for Gmail, which simplifies the process a lot. But you have to make sure the package is updated based on the foundation modules and Gmail
- SendGrid: this service has a free tier. But since it’s a managed service, you do have to trust it.
- Mailgun: this service offers 3 months free trial. But since it’s a managed service, you do have to trust it.
Further learning: to learn about generating reports with Python, check out How to generate Reports with Python (3 Formats/4 Tools). So that you can generate reports, sending emails to share the reports, both automatically in Python!
We’d love to hear from you. Leave a comment for any questions you may have or anything else.
22 thoughts on “How to Send Emails using Python: Tutorial with examples<br /><div style='color:#7A7A7A;font-size: large;font-family:roboto;font-weight:400;'> Plain text, HTML with attachments</div>”
Hi, since 30.05.2022 gmail doesn’t allow “access with less secure apps”, so it doesn’t work anymore.
Are there other providers, which still work with your described method?
Regards
Hi thanks for letting us know. If you want to stick to Gmail, you can set up an app password as we’ve updated in the article. For other providers, I haven’t tested, but outlook might be still available.
Wow!
Since Google changed the terms for Gmail to non-secure apps I have spent many hours looking at and creating apps that use OAuth 2.0 and Workspace services. But none (for various reasons) have been a complete substitute for what existed before the change.
Your post is easy to understand and implement while also giving back the functionality that previously existed. What really blows me away is that I have never seen any mention of “To fix the problems with our tutorial on Gmail, please set up an App Password.”
So thanks for that.
Glad it helps, Malcolm:)
which python you use to run those scripts ?
Hi Eric, we probably used 3.8
how can I create the Multiple sender function in smtp
Hi Kamal, I’m not sure if I understand your question. I think an email should only have one sender.
I think he meant sending to multiple recipient addresses, which I am interested in finding out as well.
Hi Sok, there’s a section about multiple recipients in the post
Hey, how can I add multiple images to the email body using this code?
Hi M, you should be able to repeat the same process as adding a single image mentioned in the post.
Thank you Pal. You saved my day…!
Hi
when I am trying to run the code on the server its giving the error
f”attachment; filename= {filename}”,
)
^
SyntaxError: invalid syntax
Thanks
venkat
this is the output that I am getting
Hi Venkat, it’s hard to tell based on this. But since it’s a Syntax error, it could be the wrong indentation.
When using this code, it’s embedding the photo and attaches it as a file. How do I get it to not attach but only show the image?
I’m trying to attach my logo to the end of the email.
Hi Brandon, I believe we’ve covered the similar topic within the article under the section Add image to email body.
It really help me, Thanks for the article.
Glad to help, Zaheer:)
Hi Lianne and Justin, I would just like to say how helpful your lessons are! I have been learning a lot of code from you guys. Thank you.
Glad it’s helpful. Thank you, Joseph!