Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import gc
- import os
- import time
- import pythoncom
- import pywintypes
- import exceptions
- import types
- import base64
- import collections
- from win32com import storagecon
- from win32com.mapi import mapi, mapiutil
- from win32com.mapi.mapitags import *
- class MAPIReadTest:
- '''
- After instantiating object, call initialize_test function and then run_test function.
- Call closeMAPI() for cleanup
- '''
- def __init__(self, profile = None, read_attachments = True):
- print 'interface count:', pythoncom._GetInterfaceCount()
- # mapi initialize
- try:
- mapi.MAPIInitialize(None)
- except Exception, fault:
- raise
- self.profile = profile
- self.read_attachments = read_attachments
- self.email_count = 0
- def closeMAPI(self):
- # cleanup
- print 'interface count:', pythoncom._GetInterfaceCount()
- print self.email_count
- self.stores = {}
- gc.collect()
- self.session.Logoff(0,0,0)
- self.session = None
- try:
- mapi.MAPIUninitialize()
- except Exception, fault:
- raise
- print 'interface count:', pythoncom._GetInterfaceCount()
- def initialize_test(self):
- # flags for mapi logon
- logon_flags = (mapi.MAPI_NO_MAIL | mapi.MAPI_EXTENDED)
- if not self.profile:
- logon_flags |= mapi.MAPI_USE_DEFAULT
- else:
- logon_flags |= mapi.MAPI_NEW_SESSION
- # start session
- self.session = mapi.MAPILogonEx(0, self.profile, None, logon_flags)
- # get stores
- self.stores = {}
- msg_store_table = self.session.GetMsgStoresTable(0)
- rows = mapi.HrQueryAllRows(msg_store_table, (PR_ENTRYID,), None, None, 0)
- for row in rows:
- (eid_tag, eid) = row[0]
- storeobj = self.session.OpenMsgStore(0, eid, None, mapi.MAPI_DEFERRED_ERRORS | mapi.MDB_NO_DIALOG)
- hr, props = storeobj.GetProps([PR_DISPLAY_NAME], 0)
- name = props[0][1]
- self.stores[eid] = [name, storeobj, []]
- # traverse hierarchy, and store all PyIMAPIFolders in list(self.stores[eid][2])
- for eid in self.stores:
- self.traverse_hierarchy(self.stores[eid][1], '', self.stores[eid][0], self.stores[eid][2])
- print 'interface count:', pythoncom._GetInterfaceCount()
- def traverse_hierarchy(self, store, path, dpath, flist):
- if len(path.split('/')) == 1:
- eid, dfolder = self.openFolder(store)
- eid = base64.b16encode(eid)
- name = dpath
- path = eid
- else:
- name = dpath.rsplit('/', 1)[1]
- eid = path.rsplit('/', 1)[1]
- dfolder = store.OpenEntry(base64.b16decode(eid), None, mapi.MAPI_DEFERRED_ERRORS)
- info = {'eid' : eid, 'name' : name, 'path' : path, 'dpath' : dpath}
- ifolder = IterateFolder(dfolder)
- flist.append([info, dfolder, ifolder])
- table = dfolder.GetHierarchyTable(mapi.MAPI_UNICODE)
- rows = mapi.HrQueryAllRows(table, (PR_ENTRYID, PR_DISPLAY_NAME), None, None, 0)
- flags = mapi.MAPI_DEFERRED_ERRORS
- for (eid_tag, seid), (name_tag, sname), in rows:
- seid = base64.b16encode(seid)
- spath = path + '/' + seid
- sdpath = dpath + '/' + sname
- try:
- self.traverse_hierarchy(store, spath, sdpath, flist)
- except Exception, fault:
- print 'error in traverse_hierarchy for %s' % sdpath
- def openFolder(self, store, rw = False):
- hr, data = store.GetProps((PR_IPM_SUBTREE_ENTRYID,), mapi.MAPI_UNICODE)
- subtree_eid = data[0][1]
- flags = mapi.MAPI_DEFERRED_ERRORS
- if rw:
- flags |= mapi.MAPI_MODIFY
- return subtree_eid, store.OpenEntry(subtree_eid, None, flags)
- def run_test(self):
- for eid in self.stores: # traverse stores
- for folder in self.stores[eid][2]: # traverse list of all folders in store
- for email_entryid in folder[2].GetAllEids(): # traverse all entry ids in folder
- try:#open email from store
- email_obj = self.stores[eid][1].OpenEntry(email_entryid[1], None, mapi.MAPI_DEFERRED_ERRORS)
- self.email_count += 1
- except:
- print 'error while opening email ' + repr(fault)
- try:
- self.read_email(email_obj)
- except Exception, fault:
- print 'error in read_email ' + repr(fault)
- finally:
- print 'interface count: ', pythoncom._GetInterfaceCount()
- def read_email(self, email_obj):
- #read email data
- dump = email_obj.GetProps(email_obj.GetPropList(mapi.MAPI_UNICODE), mapi.MAPI_UNICODE)
- dump = None
- #read attachments
- if self.read_attachments:
- try:
- self.read_attachment(email_obj)
- except Exception, fault:
- print 'error in read_attachment ' + repr(fault)
- def read_attachment(self, email_obj):
- hr, hasattach = email_obj.GetProps([PR_HASATTACH,])
- if not hasattach:
- return
- attach_table = email_obj.GetAttachmentTable(mapi.MAPI_UNICODE)
- aidlist = mapi.HrQueryAllRows(attach_table, (PR_ATTACH_NUM), None, None, 0) # get all attachment ids
- for aid in aidlist:
- atch = email_obj.OpenAttach(aid[0][1], None, 0)
- hr, atch_method = atch.GetProps((PR_ATTACH_METHOD,))
- if atch_method[0][1] == mapi.ATTACH_BY_VALUE:
- data = self.readstream(atch, PR_ATTACH_DATA_BIN)
- del data
- elif atch_method[0][1] == mapi.ATTACH_EMBEDDED_MSG:
- msg = atch.OpenProperty(PR_ATTACH_DATA_OBJ, mapi.IID_IMessage, 0, 0)
- try:
- self.read_email(msg)
- except Exception, fault:
- print repr(fault)
- else:
- print 'Another method:%s'%atch_method[0][1]
- def readstream(self, obj, prop):
- stream = obj.OpenProperty(prop, pythoncom.IID_IStream, 0, 0)
- stream.Seek(0, storagecon.STREAM_SEEK_SET)
- size = stream.Stat()[2]
- data = ''
- while True:
- buf = stream.Read(4<<20)
- if not buf:
- break
- data += buf
- buf = None
- del stream
- return data
- class IterateFolder:
- def __init__(self, folder):
- self.folder = folder
- self.done = False
- self.ique = collections.deque()
- table = self.folder.GetContentsTable(mapi.MAPI_UNICODE)
- table.SetColumns((PR_ENTRYID, PR_RECORD_KEY), 0)
- table.SortTable((((PR_RECORD_KEY, mapi.TABLE_SORT_ASCEND), ), 0, 0), mapi.TBL_BATCH)
- self.table = table
- def __fetch(self):
- if self.done:
- return
- rows = self.table.QueryRows(70, 0)
- if len(rows) == 0:
- self.done = True
- return
- for row in rows:
- (tag, eid), (tag, rk) = row
- self.ique.append((rk, eid))
- def GetAllEids(self):
- while True:
- if len(self.ique) == 0 and self.done:
- break
- if len(self.ique) == 0:
- self.__fetch()
- continue
- yield self.ique.popleft()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement