Home > Blockchain >  I am trying to download attachments from Outlook using Python by specifying subject line. But the co
I am trying to download attachments from Outlook using Python by specifying subject line. But the co

Time:11-06

Below is my code:

import win32com.client
import os
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6) # "6" refers to the index of a folder - in this case the inbox. You can change that number to reference
messages = inbox.Items
message = messages.GetFirst()
subject = message.Subject
body = message.body
#
get_path = 'C:\\Users\\username\\Downloads'

for m in messages:
    if m.Subject == "Dummy report":
        attachments = message.Attachments
        num_attach = len([x for x in attachments])
        for x in range(1, num_attach):
            attachment = attachments.Item(x)
            attachment.SaveAsFile(os.path.join(get_path,attachment.FileName))
            print (attachment.FileName)
            break

    else:
        message = messages.GetNext()

Please let me know what is wrong with this code. I was able to find the specific mail but I was not able to download the attachment associated with that mail.

CodePudding user response:

First, the subject line may contain forbidden symbols for file names. Make sure the file name string is safe. The file will not be saved if the string contains any forbidden symbols.

Second, it makes sense to check the Attachment.Type property which returns an OlAttachmentType constant indicating the type of the specified object. Make sure that you deal with real attached files by making sure the property is set to the olByValue value.

Third, make sure the FileName property is not empty. In some cases you may need to use the DisplayName property value instead.

Fourth, direct comparison of the subject line is not the best way to find items with a specified subject line. It may be prepended with RE: or FW: prefixes.

for m in messages:
    if m.Subject == "Dummy report":

Instead, you need to use the Find/FindNext or Restrict methods of the Items class. They allow getting items that correspond to your conditions without iterating over all items in the folder. Read more about these methods in the articles I wrote for the technical blog:

For example, you could use the following search criteria (VBA syntax):

criteria = "@SQL=" & Chr(34) _ 
& "urn:schemas:httpmail:subject" & Chr(34) _ 
& " ci_phrasematch 'question'" 

This example shows Equivalence Matching, assuming that the folder you are searching contains items with the following subjects:

Question
Questionable
Unquestionable
RE: Question
The big question

If a store is indexed, searching with content indexer keywords is more efficient than with like. If your search scenarios include substring matching (which content indexer keywords don't support), use the like keyword in a DASL query.

Read more about that in the Filtering Items Using a String Comparison article.

CodePudding user response:

Taking on board some of @Eugene Astafiev's points, this code will iterate over the Inbox for a matching subject:

import win32com.client as wc
from os.path import join

ol = wc.gencache.EnsureDispatch('Outlook.Application')
ns = ol.GetNamespace('MAPI')

inbox = ns.GetDefaultFolder(wc.constants.olFolderInbox)

items = inbox.Items
pattern = 'Dummy report'

criteria = '@SQL="urn:schemas:httpmail:subject" like \'%'   pattern   '%\''
   
msg = items.Find(criteria)

while msg is not None:
    for att in msg.Attachments:
        if att.Type == wc.constants.olByValue:
            att.SaveAsFile(join('c:\\temp',att.FileName))
            print(att.FileName)
    
    msg = items.FindNext()

I have to say that I did try to use ci_phrasematch with Find, as suggested, but it would not work for me (even cutting & pasting the MS example into VBA). The keyword like does seem to work though.

NB. By using EnsureDispatch to create the Outlook object, you can access the Outlook enumerated constants from the documentation (such as olFolderInbox and olByValue) without resorting to magic numbers.

  • Related