I want to check for a particular sender email and process it automatically wherever it arrives
However, there may be some situation where my outlook was restarted, m
So if you restart your python script every time your Outlook restart, then add these lines to your code to check unread emails in your Inbox:
ol = win32com.client.Dispatch( "Outlook.Application")
inbox = ol.GetNamespace("MAPI").GetDefaultFolder(6)
for message in inbox.Items:
if message.UnRead == True:
print message.Subject #or whatever command you want to do
Put this code before your definition of outlook
in your code
EDIT
For me, the code you posted works great until I close Outlook and then even if I reopen it, I don't get anything when a new message is received (see one of my comments). I guess the fact of closing Outlook "unlink" with pythoncom.PumpMessages()
. Anyway, I come around to do both your checking for unread email in the class Handler_Class
and restart the monitoring in case you restart Outlook.
import win32com.client
import ctypes # for the VM_QUIT to stop PumpMessage()
import pythoncom
import re
import time
import psutil
class Handler_Class(object):
def __init__(self):
# First action to do when using the class in the DispatchWithEvents
inbox = self.Application.GetNamespace("MAPI").GetDefaultFolder(6)
messages = inbox.Items
# Check for unread emails when starting the event
for message in messages:
if message.UnRead:
print message.Subject # Or whatever code you wish to execute.
def OnQuit(self):
# To stop PumpMessages() when Outlook Quit
# Note: Not sure it works when disconnecting!!
ctypes.windll.user32.PostQuitMessage(0)
def OnNewMailEx(self, receivedItemsIDs):
# RecrivedItemIDs is a collection of mail IDs separated by a ",".
# You know, sometimes more than 1 mail is received at the same moment.
for ID in receivedItemsIDs.split(","):
mail = self.Session.GetItemFromID(ID)
subject = mail.Subject
print subject
try:
command = re.search(r"%(.*?)%", subject).group(1)
print command # Or whatever code you wish to execute.
except:
pass
# Function to check if outlook is open
def check_outlook_open ():
list_process = []
for pid in psutil.pids():
p = psutil.Process(pid)
# Append to the list of process
list_process.append(p.name())
# If outlook open then return True
if 'OUTLOOK.EXE' in list_process:
return True
else:
return False
# Loop
while True:
try:
outlook_open = check_outlook_open()
except:
outlook_open = False
# If outlook opened then it will start the DispatchWithEvents
if outlook_open == True:
outlook = win32com.client.DispatchWithEvents("Outlook.Application", Handler_Class)
pythoncom.PumpMessages()
# To not check all the time (should increase 10 depending on your needs)
time.sleep(10)
Not sure it is the best way, but it seems to work the way you look for.
Instead of monitoring outlook from python, try setting up outlook rules for that email and then launch python script via vba.
Here is the code to launch the python script from VBA.
Note: The code below was taken from here.
Sub UruchomBata(MyMail As MailItem) Dim Ret_Val Dim args As String args = "c:\new.py" Ret_Val = Shell("C:\python27\python.exe" & " " & args, vbNormalFocus) End Sub
Below this line is the python script for those interested. It is currently set to control the DTR pins on the com1 serial port. The following will need to be save as a yourname.py file
import serial from time import sleep conn = serial.Serial('com1', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1, xonxoff=0, rtscts=0 ) # Wake Modem conn.setDTR(True) sleep(3) conn.setDTR(False) sleep(1) conn.close() # Start talking try: while True: conn.write('AT'+chr(13)); print conn.readline() # readlines() will probably never return. finally: conn.close()