Search and organize mail - israel-dryer/Outlook-Python-Tutorial GitHub Wiki

In this lesson, I’m going to show you how to search and organize your mail in Outlook, using Python. Also, I’m going to show you a method for recursively searching and collecting every message in your account folder that meets your search criteria. This is a method you can customize for whatever search operation you want to perform on your own.

The first steps are standard... import the win32com library and startup and instance of Outlook.

import win32com.client as client

# startup outlook instance
outlook = client.Dispatch('Outlook.Application')

# get namespace so that we can access folders
namespace = outlook.GetNameSpace('MAPI')

# get the inbox folder, specifically
inbox = namespace.Folders['Inbox'] 

# alternatively you could have used the following
inbox = namespace.GetDefaultFolder(6)`

Search toolbox

There is a searching mechanism in the win32com api, however, using a pure python approach is actually MUCH simpler.

There are a few key search tools that we'll use:

  • str.endswith()
  • str.startswith()
  • ==
  • in

You can also use regular expressions if you want, but we won't be covering that here.

Simple search examples

In this example, I'm searching for an email address that ends with youtube.com using the str.endswidth() method. All of the emails will be collected in a list comprehension where they will be moved to a newly created folder YTEmails.

# collect all relevant messages
yt_emails = [message for message in inbox.Items if message.SenderEmailAddress.endswith('youtube.com')]

# create a new folder for these messages
yt_folder = inbox.Folders.Add('YTEmails')

# move the messages to the new folder
for message in yt_emails:
    message.Move(yt_folder)

The same kind of search above can be performed with the str.startswith() method, or the == operator. The == operator will return an exact match, however. So if you have a specific term you want to check for, then this is a good choice.

I chose to search based on the SenderEmailAddress property, however, any of the mail properties can be used as a filter. In this next example, I'm going to use the in operator to look for a term within the Body of the email.

# filter messages with a body that includes a specific term
junk_messages = [message for message in inbox.Items if 'deal' in message.Body.lower()]

# I'm using the `lower` method above to prevent issues with capitalization

# delete all the junk messages
for message in junk_messages:
    message.Delete()

Recursive searches

Until now, we've only performed searches within a single folder. However, often you need to perform a search in many folders, including subfolders. In this case, a recursive search is required.

In the following example, I'm using a recursive search function to check a folder for messages that match the search term. I'm then checking to see if there are subfolders. If so, I call the same function on each of those subfolders. When all checks have been made, and the function is returned, I will have accumulated the results from the search of all folders.

def mail_body_search(term, folder): 
    """Recursively search all folders for email containing the search term"""
    try:
        relevant_messages = [message for message in folder.Items if term in message.Body.lower()]
    except AttributeError:
        # not items in the current folder
        relevant_messages = []

    # check for subfolders (base case)
    subfolder_count = folder.Folders.Count

    # search all subfolders
    if subfolder_count > 0:
        for subfolder in folder.Folders:
            relevant_messages.extend(mail_body_search(term, subfolder))

    return relevant_messages

Now that the function has been created, I can use it to move all messages that contain the term python into a folder for my python messages. Because I want to search ALL folders, including the inbox, I'm going to use the namespace object as the starting folder... which represents my account.

# create a folder for python messages
py_messages = inbox.Folders.Add('PyMessages')

# search for all messages containing the word "python"
matches = mail_body_search('python', namespace)

# move all messages to the new folder
for message in matches:
    message.Move(py_messages)