Search code examples
pythonoutlookwin32comoffice-automation

com_error when saving emails in windows outlook with python


I'm using python to save emails in a specified folder and complete the following:

  • check if the email is unread
  • save the email to target folder
  • mark the message as read
  • tell me how many messages were archived and the location

the code:

from  win32com.client import Dispatch
import os

outlook = Dispatch('outlook.application').GetNamespace("MAPI")
root = outlook.Folders[0].Folders[27]
targetPath = os.path.expanduser(r'\\path\to\target\folder')
messages = root.Items
count = 0
for msg in messages:
    if msg.UnRead:
        msg.SaveAs(os.path.join(targetPath))
        msg.UnRead = False
        count +=1
print(str(count)+' emails archived to: '+targetPath)

I end up with this error i've never seen before, and I haven't had any luck with the google machine... so I come to stackoverflow and wake you from your slumber.

Traceback (most recent call last):

  File "C:\Users\e582324\Documents\Python Scripts\untitled6.py", line 18, in <module>
    msg.SaveAs(os.path.join(targetPath))

  File "<COMObject <unknown>>", line 3, in SaveAs

com_error: (-2147352567, 'Exception occurred.', (4096, 'Microsoft Outlook', 'The operation failed.', None, 0, -2147024829), None)

Any idea whats causing this? I have a similar script that saves just attachments and it works fine. My target folder is on a network shared drive for both scripts and it hasn't caused an issue until now. Only real difference is the use of .SaveAs() instead of .SaveAsFile()


Solution

  • You need to specify the file name as well as its extension. passing the path is not enough sometimes, especially when you don't specify the format (see the second parameter). Note, an Outlook folder may contain different kind of items - mail items, appointments, documents, notes and etc. For example, here is a sample:

    Item.SaveAs Environ("HOMEPATH") & "\My Documents\" & strname & ".txt", olTXT 
    

    Also I've noticed that you are iterating over all items in the folder:

    for msg in messages:
        if msg.UnRead:
    

    Instead, you need to use the Find/FindNext or Restrict methods of the Items class. So, you get only items that correspond to your conditions and iterate only over them. Read more about these methods in the following articles: