DEV Community

Brayan Vasquez
Brayan Vasquez

Posted on • Edited on

Send emails with Python and Gmail

Hi Everyone!. In this post, I want to share with you a little guide that will show you how to send emails using Python and Gmail.

Requirements

  • Python (I use Python 3.8.2)
  • Pip (I use Pip 20.1.1)

Setup Project

To create our project we are going to use virtualenv, to create an isolated python environment for this project. However, you can also use pyenv or venv.

So, first, we have to install venv.

pip3 install virtualenv 
Enter fullscreen mode Exit fullscreen mode

Now, we have to create the project folder and set up the virtualenv.

# Creating a project folder mkdir emails-example cd emails-example # Creating the virtual environment virtualenv env # Activate the virtual environment source env/bin/activate # Create our main file touch main.py 
Enter fullscreen mode Exit fullscreen mode

NOTE: To exit the environment you just have to write deactivate.

Setup dotenv

Before starting to write code, we need to install the package python-dotenv, to manage environment variables, where we will put our Gmail credentials. We'll use .env files to easily configure the project and to avoid sharing sensitive info in our code.

pip install -U python-dotenv 
Enter fullscreen mode Exit fullscreen mode

Ok, now we should test if we can use the package. Create a file called .env.

touch .env 
Enter fullscreen mode Exit fullscreen mode

Create a test variable in our .env file.

TEST="my test variable" 
Enter fullscreen mode Exit fullscreen mode

Import the dotenv package and load the variables.

# main.py # Import section .... import os from dotenv import load_dotenv # Loading ENV variables load_dotenv() # Obtain our TEST variable print(os.getenv('TEST')) 
Enter fullscreen mode Exit fullscreen mode

Run the script.

python main.py # my test variable 
Enter fullscreen mode Exit fullscreen mode

Configure our Gmail account

To use the Gmail SMTP, we need to allow external apps in our Gmail account. So, we have to go to our account settings.

Alt Text

Click on the Security option.

Alt Text

Scroll down until you see the Less secure app access section, and click on Turn on access.

Alt Text

Click the switch button to turn ON the configuration.

Alt Text

Send basic emails

Now that we have configured our Gmail account, we can start writing code. First, we must import the python smtplib client, which will help us to send our emails.

# main.py # Import section .... from smtplib import SMTP, SMTPException # Import SMTP module # .... 
Enter fullscreen mode Exit fullscreen mode

We will create some environment variables that we need to configure our SMTP client.

# .env SENDER="YOUR GMAIL EMAIL" PASSWORD="YOUR GMAIL PASSWORD" RECEIVERS="A LIST OF EMAILS TO SEND THE MESSAGE, SEPARATED USING ','" HOST="smtp.gmail.com" PORT="587" 
Enter fullscreen mode Exit fullscreen mode

Now, we can set some constants using the environment variables defined before.

# main.py  # Constants section ....  # GMAIL account sender SENDER = os.getenv('SENDER') PASSWORD = os.getenv('PASSWORD') # Accounts receivers RECEIVERS = os.getenv('RECEIVERS').split(',') # SMTP server options HOST = os.getenv('HOST') PORT = os.getenv('PORT') # .... # SMTP object SMTP_OBJECT = SMTP(host=HOST, port=PORT) 
Enter fullscreen mode Exit fullscreen mode

Ok, We will create a base function to reuse in the other functions and avoid code duplication.

# main.py  # Methods section ....  # Base function def send_email(message=""): """ Send an email using the credentials defined before Parameters ---------- message : str content to send in the message """ try: SMTP_OBJECT.ehlo() SMTP_OBJECT.starttls() SMTP_OBJECT.login(SENDER, PASSWORD) SMTP_OBJECT.sendmail(SENDER, RECEIVERS, message) SMTP_OBJECT.quit() print("Successfully sent email") except SMTPException: print ("Error: unable to send email") 
Enter fullscreen mode Exit fullscreen mode
  • ehlo() Open a transmision using the command EHLO. Usually this method is called automatically when use sendmail() function. We also can use the function ehlo_or_helo_if_needed() for this purpose.
  • starttls() Uses the TLS protocol in the connection.
  • login() Login on the SMTP server.
  • sendmail() Sends our email.
  • quit() Terminate the session and close the connection.

Once we have the base function we can create our basic_mail function.

# main.py # Methods section ....  def basic_email(message = ""): """ Basic email with plain text message """ send_email(message) 
Enter fullscreen mode Exit fullscreen mode

Our main function will be the following.

# main.py # Import section .... import sys # Main section ... if __name__ == "__main__": # Message to send  message = """ this message is sent from python for testing purposes """ if len(sys.argv)> 1 : if sys.argv[1] == '--help': print('Info: ') print('--help List the options to send an email') print('--basic Sends a plain text email') print('--txt Send an email from a text file content') print('--attach Send an email with an attachment') elif sys.argv[1] == '--basic': print("Sending a plain text email") basic_email(message) else: print("Please give the type of message to send.") print("For help execute `python main.py --help`") 
Enter fullscreen mode Exit fullscreen mode

We can test our function by executing the following command in our terminal.

python main.py --basic # Sending a plain text email # Successfully sent email 
Enter fullscreen mode Exit fullscreen mode

Send email from TXT file

Here, we will send a message from a .txt file. First, we have to import some useful functions.

# main.py # Import section .... from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.base import MIMEBase import email.encoders 
Enter fullscreen mode Exit fullscreen mode
  • MIMEBase This is the base class for all the MIME-specific subclasses.
  • MIMEMultipart To send messages divided in multiple messages. Usually used for attachments.
  • MIMEText To work with plain text files.

Now, We can create our function to send emails attaching a text file.

# main.py  # Methods section .... def send_from_txt(): """ Send an email reading the content message from a txt file """ message = MIMEMultipart('alternative') message['Subject'] = 'TXT file content' message['From'] = SENDER body = "Email message body" content = MIMEText(body, 'plain') message.attach(content) # process text file  file_open = open('text.txt', 'rb') file_content = MIMEText(_text=file_open.read(), _charset='utf-8') file_open.close() message.attach(file_content) # Send email  send_email(message.as_string()) 
Enter fullscreen mode Exit fullscreen mode

Add the option to our main function.

# main.py  # Main section ... if __name__ == "__main__": # ....  if len(sys.argv)> 1 : # if ....  elif sys.argv[1] == '--txt': print("Sending an email from a text file content") send_from_txt() else: # .... 
Enter fullscreen mode Exit fullscreen mode

Create a .txt file with a message.

# Creating file touch text.txt # Edit the file nano text.txt # Put the following message Message from a TXT file 
Enter fullscreen mode Exit fullscreen mode

We can test our function by executing the following command in our terminal.

python main.py --txt # Sending an email from a text file content # Successfully sent email 
Enter fullscreen mode Exit fullscreen mode

Attaching files

Finally, we will send an email with a PDF attachment.

# main.py  # Methods section .... def send_attachment(): """ Send an email with an attachment """ message = MIMEMultipart('alternative') message['Subject'] = 'Attachment' message['From'] = SENDER attachment = MIMEBase('application', 'octet-stream') attachment.set_payload(open('file.pdf', 'rb').read()) attachment.add_header('Content-Disposition', 'attachment; filename="file.pdf"') email.encoders.encode_base64(attachment) message.attach(attachment) # Send email  send_email(message.as_string()) 
Enter fullscreen mode Exit fullscreen mode

Add the option to our main function.

# main.py  # Main section ... if __name__ == "__main__": # ....  if len(sys.argv)> 1 : # if ....  elif sys.argv[1] == '--attach': print("Sending an email with an attachment") send_attachment() else: # .... 
Enter fullscreen mode Exit fullscreen mode

We can test our function by executing the following command in our terminal.

python main.py --attach # Sending an email with an attachment # Successfully sent email 
Enter fullscreen mode Exit fullscreen mode

NOTE: To test this method we have to put in our project folder a file called file.pdf.

Final Words

Thanks for reading this post and don't forget to turn off the Less secure app access configuration.

You can find the code of this guide here.

Top comments (1)

Collapse
 
nataliiapolomkina profile image
nataliiapolomkina

Hey Brayan, your guide is awesome! Thanks for sharing it.
IFYI: you might like using Mailtrap for email-related tasks as it has native code integration with Python and RoR engineers mostly like this platform