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, well 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, youll need a Gmail account. In addition, in your project folder youll need:
A message text file containing the email's message
An image file of your choice
Lets get started building our highly ineffective but usable mail client:
Defining Import Statements
In this section, well 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
Lets understand what each import statement above does:
smtplib: This is the Python library well be using to send emails
MIMEText: This class will be used to wrap our emails 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 emails 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, well 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 thats because its important to understand that this is different from your Gmail accounts 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 youll 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 well 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.
Top comments (0)