Building A Mail Client With  Python

Favour GeorgeFavour George
5 min read

What is a Mail Client?

A mail client is a program used to manage and compose emails that can be sent as well as received. A mail client is only ever active when it is being run by a user.

In this project, we’ll be creating a rudimentary version of a mail client to send emails with attachments such as images in the Python programming language.

PROJECT REQUIREMENTS: To build this project, you’ll need a Gmail account. In addition, in your project folder you’ll need:

  • A message text file containing the email's message

  • An image file of your choice

Let’s get started building our highly ineffective but usable mail client:

Defining Import Statements

In this section, we’ll be importing the necessary libraries we need to build this project into our main.py file in our project directory

import smtplib
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email import encoders

Let’s understand what each import statement above does:

  • smtplib: This is the Python library we’ll be using to send emails

  • MIMEText: This class will be used to wrap our email’s message to provide better formatting.

  • MIMEBase: The MIMEBase class adds a content-type header to the email.

  • MIMEMultipart: This class is used to create an object that will contain information that will be in the email’s header such as the from address, to address and email subject.

  • encoders: This will be used to encode our payload, in our case, the image, to a base64 format.

Setting Up Our Credentials

In this section, we’ll set up the login details for our Gmail account; email address and app password as shown below:

credentials = __import__("credentials")
email_address = credentials.email
password = credentials.app_password
to_addr = credentials.to_address

In the code above, I had already created a file named credentials.py, and in it, I stored my email address and app password as well as the email address I'm sending the email. So all I did was import them into my main.py file and assign them to variables as shown above. If the code you are writing won't be shared anywhere, feel free to include the email address and password directly into the code.

Now, you may have heard me say the app password above twice and that’s because it’s important to understand that this is different from your Gmail account’s password. Now, the app password is a safer way to access your Gmail account outside Gmail itself through our code. To set up an app password follow the steps below:

  • Login to your Google account

  • Go to the security tab

  • Enable 2-factor authentication

  • After enabling 2-factor authentication, in the 2-factor authentication section scroll down, and you’ll find a section on creating an app password. Create one.

  • Copy the password which will be 16 characters long and paste it where you are assigning the password in your code

This YouTube video provides a clearer explanation of how to set up an app password.

Setting up the Email Header

In this section we’ll be setting the contents of our email header which will include things such as the from address, to address and email subject

msg = MIMEMultipart()
msg['From'] = "Mad Max"
msg["To"] = to_addr
msg["Subject"] = "Hello nerd, its Mad Max"

In the code above, we created an instance of the MIMEMultipart class. Think of the object instantiated as a dictionary, to which we can assign values to its keys. In this case, we've assigned the "from email address", "to email address" and "subject" to their respective keys.

Reading our Message File

Now we'll read the message text file we created and stored in our project folder

with open("message.txt", 'r') as message:
    subject = message.read()
    msg.attach(MIMEText(subject, "plain"))

In the code above, we opened our message.txt file in read mode, 'r'. We then read the file and attached it to the message as a plain text document through the MIMEText class.

Attaching a File

We'll now be attaching a file to our message body

attached_file = "mad_max.png"
with open(attached_file, "rb") as attachment:
    payload = MIMEBase("application", "octet-stream")
    payload.set_payload(attachment.read())

    encoders.encode_base64(payload)
    payload.add_header("Content-Disposition", f"attachment; filename={attached_file}")
    msg.attach(payload)

First of all, we read our file in read binary mode, 'rb' because we are dealing with an image file and not an ordinary text file. Next, we instantiate the MIMEBase class and set a payload of our read image file. We then encode the payload to base64 as good practice and then add a header and finally attach the payload to the email message body.

Sending our Email

To send our email, we'll be using the SMTP library of Python as shown below

text = msg.as_string()
with smtplib.SMTP("smtp.gmail.com", 587) as server:
    server.starttls()
    server.login(email_address, password)
    server.sendmail(email_address, to_addr, text)

Before sending our email, we convert the entire message body to string just for good measure. Then we create a connection with the SMTP service of our email service provider, in this case, Gmail, on their specified port, 587. The starttls() method enables us to establish a secure connection to our email service provider. We then log in using the credentials we provided above(email address and password) and finally send the mail specifying the email address we are sending from, the address we are sending to and the contents of the email.

If everything was successful and the code ran without errors, the email should be in the inbox of the email address it was sent to as shown below

From the image above, you can confirm that I've successfully received the email sent from our crappy mail client and that our code ran without any errors, thus far.

Here's the complete code and a link to the project on GitHub.

import smtplib
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email import encoders

credentials = __import__("credentials")
email_address = credentials.email
password = credentials.app_password
to_addr = credentials.to_address

msg = MIMEMultipart()
msg['From'] = "Mad Max"
msg["To"] = to_addr
msg["Subject"] = "Hello nerd, its Mad Max"

with open("message.txt", 'r') as message:
    subject = message.read()
    msg.attach(MIMEText(subject, "plain"))

attached_file = "mad_max.png"
with open(attached_file, "rb") as attachment:
    payload = MIMEBase("application", "octet-stream")
    payload.set_payload(attachment.read())

    encoders.encode_base64(payload)
    payload.add_header("Content-Disposition", f"attachment; filename={attached_file}")
    msg.attach(payload)


text = msg.as_string()
with smtplib.SMTP("smtp.gmail.com", 587) as server:
    server.starttls()
    server.login(email_address, password)
    server.sendmail(email_address, to_addr, text)

That's it for this article, thanks for reading and hopefully building along. Let me know in the comments about any issues you might have gotten into while building.

0
Subscribe to my newsletter

Read articles from Favour George directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Favour George
Favour George

I am Software Developer specializing in Python programming for building web apps, scripting and building machine learning models. I hope to share what I learn along the way.