pythonpython-3.xoutlookwin32com

Outlook using python win32com reading only email till a specific date and nothing after that


Below is my Python code using win32com to read emails from a particular folder.


from logging import root
import os
import win32com.client
from datetime import datetime, timedelta
import zipfile

date_format = "%m/%d/%Y %H:%M"

def recursively_find_folder(folder, target_name):
    if folder.Name == target_name:
        return folder
    for subfolder in folder.Folders:
        found_folder = recursively_find_folder(subfolder, target_name)
        if found_folder:
            return found_folder

#function to check the emails mentioned in outlook folder and down load the attachements based on email subject
def download_attachments(folder_name, output_folder, start_time, end_time, target_subject):
    outlook_app = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
    #root_folder = outlook_app.Folders.Item(3)  # Assume the first folder is the mailbox
    root_folder = outlook_app.GetDefaultFolder(6)  # Assume the first folder is the mailbox
      
    target_folder = recursively_find_folder(root_folder, folder_name)

    if target_folder:
        print(f"Found folder: {target_folder.Name}")

        # Iterate through items in the folder
        items = target_folder.Items
        items.sort("[ReceivedTime]", True)

        for item in items:
            print("Item:: ", item)
            print("    Subject:: ", item.Subject.lower())
            print("    Recevied Time: ", item.ReceivedTime)
            # Check if the email matches the criteria
            for subject in target_subject:
                print(subject)
                print("Email Received Time: ", datetime.strptime(item.ReceivedTime.strftime('%m/%d/%Y %H:%M'), date_format))
                if (
                    start_time <= datetime.strptime(item.ReceivedTime.strftime('%m/%d/%Y %H:%M'), date_format) <= end_time
                    and subject.lower().strip() in item.Subject.lower().strip()
                    and item.Attachments.Count > 0
                ):
                    print(f"Processing email: {item.Subject}")
                    for attachment in item.Attachments:
                        # Save attachments to the output folder
                        attachment.SaveAsFile(os.path.join(output_folder, attachment.FileName))
                        print(f"Downloaded attachment: {attachment.FileName}")
                else:
                    print("Nothing Happened!!!")

    else:
        print(f"Folder '{folder_name}' not found.")
        
#--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#function to find zip folder and unzip it
def find_and_unzip_report_file(folder_path, extraction_path):
    # Check if the folder exists
    if not os.path.exists(folder_path):
        print(f"Error: Folder '{folder_path}' not found.")
        return

    # Get a list of all files in the folder
    files = os.listdir(folder_path)

    # Find the report file based on the name pattern
    report_file = next((file for file in files if file.lower().startswith('report') and file.lower().endswith('.zip')), None)

    if report_file:
        # Construct the full path to the zip file
        zip_file_path = os.path.join(folder_path, report_file)

        # Create the extraction path if it doesn't exist
        os.makedirs(extraction_path, exist_ok=True)

        # Unzip the contents of the zip file
        with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
            zip_ref.extractall(extraction_path)
        
        os.rename(folder_path + 'CC CM Provisioning - INC SLA - ALL.csv', folder_path + 'CC CM Provisioning - INC SLA - ALL' + '-' + report_file[7:24] + '.csv')
        
        os.remove(zip_file_path)
        print(f"Successfully unzipped '{zip_file_path}' to '{extraction_path}'.")
    else:
        print("Error: Report file not found in the specified folder.")


if __name__ == "__main__":
    folder_to_download = "service_tickets"
    output_directory = "//prod_drive/meta/downloads/"
    # Get the first day of the current month
   
    start_date_time = (datetime.today().replace(day=1, hour=23, minute=0, second=0, microsecond=0) - timedelta(days=1)).strftime('%m/%d/%Y %H:%M')
    
    end_date_time = (datetime.today().replace(day=1, hour=23, minute=10, second=0, microsecond=0) - timedelta(days=1)).strftime('%m/%d/%Y %H:%M') 
    date_format = "%m/%d/%Y %H:%M"
    start_time = datetime.strptime(start_date_time, date_format)
    print("Start Time:", start_time)
    end_time = datetime.strptime(end_date_time, date_format)
    print("End Time: ", end_time)
    target_subject = ['CC CM Provisioning - INC SLA - ALL','CC CM Provisioning - SCTASK SLA - All','CC CM Provisioning - SCTASK - All']


    download_attachments(folder_to_download, output_directory, start_time, end_time, target_subject)
    
    find_and_unzip_report_file(output_directory, output_directory)

But the above code only reads email till 05/31/2024 and nothing after that. I tried running the code for other folders as well, but is the same. Emails scanned/processed only till 05/31.

Could someone please advise what exactly the issue in my code. Couldnt find any similar posts regarding this.


Solution

  • It seems win32com works only with Outlook Classic which uses a .pst data file, and I switched from outlook classic to 'New Outlook' on May. As a result, my mailbox and folders were not synced in the classic version and the code is picking only those till May which are available there. After i switched to the classic version, I saw that my mailbox is not refreshed, and after a while when the mailbox got refreshed and ran the above code, it started reading all the emails from the necessary folders as desired.

    enter image description here

    Hopefully in future, win32com might put in a fix to read from 'New Outlook' as well where the .pst file is not being used.