def _load(self, d, attachments): # props props = [] for proptag, value, nameid in d[b'props']: if nameid is not None: proptag = self.mapiobj.GetIDsFromNames([nameid], MAPI_CREATE)[0] | (proptag & 0xffff) if (proptag >> 16) not in (PR_BODY >> 16, PR_HTML >> 16, PR_RTF_COMPRESSED >> 16) or \ value not in (MAPI_E_NOT_FOUND, MAPI_E_NOT_ENOUGH_MEMORY): # XXX why do we backup these errors props.append(SPropValue(proptag, value)) self.mapiobj.SetProps(props) # recipients recipients = [[SPropValue(proptag_, value) for (proptag_, value, nameid) in row] for row in d[b'recipients']] self.mapiobj.ModifyRecipients(0, recipients) # attachments for props, data in d[b'attachments']: if attachments or isinstance(data, dict): props = [SPropValue(proptag_, value) for (proptag_, value, nameid) in props] (id_, attach) = self.mapiobj.CreateAttach(None, 0) attach.SetProps(props) if isinstance(data, dict): # embedded message msg = attach.OpenProperty(PR_ATTACH_DATA_OBJ, IID_IMessage, 0, MAPI_CREATE | MAPI_MODIFY) item = Item(mapiobj=msg) item._load(data, attachments) # recursion else: stream = attach.OpenProperty(PR_ATTACH_DATA_BIN, IID_IStream, STGM_WRITE | STGM_TRANSACTED, MAPI_MODIFY | MAPI_CREATE) stream.Write(data) stream.Commit(0) _utils._save(attach) _utils._save(self.mapiobj) # XXX needed?
def create_attachment(self, name=None, data=None, filename=None, **kwargs): """Create a new attachment :param name: the attachment name :param data: string containing the attachment data :param filename: string """ if filename: data = open(filename, 'rb').read() name = os.path.basename(filename) (id_, attach) = self.mapiobj.CreateAttach(None, 0) name = _unicode(name) props = [SPropValue(PR_ATTACH_LONG_FILENAME_W, name), SPropValue(PR_ATTACH_METHOD, ATTACH_BY_VALUE)] attach.SetProps(props) stream = attach.OpenProperty(PR_ATTACH_DATA_BIN, IID_IStream, STGM_WRITE | STGM_TRANSACTED, MAPI_MODIFY | MAPI_CREATE) stream.Write(data) stream.Commit(0) _utils._save(attach) _utils._save(self.mapiobj) # XXX needed? att = Attachment(self, mapiitem=self.mapiobj, mapiobj=attach) for key, val in kwargs.items(): setattr(att, key, val) return att
def _init_calitem(self, cal_item, tentative, merge=False): # XXX what about updating existing cal_item.message_class = 'IPM.Appointment' # busystatus intended_busystatus = self.item.get(PidLidIntendedBusyStatus) if intended_busystatus is not None: if tentative and intended_busystatus != libfreebusy.fbFree: # XXX busystatus = libfreebusy.fbTentative else: busystatus = intended_busystatus cal_item[PidLidBusyStatus] = busystatus # add organizer as recipient organizer_props = _organizer_props(cal_item, self.item) if organizer_props and not merge: table = cal_item.mapiobj.OpenProperty(PR_MESSAGE_RECIPIENTS, IID_IMAPITable, MAPI_UNICODE, 0) table.SetColumns(RECIP_PROPS, 0) rows = table.QueryRows(-1, 0) if tentative: # XXX php-compat: php checks 'move' flag, should we cal_item.mapiobj.ModifyRecipients(MODRECIP_REMOVE, rows) cal_item.mapiobj.ModifyRecipients(MODRECIP_ADD, [organizer_props] + rows) else: cal_item.mapiobj.ModifyRecipients(MODRECIP_ADD, [organizer_props]) _utils._save(cal_item.mapiobj)
def message(self, value): if value is None: self.store.mapiobj.DeleteProps([PR_EC_OUTOFOFFICE_MSG_W]) else: self.store.mapiobj.SetProps( [SPropValue(PR_EC_OUTOFOFFICE_MSG_W, _unicode(value))]) _utils._save(self.store.mapiobj)
def subject(self, value): if value is None: self.store.mapiobj.DeleteProps([PR_EC_OUTOFOFFICE_SUBJECT_W]) else: self.store.mapiobj.SetProps( [SPropValue(PR_EC_OUTOFOFFICE_SUBJECT_W, _unicode(value))]) _utils._save(self.store.mapiobj)
def start(self, value): if value is None: self.store.mapiobj.DeleteProps([PR_EC_OUTOFOFFICE_FROM]) else: value = unixtime(time.mktime(value.timetuple())) self.store.mapiobj.SetProps([SPropValue(PR_EC_OUTOFOFFICE_FROM, value)]) _utils._save(self.store.mapiobj)
def set_photo(self, name, data, mimetype): for attachment in self.attachments(): if attachment.get(PR_ATTACHMENT_CONTACTPHOTO): self.delete(attachment) attachment = self.create_attachment(name, data) attachment[PR_ATTACHMENT_CONTACTPHOTO] = True attachment.mimetype = mimetype _utils._save(self.mapiobj) return attachment
def sender(self, addr): pr_addrtype, pr_dispname, pr_email, pr_entryid = self._addr_props(addr) self.mapiobj.SetProps([ SPropValue(PR_SENDER_ADDRTYPE_W, _unicode(pr_addrtype)), # XXX pr_addrtype should be unicode already SPropValue(PR_SENDER_NAME_W, pr_dispname), SPropValue(PR_SENDER_EMAIL_ADDRESS_W, pr_email), SPropValue(PR_SENDER_ENTRYID, pr_entryid), ]) _utils._save(self.mapiobj)
def archive_store(self, store): ids = self.mapiobj.GetIDsFromNames( NAMED_PROPS_ARCHIVER, MAPI_CREATE) # XXX merge namedprops stuff PROP_STORE_ENTRYIDS = CHANGE_PROP_TYPE(ids[0], PT_MV_BINARY) PROP_ITEM_ENTRYIDS = CHANGE_PROP_TYPE(ids[1], PT_MV_BINARY) # XXX only for detaching atm if store is None: self.mapiobj.DeleteProps([PROP_STORE_ENTRYIDS, PROP_ITEM_ENTRYIDS]) _utils._save(self.mapiobj)
def delete(self, objects): objects = _utils.arg_objects(objects, (_prop.Property, ), 'Attachment.delete') proptags = [ item.proptag for item in objects if isinstance(item, _prop.Property) ] if proptags: self.mapiobj.DeleteProps(proptags) _utils._save(self.parent.mapiobj)
def read_ics(self, ics): """Import a complete ics calendar into the current folder :param ics: the ics file to import """ icm = icalmapi.CreateICalToMapi(self.mapiobj, self.server.ab, False) icm.ParseICal(ics, 'utf-8', '', None, 0) for i in range(0, icm.GetItemCount()): mapiobj = self.mapiobj.CreateMessage(None, 0) icm.GetItem(i, 0, mapiobj) _utils._save(mapiobj)
def importance(self, value): """ Set importance PR_IMPORTANCE_LOW PR_IMPORTANCE_MEDIUM PR_IMPORTANCE_HIGH """ warnings.warn('item.importance is deprecated (use item.urgency)', _DeprecationWarning) self.mapiobj.SetProps([SPropValue(PR_IMPORTANCE, value)]) _utils._save(self.mapiobj)
def see_private(self, b): fbmsg, (entryids, names, flags) = self.store._fbmsg_delgs() pos = entryids.Value.index(_bdec(self.user.userid)) if b: flags.Value[pos] |= 1 else: flags.Value[pos] &= ~1 fbmsg.SetProps([flags]) _utils._save(fbmsg)
def process_cancellation(self, delete=False): """ Process meeting request cancellation :param delete: delete appointment from calendar """ if not self.is_cancellation: raise Error('item is not a meeting request cancellation') cal_item = self.calendar_item if not cal_item: self.log.debug('no appointment matches cancellation') return basedate = self.basedate if basedate: if cal_item.recurring: recurrence = cal_item.recurrence copytags = _copytags(cal_item.mapiobj) if delete: recurrence._delete_exception(basedate, self.item, copytags) else: if recurrence._is_exception(basedate): recurrence._modify_exception(basedate, self.item, copytags) else: recurrence._create_exception(basedate, self.item, copytags) message = recurrence._exception_message(basedate) message[PidLidBusyStatus] = libfreebusy.fbFree message[PR_MESSAGE_FLAGS] = MSGFLAG_UNSENT | MSGFLAG_READ _utils._save(message._attobj) else: if delete: self.calendar.delete(cal_item) else: cal_item.cancel() else: if delete: self.calendar.delete(cal_item) else: self.item.mapiobj.CopyTo([], [], 0, None, IID_IMessage, cal_item.mapiobj, 0) cal_item.mapiobj.SetProps( [SPropValue(PR_MESSAGE_CLASS_W, u'IPM.Appointment')]) if cal_item and not delete: _utils._save(cal_item.mapiobj)
def create_attendee(self, type_, addr): if self.item.recurring: rec = self.item.recurrence basedate = datetime.datetime.utcfromtimestamp(_utils.rectime_to_unixtime(self._basedate_val)) basedate = basedate.replace(hour=0, minute=0) message = rec._exception_message(basedate) if message: message.create_attendee(type_, addr) _utils._save(message._attobj) return # TODO else? else: self.item.create_attendee(type_, addr)
def message_class(self, messageclass): # FIXME: Add all possible PR_MESSAGE_CLASS values """ MAPI Message classes: * IPM.Note.SMIME.MultipartSigned - smime signed email * IMP.Note - normal email * IPM.Note.SMIME - smime encypted email * IPM.StickyNote - note * IPM.Appointment - appointment * IPM.Task - task """ self.mapiobj.SetProps([SPropValue(PR_MESSAGE_CLASS_W, _unicode(messageclass))]) _utils._save(self.mapiobj)
def from_(self, addr): pr_addrtype, pr_dispname, pr_email, pr_entryid = self._addr_props(addr) self.mapiobj.SetProps([ SPropValue(PR_SENT_REPRESENTING_ADDRTYPE_W, _unicode(pr_addrtype)), # XXX pr_addrtype should be unicode already SPropValue(PR_SENT_REPRESENTING_NAME_W, pr_dispname), SPropValue(PR_SENT_REPRESENTING_EMAIL_ADDRESS_W, pr_email), SPropValue(PR_SENT_REPRESENTING_ENTRYID, pr_entryid), ]) # XXX Hack around missing sender if not self.sender.email: self.sender = addr _utils._save(self.mapiobj)
def copy(self, folder, _delete=False): """ Copy item to folder; return copied item :param folder: target folder """ mapiobj = folder.mapiobj.CreateMessage(None, 0) self.mapiobj.CopyTo([], [], 0, None, IID_IMessage, mapiobj, 0) _utils._save(mapiobj) if _delete: self.folder.delete(self) item = Item(mapiobj=mapiobj) item.store = self.store # XXX item.server = self.server return item
def _delete(self): # XXX update delegate rule fbmsg, (entryids, names, flags) = self.store._fbmsg_delgs() try: pos = entryids.Value.index(_bdec(self.user.userid)) except ValueError: raise NotFoundError("no delegation for user '%s'" % self.user.name) del entryids.Value[pos] del names.Value[pos] del flags.Value[pos] fbmsg.SetProps([entryids, names, flags]) _utils._save(fbmsg)
def create_attendee(self, type_, address): # TODO move to Attendee class reciptype = {'required': 1, 'optional': 2, 'resource': 3}[type_] table = self.table(PR_MESSAGE_RECIPIENTS) names = [] pr_addrtype, pr_dispname, pr_email, pr_entryid = self._addr_props( address) names.append([ SPropValue(PR_RECIPIENT_TYPE, reciptype), SPropValue(PR_DISPLAY_NAME_W, pr_dispname), SPropValue(PR_ADDRTYPE_W, _unicode(pr_addrtype)), SPropValue(PR_EMAIL_ADDRESS_W, _unicode(pr_email)), SPropValue(PR_ENTRYID, pr_entryid), ]) self.mapiobj.ModifyRecipients(MODRECIP_ADD, names) _utils._save(self.mapiobj)
def create_prop(self, mapiobj, proptag, value=None, proptype=None): # XXX selfie if _is_int(proptag) or \ (_is_str(proptag) and ':' not in proptag): if _is_str(proptag): proptag2 = getattr(MAPI.Tags, proptag) else: proptag2 = proptag proptype2 = proptype or PROP_TYPE(proptag) else: # named property proptag2, proptype2, _, _ = _name_to_proptag(proptag, mapiobj, proptype) if proptype2 is None: raise Error('Missing type to create named property' ) # XXX exception too general? if value is None: if proptype2 in (PT_STRING8, PT_UNICODE): value = u'' elif proptype2 == PT_BINARY: value = b'' elif proptype2 == PT_SYSTIME: value = unixtime(0) elif proptype2 & MV_FLAG: value = [] else: value = 0 else: if proptype2 == PT_SYSTIME: value = unixtime(time.mktime(value.timetuple())) # handle invalid type versus value. For example proptype=PT_UNICODE and value=True try: mapiobj.SetProps([SPropValue(proptag2, value)]) _utils._save(mapiobj) except TypeError: raise Error('Could not create property, type and value did not match') return prop(self, mapiobj, proptag, proptype=proptype2)
def restore(self): ids = self.mapiobj.GetIDsFromNames(NAMED_PROPS_ARCHIVER, MAPI_CREATE) # XXX cache folder.GetIDs..? PROP_STUBBED = CHANGE_PROP_TYPE(ids[2], PT_BOOLEAN) PROP_REF_STORE_ENTRYID = CHANGE_PROP_TYPE(ids[3], PT_BINARY) PROP_REF_ITEM_ENTRYID = CHANGE_PROP_TYPE(ids[4], PT_BINARY) PROP_REF_PREV_ENTRYID = CHANGE_PROP_TYPE(ids[5], PT_BINARY) PROP_FLAGS = CHANGE_PROP_TYPE(ids[6], PT_LONG) # get/create primary item primary_item = self.primary_item if not primary_item: mapiobj = self.folder.primary_folder.mapiobj.CreateMessage(None, 0) new = True else: mapiobj = primary_item.mapiobj new = False if not new and not primary_item.stubbed: return # cleanup primary item mapiobj.DeleteProps([PROP_STUBBED, PR_ICON_INDEX]) at = Table( self.server, self.mapiobj, mapiobj.GetAttachmentTable(0), columns=[PR_ATTACH_NUM], ) for row in at.rows(): mapiobj.DeleteAttach(row[0].value, 0, None, 0) # copy contents into it exclude_props = [PROP_REF_STORE_ENTRYID, PROP_REF_ITEM_ENTRYID, PROP_REF_PREV_ENTRYID, PROP_FLAGS] self.mapiobj.CopyTo(None, exclude_props, 0, None, IID_IMessage, mapiobj, 0) _utils._save(mapiobj) # update backref if new: entryid = HrGetOneProp(mapiobj, PR_ENTRYID).Value self.mapiobj.SetProps([SPropValue(PROP_REF_ITEM_ENTRYID, entryid)]) _utils._save(self.mapiobj)
def delete(self, objects): """Delete properties or attachments from item. :param objects: The object(s) to delete """ objects = _utils.arg_objects(objects, (Attachment, _prop.Property, Occurrence), 'Item.delete') # XXX embedded items? attach_ids = [item.number for item in objects if isinstance(item, Attachment)] proptags = [item.proptag for item in objects if isinstance(item, _prop.Property)] occs = [item for item in objects if isinstance(item, Occurrence)] for occ in occs: self.recurrence._delete_exception(occ.start, self, _copytags(self.mapiobj)) if proptags: self.mapiobj.DeleteProps(proptags) for attach_id in attach_ids: self._arch_item.DeleteAttach(attach_id, 0, None, 0) # XXX: refresh the mapiobj since PR_ATTACH_NUM is updated when opening # a message? PR_HASATTACH is also updated by the server. _utils._save(self.mapiobj)
def create_item(self, message_flags=None, hidden=False, **kwargs): """ Create embedded :class:`item <Item>` """ (id_, attach) = self.mapiobj.CreateAttach(None, 0) attach.SetProps([ SPropValue(PR_ATTACH_METHOD, ATTACH_EMBEDDED_MSG), SPropValue(PR_ATTACHMENT_FLAGS, 2), SPropValue(PR_ATTACHMENT_HIDDEN, hidden), SPropValue(PR_ATTACHMENT_LINKID, 0), SPropValue(PR_ATTACH_FLAGS, 0), ]) if kwargs.get('subject'): attach.SetProps([ SPropValue(PR_DISPLAY_NAME_W, _unicode(kwargs.get('subject'))), ]) msg = attach.OpenProperty(PR_ATTACH_DATA_OBJ, IID_IMessage, 0, MAPI_CREATE | MAPI_MODIFY) if message_flags is not None: msg.SetProps([SPropValue(PR_MESSAGE_FLAGS, message_flags)]) item = Item(mapiobj=msg) item.server = self.server item._attobj = attach for key, val in kwargs.items(): setattr(item, key, val) _utils._save(msg) _utils._save(attach) _utils._save(self.mapiobj) # XXX needed? return item
def delegation(self, user, create=False, see_private=False): """Return :class:`delegation <Delegation>` for user. :param user: user :param create: create new delegation for this user :param see_private: user can see private items """ for delegation in self.delegations(): if delegation.user == user: return delegation if create: fbmsg, (entryids, names, flags) = self._fbmsg_delgs() entryids.Value.append(_bdec(user.userid)) names.Value.append(user.name) flags.Value.append(1 if see_private else 0) fbmsg.SetProps([entryids, names, flags]) _utils._save(fbmsg) return Delegation(self, user) else: raise NotFoundError("no delegation for user '%s'" % user.name)
def _recipients(self, reciptype, addrs): """Sets the recipient table according to the type and given addresses. Since the recipienttable contains to, cc and bcc addresses, and item.to = [] should only set the to recipients (not append), the to recipients are first removed and then added again. This approach works but seems suboptimal, since it queries the MAPI_TO items, removes them and adds the new entries while leaving the other recipients intact. :param reciptype: MAPI_TO, MAPI_CC or MAPI_BCC :param addrs: list of addresses to set. """ restriction = Restriction(SPropertyRestriction(RELOP_EQ, PR_RECIPIENT_TYPE, SPropValue(PR_RECIPIENT_TYPE, reciptype))) table = self.table(PR_MESSAGE_RECIPIENTS, columns=[PR_ROWID], restriction=restriction) rows = [[SPropValue(PR_ROWID, row[PR_ROWID])] for row in table.dict_rows()] if rows: self.mapiobj.ModifyRecipients(MODRECIP_REMOVE, rows) if _is_str(addrs): addrs = [x.strip() for x in _unicode(addrs).split(';')] elif isinstance(addrs, _user.User): addrs = [addrs] names = [] for addr in addrs: pr_addrtype, pr_dispname, pr_email, pr_entryid = self._addr_props(addr) names.append([ SPropValue(PR_RECIPIENT_TYPE, reciptype), SPropValue(PR_DISPLAY_NAME_W, pr_dispname), SPropValue(PR_ADDRTYPE_W, _unicode(pr_addrtype)), SPropValue(PR_EMAIL_ADDRESS_W, _unicode(pr_email)), SPropValue(PR_ENTRYID, pr_entryid), ]) self.mapiobj.ModifyRecipients(MODRECIP_ADD, names) _utils._save(self.mapiobj) # XXX needed?
def delete(self, objects, soft=False): """Delete properties, delegations, permissions, folders or items from store. :param props: The object(s) to delete """ objects = _utils.arg_objects( objects, (_folder.Folder, _item.Item, Property, Delegation, Permission), 'Store.delete') # XXX directly delete inbox rule? props = [o for o in objects if isinstance(o, Property)] if props: self.mapiobj.DeleteProps([p.proptag for p in props]) _utils._save(self.mapiobj) delgs = [o for o in objects if isinstance(o, Delegation)] for d in delgs: d._delete() perms = [o for o in objects if isinstance(o, Permission)] for perm in perms: acl_table = self.mapiobj.OpenProperty(PR_ACL_TABLE, IID_IExchangeModifyTable, 0, 0) acl_table.ModifyTable(0, [ ROWENTRY( ROW_REMOVE, [SPropValue(PR_MEMBER_ID, perm.mapirow[PR_MEMBER_ID])]) ]) others = [ o for o in objects if isinstance(o, (_item.Item, _folder.Folder)) ] if others: self.root.delete(others, soft=soft)
def mimetype(self, m): self[PR_ATTACH_MIME_TAG_W] = _unicode(m) _utils._save(self.parent.mapiobj)
submission = pd.DataFrame({'test_id': test_ids, 'is_duplicate': res.ravel()}) a = 0.174264424749 / 0.369197853026 b = (1 - 0.174264424749) / (1 - 0.369197853026) submission.to_csv('lstm_concatenation_prediction.csv', index=False) submission.is_duplicate = submission.is_duplicate.apply(lambda x: a * x / (a * x + b * (1 - x))) submission.to_csv('lstm_concatenation_prediction_trans.csv', index=False) train_stacking_pred = np.zeros(data_1.shape[0]).astype(np.float32) for curr_fold, (idx_train, idx_val) in enumerate(folds): data_1_val = data_1[idx_val] data_2_val = data_2[idx_val] labels_val = labels[idx_val] model = build_model(embedding_matrix, shape, settings) model.load_weights( 'lstm_concatenation_%ddense_%.2fdropoutdense_%.2fdropoutlstm_%dfold_%dcurfold.h5' % (num_dense, rate_drop_dense, rate_drop_lstm, nfolds, curr_fold)) pred = model.predict([data_1_val, data_2_val], batch_size=2048, verbose=1).ravel() train_stacking_pred[idx_val] = pred df = pd.DataFrame() df['train_stacking_pred'] = train_stacking_pred df['is_duplicate'] = labels _save('train_lstm_concatenation_stacking_pred.pkl', train_stacking_pred)
def enabled(self, b): prop = CHANGE_PROP_TYPE(self._ids[0], PT_BOOLEAN) self._fb.SetProps([SPropValue(prop, b)]) _utils._save(self._fb)