def get_olprops_from_mapi(self, entryid=None): """This reads the current contact's entire property list from MAPI and returns an array of property tuples""" oli = self.get_olitem() # prop_list = oli.GetPropList(mapi.MAPI_UNICODE) # hr, props = oli.GetProps(prop_list, 0) # hr, props = oli.GetProps(self.get_folder().get_def_cols(), 0) # The idea here is to get the full property list, and then filter down # to the ones we are really interested in. It was getting a bit # confusing, as the available property list was getting filtered # somewhere upstream, and we were not even seeing basic stuff like # PR_BODY and PR_GIVEN_NAME. The following approach works for now, # i.e. just set the properties we are keen on. hr, props = oli.GetProps(self.get_sync_fields(), 0) # hr, props = oli.GetProps(None, 0) if (winerror.FAILED(hr)): logging.error( 'get_olprops_from_mapi: Unable to GetProps. Code: %x', winerror.HRESULT_CODE(hr)) logging.error('Formatted error: %s', win32api.FormatMessage(hr)) return props
def create_contact(self, name, email=None, org=None): """Save the current contact to Outlook, and returns the entryid of the entry.""" logging.info('Saving to Outlook: %-32s ....', name) msg = self.def_cf.CreateMessage(None, 0) if not msg: return None self.props_list = [(mapitags.PR_MESSAGE_CLASS, "IPM.Contact")] self.props_list.append((mapitags.PR_DISPLAY_NAME, name)) fileas_prop_tag = self.get_file_as_prop_tag() self.props_list.append((fileas_prop_tag, name)) self.props_list.append((mapitags.PR_COMPANY_NAME, org)) self.props_list.append((mapitags.PR_BODY, email)) hr, res = msg.SetProps(self.props_list) if (winerror.FAILED(hr)): logging.critical( 'push_to_outlook(): unable to SetProps (code: %x)', winerror.HRESULT_CODE(hr)) return None msg.SaveChanges(mapi.KEEP_OPEN_READWRITE)
def get_ipm_subtree_eid (self): msgstore = self.get_obj() hr, ps = msgstore.GetProps((mapitags.PR_IPM_SUBTREE_ENTRYID)) if winerror.FAILED(hr): logging.error('Could not get subtree entryid for store: %s. ' 'Error: 0x%x', self.get_name(), winerror.HRESULT_CODE(hr)) return None tag, eid = ps[0] return eid
def _clear_tag(self, tags, dryrun=False): """Clear any property whose property tag is the provided array.""" logging.info('Querying MAPI for all data needed to clear flag') ctable = self.get_contents() cols = tuple([mt.PR_ENTRYID, mt.PR_DISPLAY_NAME]) + tuple(tags) ctable.SetColumns(cols, 0) logging.info('Data obtained from MAPI. Clearing one at a time') cnt = set() errs = set() i = 0 store = self.get_msgstore().get_obj() hr = ctable.SeekRow(mapi.BOOKMARK_BEGINNING, 0) while True: rows = ctable.QueryRows(1, 0) # if this is the last row then stop if len(rows) != 1: break (entryid_tag, entryid), (name_tag, name) = rows[0][:2] i += 1 for j in range(2, len(rows[0])): (gid_tag, gid) = rows[0][j] if mt.PROP_TYPE(gid_tag) != mt.PT_ERROR: if not dryrun: entry = store.OpenEntry(entryid, None, mapi.MAPI_BEST_ACCESS) hr, ps = entry.DeleteProps([gid_tag]) if winerror.FAILED(hr): logging.debug( 'Could not delete sync tag for: %s ' '(%s), due to: %s', name, base64.b64encode(entryid), winerror.HRESULT_CODE(hr)) errs.add(entryid) else: entry.SaveChanges(0) cnt.add(entryid) logging.info('Entries cleared: %d. Errors: %d; i: %d', len(cnt), len(errs), i) ctable.SetColumns(self.get_def_cols(), 0) return (len(errs) == 0)
def enumerate_ipm_folders (self): """Walk through all the folders in the IPM subtree of the message store and print one line per folder with some critical information. For more information on what a IPM Subtree is, look here: http://msdn.microsoft.com/en-us/library/cc815825.aspx """ msgstore = self.get_obj() hr, ps = msgstore.GetProps((mapitags.PR_IPM_SUBTREE_ENTRYID)) if winerror.FAILED(hr): logging.error('Could not get subtree entryid for store: %s. ' 'Error: 0x%x', self.get_name(), winerror.HRESULT_CODE(hr)) return tag, ipm_eid = ps[0] folder = msgstore.OpenEntry(ipm_eid, None, MOD_FLAG) self.enumerate_all_folders(ipm_eid)
def del_itemids(self, itemids): """Delete the specified contacts from this folder if they exist. The return value is a pair of (success, [failed entrie]). success is true if and only all items were deleted successfully.""" fobj = self.get_fobj() retv = True retf = [] for iid in itemids: logging.info('Deleting ID: %s...', iid) eid = base64.b64decode(iid) hr = fobj.DeleteMessages([eid], 0, None, 0) if winerror.FAILED(hr): retv = False retf.append(base64.b64encode(eid)) return retv, retf
def save(self): """Saves the current (new) contact to Outlook so it is persistent. Returns the itemid for the saved entry. Returns None in case of an error""" ## FIXME: This only takes care of new insertions. In-place updates are ## not taken care of by this. As of this time (May 2012) this method ## is only invoked for new contact creations. Updates are handld ## differently - see folder_ol:batch_update(), so this is not a bug, ## just that it would be good to have a single method deal with both ## cases. fobj = self.get_folder().get_fobj() msg = fobj.CreateMessage(None, 0) if not msg: return None olprops = self.get_olprops() hr, res = msg.SetProps(olprops) if (winerror.FAILED(hr)): logging.critical( 'push_to_outlook(): unable to SetProps (code: %x)', winerror.HRESULT_CODE(hr)) return None msg.SaveChanges(mapi.KEEP_OPEN_READWRITE) # Now that we have successfully saved the record, let's fetch the # entryid and return it to the caller. hr, props = msg.GetProps([mt.PR_ENTRYID], mapi.MAPI_UNICODE) (tag, val) = props[0] if mt.PROP_TYPE(tag) == mt.PT_ERROR: logging.error('save: EntryID could not be found. Weird') return None else: logging.debug('Successfully Wrote contact to Outlook : %-32s', self.get_name()) return self.set_entryid(val)
store.get_name(), str(e)) return None cclass = OLFolder.get_cclass_from_ftype(ftype) try: nf = folder.CreateFolder(mapi.FOLDER_GENERIC, fname, 'Comment', None, 0) folder.SaveChanges(0) except Exception, e: logging.error('Failed to create new folder %s. CreateFolder ' 'returned error code: %s', fname, str(e)) return None hr, ps = nf.SetProps([(mapitags.PR_CONTAINER_CLASS, cclass)]) if winerror.FAILED(hr): logging.error('Failed to Set Container class for newly created ' 'folder %s. Hm. tough luck... Delete the sucker ' 'manually from Outlook. Sorry for the bother. ' 'Error Code retruned by SetProps: 0x%x',fname, winerror.HRESULT_CODE(hr)) return None hr, ps = nf.GetProps((mapitags.PR_ENTRYID)) if winerror.FAILED(hr): logging.error('Failed to get Entry_ID for newly created ' 'folder %s. Hm. tough luck... Delete the sucker ' 'manually from Outlook. Sorry for the bother. ' 'Error Code retruned by SetProps: 0x%x',fname, winerror.HRESULT_CODE(hr)) return None