2

I have created a function that uses the win32com library to create custom rules instead of creating them manually. I was not able to create the rule in outlook at first, so I tried to remove as much conditions as possible to find the error. This is the remaining Code snippet for this task, that has only a sender address condition and a moving to a folder action.

import win32com.client

def find_or_create_folder(parent_folder, folder_name):
    for folder in parent_folder.Folders:
       if folder.Name == folder_name:
       return folder
     return parent_folder.Folders.Add(folder_name)

def create_rule(subject, sent_to, sender_address, from_address, importance, folder_name,     alert_text, mark_as_read, category):

    try:
        outlook = win32com.client.GetActiveObject("Outlook.Application")
    except:
        outlook = win32com.client.Dispatch("Outlook.Application")

    namespace = outlook.GetNamespace("MAPI")
    inbox = namespace.GetDefaultFolder(6)  # 6 corresponds to the Inbox folder
    target_folder = find_or_create_folder(inbox, folder_name)

    rules = namespace.DefaultStore.GetRules()

    # Create a new rule
    # 0 corresponds to the olRuleReceive type
    rule = rules.Create("MyCustomRule", 0)

    # Set conditions
    if sender_address:
       sender_address_condition = rule.Conditions.SenderAddress
       sender_address_condition.Enabled = True
       sender_address_condition.Address = [sender_address]

    #check if foldername exists and then create the rule to move to a specific folder
    if folder_name:
       move_action = rule.Actions.MoveToFolder
       move_action.Enabled = True
       move_action.Folder = target_folder

   # Save the rule
    rules.Save()  # True to show progress dialog

subject = ""
sent_to = ""
sender_address = "example@gmail.com"
from_address = ""
importance = None
folder_name = "Test"
alert_text = ""
mark_as_read = False
category = ""

create_rule(subject, sent_to, sender_address, from_address,
importance, folder_name, alert_text, mark_as_read, category)

When I remove the code snippet below, the code works and the rule is created in outlook with the sender condition:

#check if foldername exists and then create the rule to move to a 
#specific folder     
if folder_name:         
   move_action = rule.Actions.MoveToFolder         
   move_action.Enabled = True         
   move_action.Folder = target_folder`

However I want to be able to move to a different folder, but this doesn't work.

I tried removing all the conditions to see what is the source of the problem, and it boiled down to moving to a different folder.

I tried creating the folder in a different way:

 try:          
     target_folder = inbox.Folders(folder_name)      
 except:          
     target_folder = inbox.Folders.Add(folder_name)`

But the problem persists, and it is not in creating the folder, because the code successfully creates the folder. The problem is precisely in trying to move the email to this created folder.

The error message is the following:

Traceback (most recent call last): File "c:\Users\houss\Desktop\scripts\mooreEmailRules.py", line 136, in <module> create_rule(subject, sent_to, sender_address, from_address, File "c:\Users\houss\Desktop\scripts\mooreEmailRules.py", line 113, in create_rule rules.Save() # True to show progress dialog File "<COMObject GetRules>", line 2, in Save pywintypes.com_error: (-2147352567, 'Exception occurred.', (4096, 'Microsoft Outlook', 'One or more rules cannot be saved because of invalid actions or conditions.', None, 0, -2147467259), None)

I also wasn't able to find proper documentation for this library in python and I am still new to this com thing.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
HousamKak
  • 23
  • 3
  • After you set the target folder (`move_action.Folder`), can you read folder properties from the action (e.g., `move_action.Folder.Name`)? – Dmitry Streblechenko Apr 15 '23 at 16:30
  • @DmitryStreblechenko I tried actually printing the (`move_action`) object and it printed (`>`). Following that, trying to print the Name property using (`move_action.Folder.Name`) gives me this error (`AttributeError: 'NoneType' object has no attribute 'Name'`) – HousamKak Apr 16 '23 at 17:08
  • Which pretty much means that the Folder property is not set, right? Are you sure target_folder is not null in your code? Does it work if you use inbox instead? – Dmitry Streblechenko Apr 16 '23 at 17:35
  • Fwiw, I can reproduce this: I have a valid non-null folder object (I can see the folder being created under my Inbox, and I can access it like any other folder). I assign it to `move_action.Folder`, but when I immediately query the `Folder` property, it is now None. I have functionally identical code in VBA which works without error, creates and saves the Rule. Also, the code using `comtypes` in this example https://stackoverflow.com/questions/56980384/use-python-to-create-rule-in-outlook-from-sender-email-address works. – DS_London Apr 17 '23 at 14:02
  • I added to an existing Issue on the `win32com` project: https://github.com/mhammond/pywin32/issues/1896 – DS_London Apr 17 '23 at 15:47
  • @DS_London I am so glad that I indirectly contributed to an open source library, thank you DS_London – HousamKak Apr 18 '23 at 06:36

0 Answers0