×

Search anything:

Sending file/ attachment in Gmail using Python

Binary Tree book by OpenGenus

Open-Source Internship opportunity by OpenGenus for programmers. Apply now.

In this article, we have explained the idea of using Python to send file/ attachment in Gmail with a complete Python implementation example.

Table of contents:

  1. Introduction to SMTP and MIME
  2. Generate App password in Google
  3. Email config file setup
  4. Difference between sending a text email vs sending an attachment
  5. Example of an email header
  6. Implementation in Python

Introduction to SMTP and MIME

The application level protocol, Simple Mail Transfer Protocol (SMTP), handles message service over TCP/IP networks. It is limited to only 7 bit ASCII characters and hence do not support languages such as Arabic, Chinese, Korean, Japanese, etc. SMTP cannot used to transmit binary files such as vidoe, images and document files created by office productivity software.

Multipurpose Internet Mail Extensions (MIME) remove the limitation faced by SMTP. Email messages can support languages such as Arabic, Chinese, Korean, Japanese, etc. It is possible to attach video, images, and document files created by office productivity software in email messages.

The structure of a MIME is as follow type/subtype;parameter=value. The type refer to the category that the data represent in general, for example text or video. The subtype provide more details with regards to the MIME type represented. For example, for type text, the subtext could be plain or html. The parameter is an optional value that can provide additional details, for example to attach a UTF-8 text file, one could specify the MIME as follow text/plain;charset=UTF-8.

Putting it all together, if I attached an HTML document specifying the MIME type text/html , this will allow the client software (web browser) to render it internally". If I attached a pdf file with the MIME type specified as application/pdf, the client software will lauch the PDF Reader software that is installed and registered as the application/pdf handler.

Generate App password in Google

Go to myaccount.google.com/security, ensure that you have enabled 2-Step Verification.
two-step-verify-2

Next click into the App passwords section to generate your password for our python script
app-pass-1

Email config file setup

Create an email_config.py file with the following

gmail_pass = "[this will be the App password you generated in the previous step]"
user = "[replace it with your gmail address, for example hello-world@gmail.com]"
host = "smtp.gmail.com"
port = 465

Difference between sending a text email vs sending an attachment

In order to send a text email, we will just need to attach the message body as MIMEText.

# attach nessage body as MIMEText
message.attach(MIMEText(body,'plain', 'utf-8'))

For sending an attachement in the email, we add the filename to the header and then attach the file to the email message.

# Add to header attachment filename
attachedfile.add_header('content-disposition', 'attachment', filename=file_to_open.name)

# Then attach to message attachment file    
message.attach(attachedfile)

Example of an email header

Below is an example of how an email header would look like.

Return-Path: <redacted-info>
   Received: from <redacted-info> 
       by mx.google.com with SMTP id <redacted-info>
       for <redacted-info>;
       Wed, 19 Jun 2021 10:09:38 -0700 (PDT)
   DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sendgrid.info; h=
   content-type:mime-version:from:to:subject; s=smtpapi; bh=<redacted-info>=
   Received: by <redacted-info> with SMTP id <redacted-info>
       Wed, 19 Jun 2021 17:09:33 +0000 (UTC)
   Content-Type: multipart/alternative;
   MIME-Version: 1.0
   From: redacted-address
   To: redacted-address
   Subject: Hello World
   Message-ID: <redacted-info>
   Date: Wed, 19 Jun 2021 17:09:33 +0000 (UTC)

Implementation in Python

Let's review the following code on how to use Python to send email in Gmail. We first need to import the following modules. smtplib for sending emails using the Simple Mail Transfer Protocol (SMTP). pathlib provides an object oriented approach to handling filesystem paths. email for managing email messages. email_config which is the email_config.py file which we had created earlier.

import smtplib
from pathlib import Path
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.header import Header
from email_config import gmail_pass, user, host, port

Thereafter we create a send_email_attach function which take in four inputs. The email address to send to, the subject, the content (body) and the filename of the attachment(s) of the email message. The email to be sent is formatted in plain text.

def send_email_attach(to, subject, body, files= None)):
    # create message object
    message = MIMEMultipart()
    
    # add the header
    message['From'] = Header(user)
    message['To'] = Header(to)
    message['Subject'] = Header(subject)

    # attach nessage body as MIMEText
    message.attach(MIMEText(body,'plain', 'utf-8'))

The pathlib module that we import earlier provides an object oriented approach to handling filesystem paths. We will write a for loop to go through the list of files that we wish to attach in the email. Here we will specify the path to the directory where our files are located. Using the with open statement , the file is opened in binary format for reading. MIMEApplication is used to handle the attachment of the file(s) in the email message.

    # attach file(s)
    data_folder = Path("data/")        
    for f in files or []:
        file_to_open = data_folder / f
        with open(file_to_open, "rb") as fil: 
            attachedfile = MIMEApplication(fil.read(), _subtype = file_to_open.suffix)
            attachedfile.add_header(
                'content-disposition', 'attachment', filename=file_to_open.name )
        message.attach(attachedfile)

We had previously stored the host, port, user, gmail_pass information in the email_config.py file. At the beginning of our Python script, we had import these data which allow us to setup the email server below. With our email server setup , we are now ready to send the email.

    # setup email server
    server = smtplib.SMTP_SSL(host, port)
    server.login(user,gmail_pass)

    # send email and quit server
    server.sendmail(user, to, message.as_string())
    server.quit()

The below codes will request the user input for the recipient email address, subject, the content (body) and the list of filenames that the user want to attach in the email message . Once the input is received, the send_email_attach function will be called and our email is sent in Gmail by our Python program.

print(f"Preparing to send email")        
to = input("Recipient email address please ")    
subject = input("Enter the subject of this email? ")
body = input("Type your email message here: ")

files = []
while True:
    i = input("Enter name of the file you want to attach? Type Q to stop adding attachment ").rstrip()
    if i.casefold() == 'q':
        break
    files.append(i)
 
send_email_attach(to, subject, body, files)

Here is the entire code block for reference

import smtplib
from pathlib import Path
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.header import Header
from email_config import gmail_pass, user, host, port

def send_email_attach(to, subject, body, files= None):
    # create message object
    message = MIMEMultipart('mixed')
    
    # add the header
    message['From'] = Header(user)
    message['To'] = Header(to)
    message['Subject'] = Header(subject)
    
    # attach nessage body as MIMEText
    message.attach(MIMEText(body,'plain', 'utf-8'))

    # attach file(s)
    data_folder = Path("data/")        
    for f in files or []:
        file_to_open = data_folder / f
        with open(file_to_open, "rb") as fil: 
            attachedfile = MIMEApplication(fil.read(), _subtype = file_to_open.suffix)
            attachedfile.add_header(
                'content-disposition', 'attachment', filename=file_to_open.name )
        message.attach(attachedfile)

    # setup email server
    server = smtplib.SMTP_SSL(host, port)
    server.login(user,gmail_pass)

    # send email and quit server
    server.sendmail(user, to, message.as_string())
    server.quit()

print(f"Preparing to send email")        
to = input("Recipient email address please ")    
subject = input("Enter the subject of this email? ")
body = input("Type your email message here: ")

files = []
while True:
    i = input("Enter name of the file you want to attach? Type Q to stop adding attachment ").rstrip()
    if i.casefold() == 'q':
        break
    files.append(i)
 
send_email_attach(to, subject, body, files)

With this article at OpenGenus, you must have the complete idea of using Python to send file/ attachment in Gmail .

Sending file/ attachment in Gmail using Python
Share this