How to Access Your Email Using Python

Manage Your Emails Efficiently Using Python

How to Access Your Email Using Python

Email communication has become an essential aspect of our personal and professional lives in today's fast-paced world. As the amount of emails we receive keeps growing, organizing them can seem challenging. Thankfully, the imaplib module in Python provides a handy and effective method for accessing email content and automating email management duties.

This article aims to demonstrate the utilization of the imaplib and email module for accessing email content and carrying out multiple email management tasks. The subsequent areas will be covered:

  • Establishing a connection with an IMAP server

  • Obtaining emails from a specific folder

  • Analyzing the content of an email

  • Saving email content to a file

  • Displaying email content in an easily readable format on the console

By the end of this article, you will understand how to use Python to access and manage email content, making your email management tasks more efficient and less time-consuming.

Prerequisite

  • A Gmail account. I recommend you create a separate email for testing

  • Python 3.x installed on your machine

  • Fundamental knowledge of Python

  • Both imaplib and email are built-in modules in Python, so you don't need to install them separately.

  • html2text library to convert email content in HTML to plain text

Getting Your Gmail Account Information

To connect to your email account, you will need the following information:

  1. The name of the server (e.g., imap.gmail.com)

  2. Your email address (e.g., )

  3. Your email password(App password). Make sure to keep this information secure.

Since May 30th, 2022 Google has removed the less secure app setting from all Google accounts. By enabling less secure apps it allowed us to use our email address and password directly in our code to access the SMTP server.

There is a workaround for accessing the SMTP server called App passwords. You use app passwords when you have applications that need access to your Google account but you also have 2-Step Verification enabled on our Google account. So if you have 2-Step Verification enabled, you can set up app passwords and use that in place of your standard Google password.

To set up app passwords;

  • Visit the Manage your Google Account page of your G-account and navigate to the Security tab on the page.

  • Make sure you have 2-Step Verification enabled on your account if not already enabled.

  • Click on 2-Step Verification, scroll down to the App passwords section, and click on it.

  • Click on Select app and choose Other(Custom name)** from the dropdown options

  • Give your token a nice name

  • Click on Generate

Now you have an access token that can be used to access your email from your Python script.

Make sure to keep your generated token safe and secure.

The Script

In this section, you're going to implement the functionalities needed to access and manage your emails using Python.

Using the concept of OOP you're going to create a EmailRetriever class that consists of standalone methods and functions that perform different actions. you can also add more functions based on the functionality you need.

To start, create a Python file, email_retriever.py in any directory of your choice.

Connecting to Your Email Account

Add the following code to the email_retriever.py file:

import imaplib
import email
import pprint
import re
import html2text
import unicodedata

class EmailRetriever:
    def __init__(self, server, email, password):
        self.server = server
        self.email = email
        self.password = password
        self.imap = self._connect_to_server()

    def _connect_to_server(self):
        """
        Connect to the IMAP server using the given username and password.
        Returns the IMAP4 object representing the connection.
        """
        imap = imaplib.IMAP4_SSL(self.server)
        imap.login(self.email, self.password)
        return imap

This code defines a class EmailRetriever that has a constructor method (__init__) and a private method (_connect_to_server). The class uses several imported libraries such as imaplib, email, pprint, re, html2text, and unicodedata.

The __init__ method takes three arguments (server, email, password) and initializes the corresponding instance variables. Then, it calls the _connect_to_server method to establish a secure connection with an email server using the IMAP4_SSL protocol and returns an IMAP4 object representing the connection.

The _connect_to_server method is a private method that establishes a secure connection to the email server using the IMAP4_SSL protocol, and then logs in with the given username and password using the login method of imaplib. Finally, it returns the IMAP4 object representing the connection.

Retrieving Email Contents

Add the following code to the email_retriever.py file as an instance method of the EmailRetriever class.

    def get_emails(self, folder="INBOX"):
        """
        Retrieve a list of email messages from the given folder on the IMAP server.
        Returns a list of email message objects.
        """
        self.imap.select(folder)
        # status, messages = self.imap.search(None, "ALL")
        status, messages = self.imap.search(None, '(FROM "Julia at CoRise")')
        messages = messages[0].split(b' ')
        emails = []
        for msg in messages:
            _, data = self.imap.fetch(msg, "(RFC822)")
            emails.append(email.message_from_bytes(data[0][1]))
        return emails

The get_emails method retrieves a list of email messages from the specified email folder on the server. It uses the select method to choose the folder, then uses the search method to filter the messages by a specific criterion, such as sender, subject, or date. The resulting list of message IDs is then fetched using the fetch method and converted to email message objects using the message_from_bytes method. The parsed messages are returned as a list.

Parsing Email Content

Add the following codes to the email_retriever.py file as an instance method of the EmailRetriever class.

    def parse_email(self, email):
        """
        Parse the header and body of the given email message.
        Returns a dictionary containing the parsed data.
        """

        parsed_email = {}

        # Get Header Content
        parsed_email["subject"] = self.header_decode(email.get("Subject"))
        parsed_email["from"] = self.header_decode(email.get("From"))
        parsed_email["to"] = self.header_decode(email.get("To"))
        parsed_email["delivered-to"] = self.header_decode(email.get("Delivered-To"))
        parsed_email["date"] = self.header_decode(email.get("Date"))
        parsed_email["reply-to"] = self.header_decode(email.get("Reply-to"))

        # Get Body
        parsed_email["zbody"] = self.parse_email_body(email)

        return parsed_email

The parse_email method parses the header content of a given email message and returns a dictionary containing the parsed data. It uses the header_decode method to decode and normalize the header fields and the parse_email_body method to parse the message body.

    def parse_email_body(self, email):
        """
        Parse the body of the given email message.
        Returns a dictionary containing the plaintext and HTML versions of the body.
        """
        body = {"text": "", "zhtml": ""}
        if email.is_multipart():
            for part in email.get_payload():
                if part.get_content_type() == "text/plain":
                    body["text"] = self.remove_special_chars(part.get_payload())
                elif part.get_content_type() == "text/html":
                    body["zhtml"] = html2text.html2text(part.get_payload())
        else:
            body["text"] = email.get_payload()
        return body

The parse_email_body method parses the body of a given email message and returns a dictionary containing the plaintext and HTML versions of the body. It iterates over the message's payload to find the plaintext and HTML parts, then converts the HTML to plain text using the html2text module.

    def header_decode(self, header):
        hd = ""
        for part, encoding in email.header.decode_header(header):
            if isinstance(part, bytes):
                part = part.decode(encoding or "utf-8")
            hd += part
        return hd

The header_decode method decodes and normalizes the given header field using the decode_header method from the email.header module.

    def remove_special_chars(self, string):
        # Normalize the string to remove accents
        string = unicodedata.normalize('NFD', string).encode('ascii', 'ignore').decode('utf-8')

        # Remove all non-alphanumeric characters
        string = re.sub(r'[^a-zA-Z0-9\s]', '', string)

        # Remove extra whitespace
        string = re.sub(r'\s+', ' ', string).strip()

        return string

The remove_special_chars method normalizes and removes all non-alphanumeric characters from a given string, leaving only whitespace and alphanumeric characters.

Saving Email Content to a File

Add the following code to the email_retriever.py file as an instance method of the EmailRetriever class.

    def pretty_print_emails(self, emails):
        """
        Pretty print the content of the given email messages to the console.
        """
        for email in emails:
            pprint.pprint(self.parse_email(email))

    def write_emails_to_file(self, emails):
        """
        Write the content of the given email messages to a file with the given name.
        """
        # save to file
        num = 0
        for email in emails:
            email = self.parse_email(email)

            f = open("mail_" + str(num) + ".txt","w")
            for key, value in email.items():
                f.write(f"{key}: {value}\n")
            f.close()
            num += 1

The pretty_print_emails method prints the content of a list of parsed email messages to the console in a formatted way using the pprint module.

The write_emails_to_file method writes the content of a list of parsed email messages to separate text files, one file per email, named with a unique identifier.

You can extend the functionalities of the EmailRetriver class to suit your needs by adding more instance methods to the class.

Example Usage

# Example usage:
email_retriever = EmailRetriever("imap.gmail.com", "in**ngz****gmail.com", "qy** *jdg p**x *eh*")
emails = email_retriever.get_emails()
email_retriever.pretty_print_emails(emails)
email_retriever.write_emails_to_file(emails)

Now you have a ready-to-use Python script consisting of a class and instance methods to manage your emails. Cheers

Conclusion

In this article, we have discussed how Python's imaplib module can be used for email automation. We have seen that it provides a convenient interface for connecting to and retrieving emails from an email server. We have also explored how to parse and extract relevant information from email messages using Python's email module.

Using Python's imaplib module for email automation can offer several benefits, including the ability to automate repetitive tasks, such as downloading attachments or parsing through large numbers of emails, and the ability to integrate email functionality into larger applications. Additionally, using Python's imaplib module can save time and increase efficiency by allowing users to automate tasks that would otherwise have to be performed manually.

To continue learning about this topic, readers can explore the official Python documentation on imaplib and email modules, as well as various tutorials and online resources available. They can also experiment using Python's imaplib module to build their email automation tools and applications.