#python #pywin32 #win32com
Вопрос:
Я хочу подождать, пока все папки в Outlook не будут синхронизированы, чтобы начать загрузку вложений. Если я запускаю код, не открывая outlook и не синхронизируя сначала все папки, код не загружает последние электронные письма.
Код приведен ниже:
import os import win32com class DailyExtracts: def __init__(self): self.outlook = win32com.client.Dispatch("outlook.application").GetNamespace("MAPI") self.root = self.outlook.Folders.item(1) self.daily_reports = self.root.Folders[".data"].Folders["daily_reports"] def download_extracts(self): for message in self.daily_reports.Items: for attachment in message.Attachments: fname = attachment.Filename attachment.SaveAsFile(os.path.join(os.path.expanduser(r"~Downloads"), fname)) message.Unread = False
Я читал, что могу использовать SyncObjects.Синхронизируйте событие, чтобы дождаться завершения отправки/получения. Однако я не знаю, как это реализовать.
Ответ №1:
Вот одно (возможно, неэлегантное) решение, которое показывает основной принцип обработки событий Outlook. Проблема с обработкой событий COM (например, создаваемых Outlook) заключается в том, что они асинхронны, и коду приходится ждать, пока событие не будет запущено. Этот код использует цикл сообщений потока для блокировки до тех пор, пока не вернутся все события синхронизации.
Класс обработчика делает больше, чем требуется для операции, но также реагирует на ошибки при синхронизации.
import win32com.client as wc import pythoncom import win32api import win32con nSync = 0 #Class to handle the SyncObject events from Outlook class SyncHandler(object): #Save the dispatch interface to identify the SyncObject if needed def set(self,disp): self._disp = disp def _process(self): #Decrement sync counter global nSync nSync -= 1 print(nSync,'Sync remaining to complete') #If nothing left to sync, then send WM_QUIT to thread message loop if nSync lt;= 0: print('Closing message loop') win32api.PostThreadMessage(win32api.GetCurrentThreadId(), win32con.WM_QUIT, 0, 0) def OnSyncStart(self): print('Starting sync on',self._disp.Name) def OnSyncEnd(self): print('Sync complete on',self._disp.Name) self._process() def OnProgress(self,state,description,value,max): print('Sync progress: {0:} {1:} {2:}%'.format(self._disp.Name,description,100 * value/max)) def OnError(self,code,description): print('Sync Error',description) self._process() #Get the application Dispatch interface ol = wc.Dispatch('Outlook.Application') syncObjects = ol.GetNamespace('MAPI').SyncObjects #Find out how many SyncObjects we have nSync = syncObjects.Count print('Number of Sync objects:',nSync) for syncObj in syncObjects: #Set up an event handler and specify the event handler class handler = wc.WithEvents(syncObj,SyncHandler) handler.set(syncObj) syncObj.Start() #This will block until a WM_QUIT message is sent to the message queue pythoncom.PumpMessages() print('Sync completed')
Я проверил это на своем клиенте Outlook, у которого есть несколько учетных записей электронной почты, и, похоже, все работает нормально, хотя у меня такое чувство, что он синхронизирует только учетные записи, не связанные с Exchange (как я полагаю, учетные записи Exchange постоянно синхронизируются?).
Комментарии:
1. Спасибо @DS_London за ответ. Я узнал, что в pythoncom нет сообщений о перекачке. Ты знаешь, почему это может произойти?
2. @diegogiraldog Какое сообщение об ошибке вы получаете? И какова ваша версия pywin32?