Sending Email with Python

Sending email is a very common task in any system. You probably found this tutorial because you want to send emails using Python. In this tutorial, we will learn how to send emails with and without attachment/HTML contents in Python.

After complete the tutorial, I have combined all code example to one beautiful CLI. Check out the project repository to get the full code example, and you can see a beautiful CLI as below:

Sending Email With Python CLI
Sending Email With Python CLI

Getting Started

To get started with the tutorial, we have to set up an SMTP Server and log in to send out the email. For learning purposes, we have two choices for an SMTP server that are a local SMTP Server or connect to third-party SMTP service. In this post, we will use Gmail SMTP, if you would like to use another service such as Outlook, Mailchimp, etc, just leave a comment to let us know.

1. Run a local SMTP Server

For debugging, Python offers us a tool to run a local SMTP that is installed along with Python. By using smtpd, we run a local SMTP server. The server won't send the email to the internet. Instead, it will print the email to your console.

Open your console/terminal and execute the below command to start the local SMTP server:

python -m smtpd -c DebuggingServer -n localhost:1025

2. Setting up a Gmail account

Because of the popular of Gmail. Through the rest of the tutorial, we assume to use Gmail SMTP for development. To get started, make sure you follow precisely below step to enable your Gmail account for development.

Establishing a secure connection to Gmail SMTP

Whenever connecting to Gmail SMTP, make sure we always use a secure connection. With the secure connection, your message and credential will be encrypted, so other guys are not easy to reach your sensitive information.

Gmail SMTP allows us to establish a secure connection by using SSL (Secure Sockets Layer) or TLS (Transport Layer Security) protocol. Following it, the smtplib module also gives us two ways to connect to any SMTP service with SSL/TLS protocol by using SMTP_SSL() and .starttls().

Using SSL Protocol

The code below is an example of how to establish an SSL connection to the SMTP server. Gmail SMTP server is smtp.gmail.com and the default port of SSL is 465

Make sure you have changed "test@pythongeeks.net" on your own email

import smtplib, ssl

context = ssl.create_default_context()
password = input("Your password: ")

with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
    server.login("test@pythongeeks.net", password)
    # TODO: Sending your email here

Using TLS Protocol

To set up a TLS connection, we will set up an unsecured SMTP connection first. After that, encrypt the unsecured connection by using .starttls(). It is very different from SSL while we directly establish a secured connection.

import smtplib, ssl

password = input("Your password: ")
context = ssl.create_default_context()

with smtplib.SMTP("smtp.gmail.com", 587) as server:
    server.starttls(context=context) # Secure the connection with TLS
    server.login("test@pythongeeks.net", password)
    # TODO: Sending your email here

Sending A Plain-Text Email

Before diving deeper into sending an email with Python, we will send a simple email with plain-text only. The body of the email can be created by any text editor. There is no HTML tag, CSS class or attachment.

We will put the function .sendmail() precisely at TODO position in the above example TODO: Sending your email here

body = """
    Hi there,

    This message is sent from Python Geeks.

    Have a good day!
"""

server.sendmail(from_email, to_email, body)

Emailing with HTML content

Most of the time when you send an email, you would like to send a fancy mail. Sometimes it contains a beautiful HTML, sometimes it has an attachment. As a backend developer, we even have to deal with a feature that sending the marketing mail to the list subscribers. To deal with it, Python gives us the email module.

First of all, we use both the email module and the smtplib module to send an email with HTML content.

import smtplib, ssl
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

password = input("Your password: ")
context = ssl.create_default_context()

msg = MIMEMultipart('alternative')
msg['Subject'] = "[Python Geeks] Sending Email With Python"
msg['From'] = "test@pythongeeks.net"
msg['To'] = "receiver@pythongeeks.net"
# Plain-text version of content
plain_text = """\
    Hi there,

    This message is sent from Python Geeks.
    Visit us here https://pythongeeks.net

    Have a good day!
"""
# html version of content
html_content = """\

Hi there,

This message is sent from Python Geeks.

Visit us here Python Geeks

    

"""
text_part = MIMEText(plain_text, 'plain')
html_part = MIMEText(html_content, 'html')
msg.attach(text_part)
msg.attach(html_part)

with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
    server.login("test@pythongeeks.net", password)
    server.send_message(msg)

In this example, we create a MIMEMultipart('alternative') message. It means we are creating an email message within the plain-text version and an alternative version - HTML version. Therefore, we have defined two-part of content separately and attach it to the main message by using .attach()

Note: Be noticed that you need to replace the login account (test@pythongeeks.net) on your own.

Emailing with an attachment

After sending an HTML email, we would like to try more by attaching an email to this email before sending it. The code below will show you how to deal with the attachment:

import smtplib, ssl
import mimetypes

from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.text import MIMEText

password = input("Your password: ")
context = ssl.create_default_context()

msg = MIMEMultipart('alternative')
msg['Subject'] = "[Python Geeks] Sending Email With Python"
msg['From'] = "test@pythongeeks.net"
msg['To'] = "receiver@pythongeeks.net"
# Plain-text version of content
plain_text = """\
    Hi there,

    This message is sent from Python Geeks.
    Visit us here https://pythongeeks.net

    Have a good day!
"""
# html version of content
html_content = """\

Hi there,

This message is sent from Python Geeks.

Visit us here Python Geeks

    

"""
text_part = MIMEText(plain_text, 'plain')
html_part = MIMEText(html_content, 'html')
msg.attach(text_part)
msg.attach(html_part)

# Define MIMEImage part
# Remember to change the file path
file_path = '../assets/level_up_your_python.png'
ctype, encoding = mimetypes.guess_type(file_path)
maintype, subtype = ctype.split('/', 1)
with open(file_path, 'rb') as fp:
    img_part = MIMEImage(fp.read(), _subtype=subtype)
    # Set the filename for the attachment
    img_part.add_header('Content-Disposition', 'attachment', filename='level_up_your_python')
    msg.attach(img_part)

with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
    server.login("test@pythongeeks.net", password)
    server.send_message(msg)

In the example, we easily attach an image to email by using MIMEImage. We also attach a variety of file types in the email. For example, using MIMEAudio for the audio file or MIMEBase for the base64 data.

Newsletter

Send us your email, we will make sure you never miss a thing!

Summary

Congratulation! You have just done a quite long tutorial. Let summary what we got through this tutorial. Although it is a long tutorial, there are only two main points to remember:

  • Using smtplib to set up an SMTP connection within the SSL/TLS protocol.
  • Using the email module, especially MIMEMultipart, we can deal well with complicated emails such as attachment or HTML content.

For more Python tutorials, please visit our Python Tutorials page and enjoy it and share it with other Python Geeks.

References

To completed this post, we have referenced a lot of sources. In the references also contains many other examples, we suggest the reader reach the below sources to get a deeper understanding:



Found the useful article? 😍

  • To keep this blog ad-free, you can buy me a coffee.
  • To boost my energy for more blog posts, you can support me.
  • To sharing your knowledge. You can visit become a writer.

If you find useful knowledge, please send your πŸ’to Python Geeks or share the useful article to help other readers.



 

Sharing is caring!

Leave a Reply

Your email address will not be published. Required fields are marked *

Name *