Deploy a python script to monitor mailbox and download attachments automatically

Question:

Below is the code to download attachments from a sender with a specific subject. I need to deploy it locally on my computer so that this code keeps monitoring outlook and as soon as the email arrives, it should download the attachment. I have earlier deployed ml models with flask. I need help to deploy this locally. Currently running the .py script in batch mode

import imaplib
import base64
import os
import email
import imap_tools
from imap_tools import MailBox
import win32com.client
import os
from datetime import datetime, timedelta
outlook = win32com.client.Dispatch('outlook.application')
mapi = outlook.GetNamespace("MAPI")
messages = inbox.Items
received_dt = datetime.now() - timedelta(days=7)
received_dt = received_dt.strftime('%m/%d/%Y %H:%M %p')
messages = messages.Restrict("[ReceivedTime] >= '" + received_dt + "'")
messages = messages.Restrict("[SenderEmailAddress] = '[email protected]'")
messages = messages.Restrict("[Subject] = '[EXTERNAL] Fwd: Expense Report'")
outputDir = r"\BLRESGANALXXXXXXXXXattachment_download"
try:
    for message in list(messages):
        try:
            s = message.sender
            for attachment in message.Attachments:
                attachment.SaveASFile(os.path.join(outputDir,attachment.FileName))
                print(f"attachment {attachment.FileName} from {s} saved")
        except Exception as e:
            print("error when saving the attachment:" + str(e))
except Exception as e:
    print("error when processing emails messages:" + str(e))
Asked By: Subhojyoti Lahiri

||

Answers:

One solution is to register to receive certain Events from the Outlook application. This code hooks into the OnItemAdd Event of the Inbox’s Items collection.

import win32com.client
import pythoncom

#Class to handle events from an Items collection object
class Items_Handler(object):
    def OnItemAdd(self,item): #Handles Items::OnItemAdd event
        #Test if it is a MailItem
        if item.Class == win32com.client.constants.olMail:
            print('New Mail Item!')
            print('   From:',item.SenderEmailAddress)
            print('   Subject:',item.Subject)
            print('   Received at:',item.ReceivedTime)
            #Do whatever you want with the message (eg save attachments)

#Create the Outlook application object
outlook = win32com.client.gencache.EnsureDispatch('Outlook.Application')
#Get the Inbox
inBox = outlook.GetNamespace('MAPI').Folders['[email protected]'].Folders['Inbox']
#Get the Items collection for the Inbox
items = inBox.Items
#Tell Outlook you are interested in the events for the Items collection
win32com.client.WithEvents(items,Items_Handler)

print('Listening ...')
#Message loop: will handle incoming events/messages until script killed
pythoncom.PumpMessages()

You can amend the OnItemAdd handler to do whatever you want with the message, eg filter for sender, subject, save attachments etc.

NB. It will only process new messages, so you may still need your original code to sweep up any new messages in your InBox that arrived before this script started.

There is also a caveat in the documentation for ItemAdd that the event might not fire if ‘a large number’ of items are added to the folder at once.

Answered By: DS_London
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.