def restriction(self, type_, store): if self.field: # determine proptag for term, eg 'subject' proptag = TYPE_KEYWORD_PROPMAP[type_][self.field] flag = None subobj = None recipient_type = None # property in sub-object (attachments/recipient): use sub-restriction if isinstance(proptag, tuple): if(proptag[0]) == PR_MESSAGE_ATTACHMENTS: subobj, proptag = proptag elif(proptag[0]) == PR_MESSAGE_RECIPIENTS: subobj, proptag, recipient_type = proptag elif len(proptag) == 2: proptag, flag = proptag # named property: resolve local proptag elif len(proptag) == 4: proptag = store._name_id(proptag[:3]) | proptag[3] # make restriction on proptag(s) if isinstance(proptag, list): restr = SOrRestriction([ self.prop_restriction(proptag, flag) for proptag in proptag ]) else: restr = self.prop_restriction(proptag, flag) # turn restriction into sub-restriction if subobj: if recipient_type is not None: restr = SAndRestriction([ restr, SPropertyRestriction( RELOP_EQ, PR_RECIPIENT_TYPE, SPropValue(PR_RECIPIENT_TYPE, recipient_type) ) ]) restr = SSubRestriction(subobj, restr) else: defaults = [(store._name_id(proptag[:3]) | proptag[3]) if isinstance(proptag, tuple) else proptag for proptag in DEFAULT_PROPTAGS[type_]] restr = SOrRestriction([ SContentRestriction( FL_SUBSTRING | FL_IGNORECASE, p, SPropValue(p, self.value) ) for p in defaults ]) if self.sign == '-': restr = SNotRestriction(restr) return restr
def test_optimize_doubleor(root): restriction = SOrRestriction([ SOrRestriction([ SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT, SPropValue(PR_SUBJECT, b'unknown')), SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT, SPropValue(PR_SUBJECT, b'unknown')) ]) ]) assert_no_results(root, restriction)
def search_start(self, folders, text, recurse=False): # specific restriction format, needed to reach indexer restriction = SOrRestriction([ SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT_W, SPropValue(PR_SUBJECT_W, str(text))), SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_BODY_W, SPropValue(PR_BODY_W, str(text))), SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_DISPLAY_TO_W, SPropValue(PR_DISPLAY_TO_W, str(text))), SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_DISPLAY_NAME_W, SPropValue(PR_DISPLAY_NAME_W, str(text))), # TODO add all default fields.. # BUT perform full-text search by default! ]) if isinstance(folders, Folder): folders = [folders] search_flags = 0 if recurse: search_flags = SEARCH_RECURSIVE self.mapiobj.SetSearchCriteria(restriction, [_bdec(f.entryid) for f in folders], search_flags)
def test_optimize_orandfalse(root): restriction = SOrRestriction([ SAndRestriction([ SNotRestriction(SExistRestriction(PR_SUBJECT)), SExistRestriction(PR_SUBJECT) ]) ]) assert_no_results(root, restriction)
def _save_rule(store, userids, deletion): # remove existing rule # XXX update for rule in store.inbox.rules(): if rule.mapirow[PR_RULE_PROVIDER_W] == u'Schedule+ EMS Interface' and \ PR_RULE_ID in rule.mapirow: pr_rule_id = rule.mapirow[PR_RULE_ID] rulerows = [ ROWENTRY(ROW_REMOVE, [SPropValue(PR_RULE_ID, pr_rule_id)]) ] table = store.inbox.mapiobj.OpenProperty( PR_RULES_TABLE, IID_IExchangeModifyTable, 0, 0) table.ModifyTable(0, rulerows) # create new rule row = [ SPropValue(PR_RULE_LEVEL, 0), SPropValue(PR_RULE_NAME_W, u"Delegate Meetingrequest service"), SPropValue(PR_RULE_PROVIDER_W, u"Schedule+ EMS Interface"), SPropValue(PR_RULE_SEQUENCE, 0), SPropValue(PR_RULE_STATE, 1), SPropValue(PR_RULE_PROVIDER_DATA, b''), ] actions = [] userprops = [] for userid in userids: user = store.server.gab.OpenEntry(userid, None, MAPI_BEST_ACCESS) props = user.GetProps(USERPROPS, MAPI_UNICODE) # Hardcode recipient type to TO props.append(SPropValue(PR_RECIPIENT_TYPE, MAPI_TO)) userprops.append(props) actions.append( ACTION(ACTTYPE.OP_DELEGATE, 0, None, None, 0, actFwdDelegate(userprops))) if deletion: actions.append(ACTION(ACTTYPE.OP_DELETE, 0, None, None, 0, None)) row.append(SPropValue(PR_RULE_ACTIONS, ACTIONS(1, actions))) cond = SAndRestriction([ SContentRestriction( FL_PREFIX, PR_MESSAGE_CLASS_W, SPropValue(PR_MESSAGE_CLASS_W, u"IPM.Schedule.Meeting")), SNotRestriction(SExistRestriction(PR_DELEGATED_BY_RULE)), SOrRestriction([ SNotRestriction(SExistRestriction(PR_SENSITIVITY)), SPropertyRestriction(RELOP_NE, PR_SENSITIVITY, SPropValue(PR_SENSITIVITY, 2)) ]) ]) row.append(SPropValue(PR_RULE_CONDITION, cond)) rulerows = [ROWENTRY(ROW_ADD, row)] table = store.inbox.mapiobj.OpenProperty(PR_RULES_TABLE, IID_IExchangeModifyTable, 0, 0) table.ModifyTable(0, rulerows)
def restriction(self, type_, store): if self.op == 'AND': return SAndRestriction( [arg.restriction(type_, store) for arg in self.args]) elif self.op == 'OR': return SOrRestriction( [arg.restriction(type_, store) for arg in self.args]) elif self.op == 'NOT': return SNotRestriction(self.args[0].restriction(type_, store))
def test_optimize_ormultianndfalse(root): restriction = SOrRestriction([ SAndRestriction([ SNotRestriction(SExistRestriction(PR_SUBJECT)), SExistRestriction(PR_SUBJECT) ]), SAndRestriction([ SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT, SPropValue(PR_SUBJECT, b'unknown')), SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_SUBJECT, SPropValue(PR_SUBJECT, b'unknown')) ]) ]) assert_no_results(root, restriction)
def attendees(self): """Appointment :class:`attendees <Attendee>`.""" # Filter out organizer from all recipients restriction = Restriction( SOrRestriction([ SNotRestriction(SExistRestriction(PR_RECIPIENT_FLAGS)), SBitMaskRestriction(BMR_EQZ, PR_RECIPIENT_FLAGS, recipOrganizer) ])) for row in self.table(PR_MESSAGE_RECIPIENTS, restriction=restriction): yield Attendee(self.server, row)
def occurrences(self, start=None, end=None): if start and end: startstamp = time.mktime(start.timetuple()) endstamp = time.mktime(end.timetuple()) # XXX use shortcuts and default type (database) to avoid MAPI snake wrestling NAMED_PROPS = [ MAPINAMEID(PSETID_Appointment, MNID_ID, x) for x in (33293, 33294, 33315) ] ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS, 0) startdate = ids[0] | PT_SYSTIME enddate = ids[1] | PT_SYSTIME recurring = ids[2] | PT_BOOLEAN # only look at non-recurring items which overlap and all recurring items restriction = SOrRestriction([ SAndRestriction([ SPropertyRestriction( RELOP_GT, enddate, SPropValue(enddate, unixtime(startstamp))), SPropertyRestriction( RELOP_LT, startdate, SPropValue(startdate, unixtime(endstamp))), ]), SAndRestriction([ SPropertyRestriction(RELOP_EQ, recurring, SPropValue(recurring, True)) ]) ]) table = Table( self.server, self.mapiobj, self.mapiobj.GetContentsTable(MAPI_DEFERRED_ERRORS), PR_CONTAINER_CONTENTS, columns=[PR_ENTRYID], ) table.mapitable.Restrict(restriction, 0) for row in table.rows(): entryid = _benc(row[0].value) for occurrence in self.item(entryid).occurrences(start, end): yield occurrence else: for item in self: for occurrence in item.occurrences(start, end): yield occurrence
def GetGab(session): ab = session.OpenAddressBook(0, None, 0) root = ab.OpenEntry(None, None, 0) table = root.GetHierarchyTable(0) table.SetColumns([PR_ENTRYID], TBL_BATCH) restriction = SOrRestriction([ SPropertyRestriction(RELOP_EQ, PR_DISPLAY_TYPE, SPropValue(PR_DISPLAY_TYPE, DT_GLOBAL)), SAndRestriction([ SExistRestriction(PR_EMS_AB_CONTAINERID), SPropertyRestriction(RELOP_EQ, PR_EMS_AB_CONTAINERID, SPropValue(PR_EMS_AB_CONTAINERID, 0)) ]) ]) table.FindRow(restriction, BOOKMARK_BEGINNING, 0) eid = table.QueryRows(1, 0)[0][0].Value return ab.OpenEntry(eid, None, 0)
def restriction(self, type_, store): if self.field: # determine proptag for term, eg 'subject' proptag = TYPE_KEYWORD_PROPMAP[type_][self.field] flag = None subobj = None recipient_type = None # property in sub-object (attachments/recipient): use sub-restriction if isinstance(proptag, tuple) and len(proptag) == 2: if(proptag[0]) == PR_MESSAGE_ATTACHMENTS: subobj, proptag = proptag elif(proptag[0]) == PR_MESSAGE_RECIPIENTS: subobj, recipient_type = proptag proptag = PR_DISPLAY_NAME_W # TODO email else: proptag, flag = proptag # named property: resolve local proptag elif isinstance(proptag, tuple) and len(proptag) == 4: proptag = store._name_id(proptag[:3]) | proptag[3] # comparison operator if self.op in ('<', '>', '>=', '<=', '<>'): if PROP_TYPE(proptag) == PT_SYSTIME: d = dateutil.parser.parse(self.value, dayfirst=True) d = datetime_to_filetime(d) restr = SPropertyRestriction( OP_RELOP[self.op], proptag, SPropValue(proptag, d) ) else: value = self.value unit = '' if [x for x in ('KB', 'MB', 'GB') if value.endswith(x)]: value, unit = value[:-2], value[-2:] if PROP_TYPE(proptag) in (PT_FLOAT, PT_DOUBLE): value = float(value) else: value = int(value) if unit == 'KB': value *= 1024 elif unit == 'MB': value *= 1024**2 elif unit == 'GB': value *= 1024**3 restr = SPropertyRestriction( OP_RELOP[self.op], proptag, SPropValue(proptag, value) ) # contains/equals operator elif self.op in (':', '='): if PROP_TYPE(proptag) == PT_UNICODE: restr = SContentRestriction( FL_SUBSTRING | FL_IGNORECASE, proptag, SPropValue(proptag, self.value) ) elif flag or PROP_TYPE(proptag) == PT_BOOLEAN: if flag: restr = SBitMaskRestriction( BMR_NEZ if self.value in ('yes', 'true') else BMR_EQZ, proptag, flag ) else: restr = SPropertyRestriction( RELOP_EQ, proptag, SPropValue(proptag, self.value in ('yes', 'true')) ) elif PROP_TYPE(proptag) == PT_MV_UNICODE: proptag2 = (proptag ^ PT_MV_UNICODE) | PT_UNICODE # funky! restr = SContentRestriction( FL_SUBSTRING | FL_IGNORECASE, proptag, SPropValue(proptag2, self.value) ) elif PROP_TYPE(proptag) in (PT_SHORT, PT_LONG, PT_LONGLONG, PT_FLOAT, PT_DOUBLE): conv = float if PROP_TYPE(proptag) in (PT_FLOAT, PT_DOUBLE) else int if '..' in self.value: val1, val2 = self.value.split('..') restr = SAndRestriction([ SPropertyRestriction( RELOP_GE, proptag, SPropValue(proptag, conv(val1)) ), SPropertyRestriction( RELOP_LT, proptag, SPropValue(proptag, conv(val2)) ) ]) else: restr = SPropertyRestriction( RELOP_EQ, proptag, SPropValue(proptag, conv(self.value)) ) elif PROP_TYPE(proptag) == PT_SYSTIME: if self.value == 'today': d = datetime.datetime.now().date() d2 = d + datetime.timedelta(days=1) restr = _interval_restriction(proptag, d, d2) elif self.value == 'yesterday': d2 = datetime.datetime.now().date() d = d2 - datetime.timedelta(days=1) restr = _interval_restriction(proptag, d, d2) elif self.value == 'this week': d2 = datetime.datetime.now() d = d2.date() - datetime.timedelta(days=d2.weekday()) restr = _interval_restriction(proptag, d, d2) elif self.value == 'this month': d2 = datetime.datetime.now() d = d2.date() - datetime.timedelta(days=d2.day-1) restr = _interval_restriction(proptag, d, d2) elif self.value == 'last month': now = datetime.datetime.now() d2 = now.date() - datetime.timedelta(days=now.day-1) d = (d2 - datetime.timedelta(days=1)).replace(day=1) restr = _interval_restriction(proptag, d, d2) elif self.value == 'this year': d2 = datetime.datetime.now() d = datetime.datetime(d2.year, 1, 1) restr = _interval_restriction(proptag, d, d2) elif self.value == 'last year': now = datetime.datetime.now() d2 = datetime.datetime(now.year, 1, 1) d = datetime.datetime(d2.year-1, 1, 1) restr = _interval_restriction(proptag, d, d2) elif '..' in self.value: date1, date2 = self.value.split('..') # TODO hours etc d = dateutil.parser.parse(date1, dayfirst=True) d2 = dateutil.parser.parse(date2, dayfirst=True) restr = _interval_restriction(proptag, d, d2) else: d = dateutil.parser.parse(self.value, dayfirst=True) # TODO hours etc d2 = d + datetime.timedelta(days=1) restr = _interval_restriction(proptag, d, d2) # turn restriction into sub-restriction if subobj: if recipient_type is not None: restr = SAndRestriction([ restr, SPropertyRestriction( RELOP_EQ, PR_RECIPIENT_TYPE, SPropValue(PR_RECIPIENT_TYPE, recipient_type) ) ]) restr = SSubRestriction(subobj, restr) else: defaults = [(store._name_id(proptag[:3]) | proptag[3]) if isinstance(proptag, tuple) else proptag for proptag in DEFAULT_PROPTAGS[type_]] restr = SOrRestriction([ SContentRestriction( FL_SUBSTRING | FL_IGNORECASE, p, SPropValue(p, self.value) ) for p in defaults ]) if self.sign == '-': restr = SNotRestriction(restr) return restr
def occurrences(self, start=None, end=None, page_start=None, page_limit=None, order=None): count = 0 pos = 0 if start and end: startstamp = time.mktime(start.timetuple()) endstamp = time.mktime(end.timetuple()) # XXX use shortcuts and default type (database) to avoid MAPI snake wrestling NAMED_PROPS = [ MAPINAMEID(PSETID_Appointment, MNID_ID, x) for x in (33285, 33293, 33294, 33315, 33301, 33333, 33334) ] ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS, MAPI_CREATE) busystatus = ids[0] | PT_LONG startdate = ids[1] | PT_SYSTIME enddate = ids[2] | PT_SYSTIME recurring = ids[3] | PT_BOOLEAN all_day = ids[4] | PT_BOOLEAN clip_start = ids[5] | PT_SYSTIME clip_end = ids[6] | PT_SYSTIME restriction = SOrRestriction([ # non-recurring: normal start/end SAndRestriction([ SPropertyRestriction( RELOP_GT, enddate, SPropValue(enddate, unixtime(startstamp))), SPropertyRestriction( RELOP_LT, startdate, SPropValue(startdate, unixtime(endstamp))), ]), # recurring: range start/end SAndRestriction([ SPropertyRestriction( RELOP_GT, clip_end, SPropValue(clip_end, unixtime(startstamp))), SPropertyRestriction( RELOP_LT, clip_start, SPropValue(clip_start, unixtime(endstamp))), ]), # exceptions: exception start/end in attachment SAndRestriction([ SPropertyRestriction(RELOP_EQ, recurring, SPropValue(recurring, True)), SSubRestriction( PR_MESSAGE_ATTACHMENTS, SAndRestriction([ SPropertyRestriction( RELOP_LT, PR_EXCEPTION_STARTTIME, SPropValue(PR_EXCEPTION_STARTTIME, unixtime(endstamp))), SPropertyRestriction( RELOP_GT, PR_EXCEPTION_ENDTIME, SPropValue(PR_EXCEPTION_ENDTIME, unixtime(startstamp))), ])) ]) ]) columns = [ PR_ENTRYID, PR_SUBJECT_W, # watch out: table unicode data is max 255 chars PR_LAST_MODIFICATION_TIME, PR_CHANGE_KEY, startdate, enddate, recurring, all_day, busystatus ] table = Table( self.server, self.mapiobj, self.mapiobj.GetContentsTable(MAPI_DEFERRED_ERRORS), PR_CONTAINER_CONTENTS, columns=columns, ) table.mapitable.Restrict(restriction, 0) for row in table.rows(): item = _item.Item(self, entryid=row[0].value, content_flag=self.content_flag, cache=dict(zip(columns, row))) for occurrence in item.occurrences(start, end): if page_start is None or pos >= page_start: yield occurrence count += 1 if page_limit is not None and count >= page_limit: break pos += 1 if page_limit is not None and count >= page_limit: break else: for item in self: for occurrence in item.occurrences(start, end): if page_start is None or pos >= page_start: yield occurrence count += 1 if page_limit is not None and count >= page_limit: break pos += 1 if page_limit is not None and count >= page_limit: break