Как постоянно отслеживать новую почту в Outlook и непрочитанные письма определенной папки в python

Я хочу проверить электронное письмо от определенного отправителя и автоматически обрабатывать его, где бы оно ни было

Однако может возникнуть ситуация, когда мой Outlook был перезапущен, в то время как я получил почту от отправителя и помечен как непрочитанный

Для непрерывного мониторинга новой почты для определенной темы я нашел следующий код

import win32com.client
import pythoncom
import re

class Handler_Class(object):
  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 = outlook.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


outlook = win32com.client.DispatchWithEvents("Outlook.Application",Handler_Class)

#and then an infinit loop that waits from events.
pythoncom.PumpMessages() 

Даже я хочу просмотреть все непрочитанные письма, чтобы проверить, пришло ли письмо от отправителя, и обработать его (если оно найдено)

Есть ли какая-либо функция для проверки непрочитанных писем для добавления в handler_class

Или дайте мне знать для любой альтернативной процедуры


person sireesha    schedule 06.04.2018    source источник
comment
Вы планируете перезапустить программу Python после перезапуска Outlook? если да, вы можете проверить наличие непрочитанной электронной почты в качестве первого действия вашего скрипта перед выполнением pythoncom.PumpMessages()   -  person Ben.T    schedule 10.04.2018
comment
Я ищу случай, если срок действия моих учетных данных Outlook истек, и я попытался войти в систему с моими новыми учетными данными или моя система была перезагружена. .также можете ли вы поместить пример кода для приведенного выше комментария.   -  person sireesha    schedule 11.04.2018
comment
Если вы не перезапустите свой скрипт Python, я не знаю, как это сделать. Если да, то смотри мой ответ   -  person Ben.T    schedule 11.04.2018
comment
Большое спасибо Бен!!!...   -  person sireesha    schedule 12.04.2018
comment
У меня есть вопрос, вы пробовали свой код после перезапуска Outlook? под этим я подразумеваю, вы все еще получаете мониторинг полученного сообщения (я не говорю о непрочитанном), если вы не перезапустите свой скрипт Python после перезапуска Outlook?   -  person Ben.T    schedule 12.04.2018


Ответы (2)


Поэтому, если вы перезапускаете свой скрипт Python каждый раз при перезапуске Outlook, добавьте эти строки в свой код, чтобы проверять непрочитанные электронные письма в папке «Входящие»:

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

Поместите этот код перед определением outlook в свой код.

ИЗМЕНИТЬ

Для меня код, который вы разместили, отлично работает, пока я не закрою Outlook, а затем, даже если я снова открою его, я ничего не получаю при получении нового сообщения (см. один из моих комментариев). Я предполагаю, что факт закрытия Outlook "отвязать" с pythoncom.PumpMessages(). В любом случае, я прихожу, чтобы проверить вашу почту на наличие непрочитанной почты в классе Handler_Class и перезапустить мониторинг на случай, если вы перезапустите 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)

Не уверен, что это лучший способ, но, похоже, он работает так, как вы ищете.

person Ben.T    schedule 11.04.2018
comment
Кто-нибудь еще, как вы можете предложить мне, как поступить в этом случае, если срок действия моих учетных данных Outlook истек, и я попытался войти в систему с моими новыми учетными данными ... значит, пока я получил 3 письма ... как обработать, чтобы проверить эти письма - person sireesha; 12.04.2018
comment
Спасибо, Бен, даже я заметил то же самое, когда пытался вчера ... проверю код и сообщу вам - person sireesha; 13.04.2018
comment
Привет, Бен, есть ли способ запустить/остановить pythoncom.PumpMessages() через равные промежутки времени, скажем, каждый час - person sireesha; 17.04.2018
comment
Привет, Бен, я попробовал что-то подобное в своем коде, если outlook_open == True: outlook=win32com.client.DispatchWithEvents(Outlook.Application, Handler_Class), а True: start_time= while time.clock() ‹ 100: pythoncom.PumpWaitingMessages() outlook_open=processExists('OUTLOOK.EXE') if outlook_open == False: ctypes.windll.user32.PostQuitMessage(0) break # Чтобы не проверять все время (должно увеличиться на 10 в зависимости от ваших потребностей) if outlook_open == False: print Outlook не открыт os.startfile(outlook) time.sleep(10) - person sireesha; 18.04.2018
comment
@Ben.T Привет, Бен, могу я узнать у тебя, есть ли способ контролировать только 1 почтовый ящик в пределах OnNewMailEx? Я застрял на этом некоторое время и задавался вопросом, возможно ли либо DispatchWithEvents указать конкретный почтовый ящик/папку, либо проверить, принадлежит ли почтовый элемент определенной учетной записи? Кажется, я не могу найти такое свойство в MSDN. Благодарю вас! - person AiRiFiEd; 11.03.2019
comment
@Ben.T Не беспокойтесь, Бен, и спасибо за вашу помощь! Пробовал методы Dispatch и очень предпочел бы подход, управляемый событиями, но мне трудно с DispatchWithEvents, учитывая отсутствие документации по win32com. Проблема со свойствами To и Recipients заключается в том, что большинство писем отправляются в оба почтовых ящика (один из которых является групповым почтовым ящиком). Вы случайно не знаете, что происходит за кулисами, когда я передаю 'Outlook.Application' и Handler_Class методу DispatchWithEvents? т.е. какие аргументы может принимать __init__(self,...) в Handler_Class? Спасибо еще раз! - person AiRiFiEd; 12.03.2019
comment
Чтобы уточнить, например, DispatchWithEvents каким-то образом знает, что Handler_Class имеет метод OnNewMailex (который, как я полагаю, взят из docs.microsoft.com/en-us/office/vba/api/) и каким-то образом передает EntryIDCollection этому методу. Однако смогу ли я написать пользовательскую функцию в Handler_Class, которая принимает аргументы? Извините за беспокойство! - person AiRiFiEd; 12.03.2019
comment
@Ben.T кое-что только что пришло мне в голову - не думаешь ли ты, что имеет смысл использовать try: msg = outlook.Session.GetItemFromID(entry_ID, store_ID и except: pass, где store_ID будет соответствующим store_ID папки, которую мне интересно слушать? Однако это потребует, чтобы я сначала получил интересующий store_ID, с оговоркой, что store_ID уникален для машины (насколько я понимаю) - person AiRiFiEd; 12.03.2019
comment
@AiRiFiEd звучит как возможность, но вы должны задать новый вопрос, например, в комментариях, мне трудно понять точно, и вы также можете получить помощь от большего количества людей;) - person Ben.T; 12.03.2019
comment
@Ben.T извинения, Бен, мои вопросы обычно не публикуются... нет другого выбора, кроме как задать через комментарии - извиняюсь! - person AiRiFiEd; 12.03.2019
comment
Я пытаюсь изменить тему, но это не работает. Может кто подскажет поработать над текстами частичной тематики? - person guialmachado; 29.04.2020
comment
@Ben.T: Отличный код, спасибо! Я сделал это, чтобы отправлять push-уведомления на свой телефон, когда приходит электронное письмо от определенных отправителей. Очень круто! Единственная проблема, с которой я столкнулся, это то, что если Outlook закрыть и снова открыть, скрипт перестает работать и даже зависает Outlook. В итоге я удалил цикл while True, чтобы выйти из кода вместе с Outlook, а затем запустить его вручную после Outlook. Также ищу решение VBA, поэтому у меня не всегда будет открыто это окно python. - person yuk; 23.02.2021
comment
@yuk хорошее использование этого кода, отправляющего уведомление на телефон. Я уверен, что версию VBA можно закодировать, удачи с этим :) - person Ben.T; 24.02.2021

Вместо того, чтобы отслеживать Outlook из Python, попробуйте настроить правила Outlook для этого электронного письма, а затем запустить скрипт Python через vba.

Вот код для запуска скрипта Python из VBA.

Примечание. Приведенный ниже код взят из здесь.

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

Ниже этой строки находится скрипт Python для тех, кто заинтересован. В настоящее время он настроен на управление контактами DTR на последовательном порту com1. Следующее нужно будет сохранить как файл yourname.py

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()
person Nikhil Dusane    schedule 16.08.2019