Send Automated Emails with Python

Email Automation with Python

21st Century is the age of digitization, and the world is changing is so fast, that if you learn to stay updated with everyone, you would be far left behind. Learning is an essential part of a developer’s life. And as a part of that, I recently started learning Python 3. I learned that Python is mainly used to create automated applications. Simple, quick and crisp applications.

I wanted to check if we could do our everyday tasks using Python, so I started digging into automating my emails. Being a team lead of few societies in university, I had to write follow-up emails to the same people daily. What my practice was, first I had to open the browser, then open my email provider’s website, and wait till I get the green signal to carry-on with email creation. It was quite a lengthy process.

While digging for the process, I came to know about one of Python’s libraries, which, along with few others helped me get the job done. The smtplib module is basically all I needed to send simple emails, without any attachments. But this single module was not enough for the task. I also had to use Python’s email package.

So I used a combination of both, smtplib and Python’s email package. Be sure to check the documentation of both of these before you continue. I used these four (04) steps to send emails using Python:

  1. Set up and log into your account using SMTP Server.

Now, let’s walk through the entire process.

First, we would need to have a contacts file, as follows:

user@computer ~ $ cat mycontacts.txt
mursal mursal@example.com
furqan furqan@example.com

Each new contact should start on a new line. With the name followed by the email address, I stored everything in the lowercase. All of this was a pretty easy task in Python 😜. Make sure the contact file is in .txt format.

After having a contact file, we would need a message template. I am sharing the template that I used for testing purposes. You can change it as per your needs.

user@computer ~ $ cat message.txt Respected Mr/Ms. ${PERSON_NAME}, This is a test message. Regards
Mursal Furqan

Here, you would have noticed something strange and odd, did you? The string “${PERSON_NAME}” is a template string in Python. They can easily be replaced with other strings; in this example, it is going to be replaced with the actual name of the person, as I will describe below. Now, let's start with the Python Code. First, we have to extract/read contacts from the .txt file, here say, mycontacts.txt file. We might as well generalize this bit into a function of its own.

def get_contacts(filename):
names = []
emails = []
with open(filename, mode='r', encoding='utf-8') as contacts_file:
for a_contact in contacts_file:
names.append(a_contact.split()[0])
emails.append(a_contact.split()[1])
return names, emails

Here, in this, you would see the function get_contacts() takes a filename as its argument. This will help open the file and read it, here, each contact, line by line, followed by splitting it into name and email, then these are appended into two separate lists. In last, two lists are returned from the function 😺

Now, after having read the contact file, we need to read the template file into our Python Program too. For that, we would again need a function that out returns us a Template object containing its contents.

from string import Template
def read_template(filename):
with open(filename, 'r', encoding='utf-8') as template_file:
template_file_content = template_file.read()
return Template(template_file_content)

Now when we have the contacts and out template, we would proceed further. Here we would use Simple Mail Transfer Protocol (SMTP). As mentioned earlier, we have libraries in Python to handle this task.

import smtplib
s = smtplib.SMTP(host='your_host_address_here', port=your_port_here)
s.starttls()
s.login(MY_ADDRESS, PASSWORD)

Having smtplib imported, we need to create an SMTP instance that would encapsulate an SMTP Connection. It would take the host address and a port number, both of them would entirely depend on the SMTP settings of your particular email service provider. In my case, I have taken an outlook. So, line 2 above would be:

s=smtplib.SMTP(host='smtp-mail.outlook.com', port=587)

Every host has its own address. These host addresses and port numbers can be found here. MY_ADDRESS and PASSWORD above are two variables that hold the full email address and password of the account you’re going to use.

After all this, the next step would be to fetch the contact information and template of our message using the above-defined functions.

names, emails = get_contacts('mycontacts.txt')
message_template = read_template('message.txt')

The following code snippet would send each of these contacts a separate mail.

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
for name, email in zip(names, emails):
msg = MIMEMultipart()
message = message_template.substitute(PERSON_NAME=name.title())
msg['From']=MY_ADDRESS
msg['To']=email
msg['Subject']="This is TEST"
msg.attach(MIMEText(message, 'plain'))
s.send_message(msg)
del msg

In the above code snippet, for each name and email you’re creating a MIMEMultipart object, setting up the From, To, Subject content-type headers as a keyword dictionary, and then attaching the message body to the MIMEMultipart object as plain text. You might want to read the documentation to find out more about other MIME types.

Also note that on line 05 above, I’m replacing $PERSON_NAME with the actual name extracted from the contacts file using the templating mechanism in Python. In the above code, you would see that I am deleting the MIMEMultipart and re-creating it again every time you iterate through the loop. Once done, you can send your message using the handy send_message() function of the SMTP object that we created earlier. For your clarification, here is the complete code:

import smtplib 
from string import Template
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
MY_ADDRESS = 'mursal@example.comm'
PASSWORD = 'mypassword'
def get_contacts(filename):
"""
Return two lists names, emails containing names and email
addresses read from a file specified by filename.
"""
names = []
emails = []

with open(filename, mode='r', encoding='utf-8') as contacts_file:
for a_contact in contacts_file:
names.append(a_contact.split()[0])
emails.append(a_contact.split()[1])
return names, emails
def read_template(filename):
"""
Returns a Template object comprising the contents of the
file specified by filename.
"""

with open(filename, 'r', encoding='utf-8') as template_file:
template_file_content = template_file.read()
return Template(template_file_content)
def main():
names, emails = get_contacts('mycontacts.txt')
message_template = read_template('message.txt')

# set up the SMTP server
s = smtplib.SMTP(host='your_host_address_here', port=your_port_here)

s.starttls()
s.login(MY_ADDRESS, PASSWORD)
# For each contact, send the email:
for name, email in zip(names, emails):
msg = MIMEMultipart()
# add in the actual person name to the message template
message = message_template.substitute(PERSON_NAME=name.title())

# Prints out the message body for our sake
print(message)

# setup the parameters of the message
msg['From']=MY_ADDRESS
msg['To']=email
msg['Subject']="This is TEST"

# add in the message body
msg.attach(MIMEText(message, 'plain'))

# send the message via the server set up earlier.
s.send_message(msg)
del msg

# Terminate the SMTP session and close the connection
s.quit()
if __name__ == '__main__':
main()

There you go! Here is a clear and fair code 😃. Feel free to copy and change it according to your needs.

Happy Coding ❤ ❤ ❤

Associate Software Engineer