Search code examples
pythonoutlookworkflowpywin32office-automation

How do I resolve the following error: AttributeError: GetNamespace.GetNamespace - when connecting to Outlook using Python?


I wrote some python code that does the following:

  1. connects to outlook and a specific subfolder
  2. gets a target date from the user
  3. searches all emails with attachments labeled "report.csv" using the specified target date
  4. removes/strips certain keywords in the subject of the email
  5. extracts the attachment
  6. saves the attachment with the parsed subject of the email in a specified folder

My code works as described but seems to crash when it iterates through the emails (or maybe dates), only extracting 4 out of the 30 or so reports I need. A copy of the code is below.

When it crashes, Vs Code is telling me the issue is on line 54 "outlook.GetNamespace.Quit()" and advising that it is "AttributeError: GetNamespace.Getnamespace"

Any thoughts and insight into this issue, would be greatly appreciated.

import os
import win32com.client
import datetime as dt
from datetime import date, timedelta
from pathlib import Path

EMAIL_ADDRESS = "emailaddress@example.com"
FOLDER_NAME = "subfolder_name"
OUTPUT_FOLDER = Path(r"Specify Path")   #specify the path

def connect_to_outlook():
    outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace ("MAPI")
    inbox_folder = outlook.GetDefaultFolder(6)  # Inbox folder
    sub_folder = inbox_folder.Folders(FOLDER_NAME)
    return sub_folder, outlook, inbox_folder, outlook

def extract_csv_attachments(emails):
    csv_attachments = [(email.Subject.split("[INSERT TEXT TO PARSE/SPLIT")[0].strip(), attachment)
                       for email in emails
                       for attachment in email.Attachments if attachment.FileName == "report.csv"]
    return csv_attachments

try:
    # Connect to Outlook
    sub_folder, outlook, inbox_folder, outlook = connect_to_outlook()

    # Get target date from user input
    target_date_str = input("Enter a target date (YYYY-MM-DD): ")
    target_date = dt.datetime.strptime(target_date_str, '%Y-%m-%d')

    # Construct search criteria and filter emails
    search_criteria = f'[SenderEmailAddress] = "{EMAIL_ADDRESS}" AND [ReceivedTime] >= "{target_date.strftime("%m/%d/%Y")}" AND [ReceivedTime] < "{(target_date + dt.timedelta(days=1)).strftime("%m/%d/%Y")}"'
    filtered_emails = sub_folder.Items.Restrict(search_criteria)
    

    # Extract CSV attachments from filtered emails
    csv_attachments = extract_csv_attachments(filtered_emails)

    # Save extracted attachments to output folder
    for email_subject, attachment in csv_attachments:
        attachment.SaveAsFile(OUTPUT_FOLDER / f"{email_subject}.csv")

finally:
    # Release Outlook resources
    sub_folder = None
    inbox_folder = None
    outlook.GetNamespace.Quit()
    outlook.Quit()

Solution

  • Use Application.Quit method - there is no Namespace.Quit method.

    Also keep in mind that most end users won't appreciate their Outlook closing on them: Outlook is a singleton, and creating an instance of the Outlook.Application object will return a pointer to the already running instance. If it is your code that created Outlook.Application object, there is no reason to call Application.Quit - Outlook will exit when your code reference to it is gone. If you really want to close it, at least check to make sure that both Application.Explorers.Count == 0 and Application.Inspectors.Count == 0 to ensure there are no open windows opened by the user.