How To Send Emails Using Python With File Attachments [Scripts]

Himanshu Tyagi
8 min readApr 2, 2020

If you want to send automated emails using Python, then you are on the right page. In this tutorial, we will see python programs to send plain text and HTML emails. You will also learn to send emails with images and PDF attachments.

Use the Python scripts in your project to send reminders to your users, team members, or for any other purpose. Sending emails is an old school process now as it consumes time and is also error-prone.

Read this tutorial till the very end and you will get a good understanding of how you can automate sending emails using Python.

Sending Email Using Python

For testing purposes, I will use the Gmail SMTP server to send emails. However, if you wish to use any other email service, that is fine, and the script will work as usual. You can also test the script on a local server, which I will explain later in this tutorial.

Before getting started, please note that I will recommend you to create a new Gmail account for testing and debugging reasons. Also, you will have to turn on the option of Allow less secure apps to connect with your Gmail account.

Few other things to note are:

1. Don’t add your Gmail account password in the script.

2. Never add your customer’s email in the script as it is quite sensitive data, and you might want to keep it secure.

3. Don’t name your script as email.py to avoid conflict with the built-in Python module.

I have addressed the above two points in the script, and you will get to know how you can send emails using Python without including any sensitive information in the code.

Also Read: How To Use ArcGIS API for Python and Jupyter Notebooks.

Python Script To Send Plain Text Email

Step 1: Connect to the mail server

There are two classes in the smtplib Python module to connect with the mail server. First import the smtplib class.

import smtplib

Now, we will connect to the plain old SMTP server using Context Managers, which automatically closes the connection at the end. Context managers ensure efficient resource handling and management. Also, it makes our code more readable and easy to maintain.

Syntax of Context Managers:

with smtplib.SMTP('server', port number) as variable_name: smtp.ehlo() #Identify ourselves with the mail server we are using. smtp.starttls() #Encrypt our connection smtp.ehlo() #Reidentify our connection as encrypted with the mail server

In the smtplib.SMTP() method, you can add these details.

SMTP server address: smtp.gmail.com.
Gmail SMTP port (TLS): 587.
SMTP port (SSL): 465.
SMTP TLS/SSL required: yes.

If you are using any other email service, then a quick Google search will give you the necessary information.

After adding the parameters, the method will look like this — smtplib.SMTP('smtp.gmail.com', 587)

Step 2: Log in with the mail server

Use the smtp.login() function to authenticate your account details.

smtp.login('email', 'password')

Now, it is not a best practice to include your Gmail account details in the script. There are two ways by which you can authenticate your email account without adding sensitive info in your email python script.

The first way is to ask users to specify the password every time the email script is run. The second way is to set up OS environment variables and use them in the script for authentication. In this tutorial, we will implement the first way to keep it simple and straightforward.

Define global variables to store the following values:

  • Sender_Email — Your Gmail address with which you want to send the emails.
  • Reciever_Email — Email address of the person to whom you want to send the email.
  • Password — Here, you don’t have to store your password. You can use the input() function to specify your Gmail account password at the runtime.

Step 3: Create your email

When you are creating a plain text email from scratch, then you need to add the subject as header and then have a couple of blank lines. After that, you can put the body of the email. For that, I will use Python F-strings, which allows you to embed expressions inside string literals. Do not worry if you don’t understand the syntax right now; I will cover this topic extensively in another tutorial.

Create three global variables to store the subject and body of your email. Use a third variable to concatenate the subject and body of your email using f-strings. Please refer to this code below.

Subject = "Test Email from CodeItBro" Body = "Hi, hope you are doing fine! Stay Home! Stay Safe!" Message = f'Subject: {Subject}\n\n{Body}'

Step 4: Sending your plain text Email

Now, in this final step, we just have to send the email using sendmail() method. Here is the syntax of this function:

smtp.sendmail(sender_email, reciever_email, message)

Source Code:

Please find the source code of the complete Python script to send plain emails.

import smtplib Sender_Email = "[email protected]" Reciever_Email = "[email protected]" Password = input('Enter your email account password: ') Subject = "Test Email from CodeItBro" Body = "Hi, hope you are doing fine! Stay Home! Stay Safe!" Message = f'Subject: {Subject}\n\n{Body}' with smtplib.SMTP('smtp.gmail.com', 587) as smtp: smtp.ehlo() smtp.starttls() smtp.ehlo() smtp.login(Sender_Email, Password) smtp.sendmail(Sender_Email, Reciever_Email, Message)

Download Python Email Script.

Testing Using Local Debug Server

To start the local debug server to check your email script, run this command in your terminal.

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

After running the local debug server, you now have to connect to this server on port number 1025.

Now, let’s update our script to test it using the local debug server.

import smtplib Sender_Email = "[email protected]" Subject = "Test Email from CodeItBro" Body = "Hi, hope you are doing fine! Stay Home! Stay Safe!" Message = f'Subject: {Subject}\n\n{Body}' with smtplib.SMTP('localhost', 1025) as server: server.sendmail(Sender_Email, '[email protected]', Message)

Now, that you have understood how to send plain text emails using Python. Let’s now see how we can send more complex emails such as HTML emails and attach images and PDF attachments with it.

Using Python To Send HTML Email With Image and PDF Attachments

Step 1: Making our code more readable

We can make our code more readable by using SMTP_SSL class to use secured and encrypted connection right from the beginning. After that, we won’t have to use ehlo() and starttls() method again and again.

Now, you can connect with the Gmail SMTP server using this statement.

with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:

Step 2: Using EmailMessage class to create our emails

Moving forward, let’s now improve how we are defining the content of our email, i.e., subject and body in our Python script. For that, we can import the EmailMessage class from email.message Python module. EmailMessage is the base class for the email object model and offers the functionality for accessing message bodies.

Using EmailMessage class, now we don’t have to use the f-string to concatenate our subject and body. We can create its object to define each component and then simply send it using the sendmail() function.

Here’s the Python code for it. Have a look and read the comments, you will understand it easily.

import smtplib
from email.message import EmailMessage
Sender_Email = "emailpythontest12345@gmail.com"
Reciever_Email = "codeitbro@gmail.com"
Password = input('Enter your email account password: ')
newMessage = EmailMessage() #creating an object of EmailMessage class
newMessage['Subject'] = "Test Email from CodeItBro" #Defining email subject
newMessage['From'] = Sender_Email #Defining sender email
newMessage['To'] = Reciever_Email #Defining reciever email
newMessage.set_content('Hi, hope you are doing fine! Stay Home! Stay Safe!') #Defining email body
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:

smtp.login(Sender_Email, Password) #Login to SMTP server
smtp.send_message(newMessage) #Sending email using send_message method by passing EmailMessage object

Step 3: Sending attachments with our Python Email

Keep the images and other attachments in the same directory of your Python script. For the starting, let’s see how we can send an image as an attachment.

To send an image as an attachment, we first have to open the file and store its data in a variable. For that, we can use Context Managers as they ensure efficient resource management.

Syntax (for understanding):

with open('file_name_with_extension', 'file_open_mode') as variable_name: variable_for_storing_image_data = variable_name.read()

Code snippet from our script:

with open('codeitbro-logo.png', 'rb') as f: image_data = f.read()

Before attaching this image in our email, we first have to determine the type of the picture. In case you just want to send a single image attachment, then you can do it manually in the script. However, while sending multiple images, you would want Python to detect it for you automatically.

We can use Python built-in module called imghdr. To determine the type of the image, follow this statement with your above with statement. Do not forget to import the imghdr module.

image_type = imghdr.what(f.name)

Now, we can attach the image to our email using add_attachment() function.

Syntax:

add_attachment(imag_data, maintype='image', subtype=image_type, filename=image_name)

Source Code

import smtplib
import imghdr
from email.message import EmailMessage
Sender_Email = "emailpythontest12345@gmail.com"
Reciever_Email = "codeitbro@gmail.com"
Password = input('Enter your email account password: ')
newMessage = EmailMessage()
newMessage['Subject'] = "Check out the new logo"
newMessage['From'] = Sender_Email
newMessage['To'] = Reciever_Email
newMessage.set_content('Let me know what you think. Image attached!')
with open('codeitbro-logo.png', 'rb') as f:
image_data = f.read()
image_type = imghdr.what(f.name)
image_name = f.name
newMessage.add_attachment(image_data, maintype='image', subtype=image_type, filename=image_name)
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:

smtp.login(Sender_Email, Password)
smtp.send_message(newMessage)

Download Python Email Script.

Sending Multiple Images As Attachments

Now, that you have understood how to attach images as attachments in your email message. Let’s now see how you can send multiple images as attachments in your Python email. For that, you just have to create a Python list and store image file names that you want to attach. After that, you can use Python For loop to open each file and attach it to your email message, as shown in the following code snippet.

files = ['codeitbro-logo.png', 'cat.gif'] for file in files: with open(file, 'rb') as f: image_data = f.read() image_type = imghdr.what(f.name) image_name = f.name newMessage.add_attachment(image_data, maintype='image', subtype=image_type, filename=image_name)

Sending PDFs As Email Attachments

To send PDFs as email attachments in Python, simply specify the maintype as application and subtype as octet-stream in the add_attachment() function. Refer to the code snippet below.

Source Code:

import smtplib
import imghdr
from email.message import EmailMessage
Sender_Email = "emailpythontest12345@gmail.com"
Reciever_Email = "codeitbro@gmail.com"
Password = input('Enter your email account password: ')
newMessage = EmailMessage()
newMessage['Subject'] = "Check out the new program PDF"
newMessage['From'] = Sender_Email
newMessage['To'] = Reciever_Email
newMessage.set_content('Let me know what you think. Image attached!')
files = ['LargeElementArray.pdf']
for file in files:
with open(file, 'rb') as f:
file_data = f.read()
file_name = f.name
newMessage.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=file_name)
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:

smtp.login(Sender_Email, Password)
smtp.send_message(newMessage)

Download Python Script.

Wrapping Up

With this, we sum up our tutorial to send emails using Python. Download Python scripts from our GitHub repository and start sending emails. In case you didn’t understand any part of the tutorial, then do leave your comments and I will try my best to solve your queries. Stay tuned for more exciting Python tutorials. In the next post, I will share Python scripts to send personalized emails from a CSV or PDF file.

If you want me to cover any specific Python tutorial, then you can share your suggestions at [email protected] .

And, if you are a Python developer and would like to contribute to our community, then do let me know so that I can set up a contributor account for you.

Originally published at https://www.codeitbro.com on April 2, 2020.

--

--