示例#1
0
    def calendar_item(
        self
    ):  # TODO ambiguous: split in two (match exact GOID or parent recurrence?)
        """ Global calendar item :class:`item <Item>` (possibly in delegator store) """

        goid = self.item.get_prop(PidLidCleanGlobalObjectId)
        if goid is not None:
            restriction = Restriction(
                SPropertyRestriction(
                    RELOP_EQ, goid.proptag,
                    SPropValue(goid.proptag, goid.mapiobj.Value)))
            return next(self.calendar.items(restriction), None)
示例#2
0
    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)
示例#3
0
    def process_cancellation(self, delete=False):
        """Process meeting request cancellation.

        :param delete: delete appointment from calendar (default False)
        """

        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, 'IPM.Appointment')])

        if cal_item and not delete:
            _utils._save(cal_item.mapiobj)
示例#4
0
    def _set_special_folder(self, folder, proptag, container_class=None):
        _root = self.mapiobj.OpenEntry(None, None, MAPI_MODIFY)

        if isinstance(proptag, tuple):
            proptag, idx = proptag
            try:
                value = HrGetOneProp(self._root, proptag).Value
            except MAPIErrorNotFound:
                value = 5 * [b'']
            value[idx] = _bdec(folder.entryid)
            _root.SetProps([SPropValue(proptag, value)])
        else:
            _root.SetProps([SPropValue(proptag, _bdec(folder.entryid))])
        _utils._save(self._root)

        if container_class:
            folder.container_class = container_class
        else:
            prop = folder.get_prop(PR_CONTAINER_CLASS_W)
            if prop:
                folder.delete(prop)
示例#5
0
    def create_item(self, message_flags=None):
        """ 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, True),
            SPropValue(PR_ATTACHMENT_LINKID, 0),
            SPropValue(PR_ATTACH_FLAGS, 0),
        ])

        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)])

        msg.SaveChanges(KEEP_OPEN_READWRITE)
        attach.SaveChanges(KEEP_OPEN_READWRITE)
        self.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)  # XXX needed?

        item = Item(mapiobj=msg)
        item.server = self.server
        item._attobj = attach
        return item
示例#6
0
    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
示例#7
0
def permission(obj, member, create):
    for permission in obj.permissions():
        if permission.member == member:
            return permission
    if create:
        acl_table = obj.mapiobj.OpenProperty(PR_ACL_TABLE,
                                             IID_IExchangeModifyTable, 0, 0)
        if isinstance(member, _user.User):  # XXX *.id_ or something..?
            memberid = member.userid
        elif isinstance(member, _group.Group):
            memberid = member.groupid
        else:
            memberid = member.companyid
        acl_table.ModifyTable(0, [
            ROWENTRY(ROW_ADD, [
                SPropValue(PR_MEMBER_ENTRYID, _bdec(memberid)),
                SPropValue(PR_MEMBER_RIGHTS, 0)
            ])
        ])
        return obj.permission(member)
    else:
        raise NotFoundError("no permission entry for '%s'" % member.name)
示例#8
0
 def type_(self):
     """Store type (*private*, *public*, *archive*)."""
     table = self.server.sa.OpenUserStoresTable(MAPI_UNICODE)
     table.Restrict(SPropertyRestriction(RELOP_EQ, PR_EC_STOREGUID,
         SPropValue(PR_EC_STOREGUID, _bdec(self.guid))), TBL_BATCH)
     for row in table.QueryRows(1, 0):
         storetype = PpropFindProp(row, PR_EC_STORETYPE)
         if storetype:
             return {
                 ECSTORE_TYPE_PRIVATE: 'private',
                 ECSTORE_TYPE_ARCHIVE: 'archive',
                 ECSTORE_TYPE_PUBLIC: 'public',
             }[storetype.Value]
示例#9
0
 def _store(self, guid):
     if len(guid) != 32:
         raise Error("invalid store id: '%s'" % guid)
     try:
         storeid = _bdec(guid)
     except:
         raise Error("invalid store id: '%s'" % guid)
     table = self.ems.GetMailboxTable(None, 0) # XXX merge with Store.__init__
     table.SetColumns([PR_ENTRYID], 0)
     table.Restrict(SPropertyRestriction(RELOP_EQ, PR_STORE_RECORD_KEY, SPropValue(PR_STORE_RECORD_KEY, storeid)), TBL_BATCH)
     for row in table.QueryRows(-1, 0):
         return self._store2(row[0].Value)
     raise NotFoundError("no such store: '%s'" % guid)
示例#10
0
def test_deleteprops_afterreopen(store, message):
    tag = PROP_TAG(PT_STRING8, 0x6600)
    message.SetProps([SPropValue(tag, b'test')])
    message.SaveChanges(0)
    props = message.GetProps([PR_ENTRYID], 0)
    entryid = props[0].Value
    message = store.OpenEntry(entryid, None, MAPI_MODIFY)
    message.DeleteProps([tag])
    message.SaveChanges(0)
    message = store.OpenEntry(entryid, None, 0)

    props = message.GetProps([tag], 0)
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, 0x6600)
示例#11
0
    def settings_loads(self, data):
        data = _utils.pickle_loads(data)

        self.delegations_loads(data['delegations'])
        self.permissions_loads(data['permissions'])

        props = []
        for proptag, value in data['props'].items():
            if proptag in SETTINGS_PROPTAGS:
                props.append(SPropValue(proptag, value))

        self.mapiobj.SetProps(props)
        self.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
示例#12
0
 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)
示例#13
0
def test_recipienttable_addmore(addressbook, defaultmessage, make_recip_smtp_entry):
    recipients = [make_recip_smtp_entry(addressbook, 0, b'user4', b'*****@*****.**', MAPI_TO),
                  make_recip_smtp_entry(addressbook, 0, b'user5', b'*****@*****.**', MAPI_TO)]

    defaultmessage.ModifyRecipients(MODRECIP_ADD, recipients)
    defaultmessage.SaveChanges(0)

    table = defaultmessage.GetRecipientTable(0)
    table.SetColumns([PR_DISPLAY_NAME_A, PR_DISPLAY_NAME_W], 0)
    rows = table.QueryRows(10, 0)
    rowsresult = [[SPropValue(PR_DISPLAY_NAME_A, b'????'), SPropValue(PR_DISPLAY_NAME_W, u'ザラファ')],
                  [SPropValue(PR_DISPLAY_NAME_A, b'user2'), SPropValue(PR_DISPLAY_NAME_W, u'user2')],
                  [SPropValue(PR_DISPLAY_NAME_A, b'user4'), SPropValue(PR_DISPLAY_NAME_W, u'user4')],
                  [SPropValue(PR_DISPLAY_NAME_A, b'user5'), SPropValue(PR_DISPLAY_NAME_W, u'user5')]]
    assert rows == rowsresult
示例#14
0
    def __init__(self,
                 name=None,
                 server=None,
                 email=None,
                 ecuser=None,
                 userid=None):
        self.server = server or _server.Server(_skip_check=True,
                                               parse_args=False)
        self._ecuser = None
        self._name = None

        if ecuser:
            self._ecuser = ecuser

        elif userid:
            try:
                self._ecuser = \
                    self.server.sa.GetUser(_bdec(userid), MAPI_UNICODE)
            except (binascii.Error, TypeError):  # TODO generalize?
                raise ArgumentError("invalid entryid: '%s'" % userid)
            except MAPIErrorNotFound:
                raise NotFoundError("no user found with userid '%s'" % userid)

        elif email or name:
            if email:
                try:
                    self._name = str(
                        self.server.gab.ResolveNames(
                            [PR_EMAIL_ADDRESS_W],
                            MAPI_UNICODE | EMS_AB_ADDRESS_LOOKUP,
                            [[SPropValue(PR_DISPLAY_NAME_W, str(email))]],
                            [MAPI_UNRESOLVED])[0][0][1].Value)
                except (MAPIErrorNotFound, MAPIErrorInvalidParameter, \
                    IndexError):
                    raise NotFoundError("no such user '%s'" % email)
            else:
                self._name = str(name)

            try:
                self._ecuser = self.server.sa.GetUser(
                    self.server.sa.ResolveUserName(self._name, MAPI_UNICODE),
                    MAPI_UNICODE)
            # multi-tenant, but no '@' in username..
            except (MAPIErrorNotFound, MAPIErrorInvalidParameter):
                raise NotFoundError("no such user: '******'" % self.name)

        if self._ecuser:
            self._name = self._ecuser.Username
            self._userid = _benc(self._ecuser.UserID)

        self._mapiobj = None
示例#15
0
 def stores(self):
     """Return all company :class:`stores <Store>`."""
     if self.server.multitenant:
         table = self.server.sa.OpenUserStoresTable(MAPI_UNICODE)
         restriction = SPropertyRestriction(RELOP_EQ, PR_EC_COMPANY_NAME_W,
             SPropValue(PR_EC_COMPANY_NAME_W, self.name))
         table.Restrict(restriction, TBL_BATCH)
         for row in table.QueryRows(-1, 0):
             prop = PpropFindProp(row, PR_EC_STOREGUID)
             if prop:
                 yield _store.Store(_hex(prop.Value), self.server)
     else:
         for store in self.server.stores():
             yield store
示例#16
0
    def create_attachment(self, name, data):
        """Create a new attachment

        :param name: the attachment name
        :param data: string containing the attachment data
        """

        # XXX: use file object instead of data?
        (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)
        attach.SaveChanges(KEEP_OPEN_READWRITE)
        self.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)  # XXX needed?
        return Attachment(mapiobj=attach)
示例#17
0
def test_HTMLToRTFAndBack(message, copy):
    # test for #7244
    message.SetProps([
        SPropValue(PR_INTERNET_CPID, 28605),
        SPropValue(PR_HTML,
                   b'<html><body>I&#8217;d like that.<br></body></html>')
    ])
    plain = message.GetProps([PR_BODY_W], 0)[0].Value
    assert plain == 'I’d like that.\r\n'
    stream = message.OpenProperty(PR_RTF_COMPRESSED, IID_IStream, 0, 0)
    rtfprop = WrapCompressedRTFStream(stream, 0)
    rtf = rtfprop.Read(10240)
    assert rtf == b'{\\rtf1\\ansi\\ansicpg1252\\fromhtml1 \\deff0{\\fonttbl\r\n{\\f0\\fswiss\\fcharset0 Arial;}\r\n{\\f1\\fmodern Courier New;}\r\n{\\f2\\fnil\\fcharset2 Symbol;}\r\n{\\f3\\fmodern\\fcharset0 Courier New;}\r\n{\\f4\\fswiss\\fcharset0 Arial;}\r\n{\\f5\\fswiss Tahoma;}\r\n{\\f6\\fswiss\\fcharset0 Times New Roman;}}\r\n{\\colortbl\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green0\\blue255;}\r\n\\uc1\\pard\\plain\\deftab360 \\f0\\fs24 \r\n{\\*\\htmltag19 <html>}{\\*\\htmltag64}\r\n{\\*\\htmltag50 <body>}{\\*\\htmltag64}I\\htmlrtf \\u8217 ?\\htmlrtf0{\\*\\htmltag80&#8217;}d like that.\r\n{\\*\\htmltag112 <br>}{\\*\\htmltag64}\\htmlrtf \\line \\htmlrtf0 \r\n{\\*\\htmltag58 </body>}{\\*\\htmltag64}\r\n{\\*\\htmltag27 </html>}{\\*\\htmltag64}}\r\n'

    message.SaveChanges(0)
    # note: this copies the PR_RTF_COMPRESSED, and re-creates the plain+html bodies in copy. (rtf->html + rtf->plain)
    message.CopyTo([], None, 0, None, IID_IMessage, copy, 0)
    html = copy.GetProps([PR_HTML], 0)[0].Value
    # previously, we had a leading enter here because of rtf conversion (we could strip that in Util::HrHtmlToRtf())
    # but since we now copy from plain again, the enter isn't present anymore
    assert html == b"<html><body>I&#8217;d like that.<br></body></html>"
    plain = copy.GetProps([PR_BODY_W], 0)[0].Value
    assert plain == 'I’d like that.\r\n'
示例#18
0
    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, _unicode(text))),
            SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_BODY_W,
                                SPropValue(PR_BODY_W, _unicode(text))),
            SContentRestriction(FL_SUBSTRING | FL_IGNORECASE, PR_DISPLAY_TO_W,
                                SPropValue(PR_DISPLAY_TO_W, _unicode(text))),
            SContentRestriction(FL_SUBSTRING | FL_IGNORECASE,
                                PR_DISPLAY_NAME_W,
                                SPropValue(PR_DISPLAY_NAME_W, _unicode(text))),
            # XXX 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)
示例#19
0
def test_attachmen_table(defaultmessage, flags):
    table = defaultmessage.GetAttachmentTable(flags)
    table.SetColumns([PR_DISPLAY_NAME_A, PR_DISPLAY_NAME_W], 0)
    rows = table.QueryRows(10, 0)
    rowsresult = [[SPropValue(PR_DISPLAY_NAME_A, b'????1'), SPropValue(PR_DISPLAY_NAME_W, u'ザラファ1')],
                  [SPropValue(PR_DISPLAY_NAME_A, b'????2'), SPropValue(PR_DISPLAY_NAME_W, u'ザラファ2')],
                  [SPropValue(PR_DISPLAY_NAME_A, b'display 3'), SPropValue(PR_DISPLAY_NAME_W, u'display 3')]]

    assert rows == rowsresult
示例#20
0
def test_recordkey(message):
    props = message.GetProps([PR_RECORD_KEY], 0)
    assert props[0] == SPropValue(PROP_TAG(PT_ERROR, PROP_ID(PR_RECORD_KEY)), MAPI_E_NOT_FOUND)
    message.SaveChanges(KEEP_OPEN_READWRITE)
    props = message.GetProps([PR_RECORD_KEY, PR_ENTRYID], 0)
    assert props[0].ulPropTag == PR_RECORD_KEY
    assert len(props[0].Value) == 48
    assert props[0].Value == props[1].Value

    (id, att) = message.CreateAttach(None, 0)
    att.SetProps([SPropValue(PR_ATTACH_METHOD, ATTACH_EMBEDDED_MSG)])
    sub = att.OpenProperty(PR_ATTACH_DATA_OBJ, IID_IMessage, 0, MAPI_CREATE | MAPI_MODIFY)
    props = sub.GetProps([PR_RECORD_KEY, PR_ENTRYID, PR_SOURCE_KEY], 0)

    # Unsaved submessages have a source key but no record key or entryid
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RECORD_KEY))
    assert props[0].Value == MAPI_E_NOT_FOUND
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_ENTRYID))
    assert props[1].Value == MAPI_E_NOT_FOUND
    assert props[2].ulPropTag == PR_SOURCE_KEY
    assert len(props[2].Value) == 22

    sub.SaveChanges(0)
    att.SaveChanges(0)
    message.SaveChanges(0)

    att = message.OpenAttach(0, None, 0)
    sub = att.OpenProperty(PR_ATTACH_DATA_OBJ, IID_IMessage, 0, 0)
    props = sub.GetProps([PR_RECORD_KEY, PR_ENTRYID, PR_SOURCE_KEY], 0)

    # Saved submessages have a PR_SOURCE_KEY but no record key or entryid
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RECORD_KEY))
    assert props[0].Value == MAPI_E_NOT_FOUND
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_ENTRYID))
    assert props[1].Value == MAPI_E_NOT_FOUND
    assert props[2].ulPropTag == PR_SOURCE_KEY
    assert len(props[2].Value) == 22
示例#21
0
    def folder(self, path=None, entryid=None, recurse=False, create=False):
        """Return :class:`Folder` with given path or entryid

        :param path: Folder path (optional)
        :param entryid: Folder entryid (optional)
        :param create: Create folder if it doesn't exist (default False)
        """
        if entryid is not None:
            try:
                return Folder(self.store, entryid)
            except (MAPIErrorInvalidEntryid, MAPIErrorNotFound, TypeError):
                raise NotFoundError('no folder with entryid "%s"' % entryid)
        elif path is None:
            raise ArgumentError('missing argument to identify folder')

        if path is None:
            raise ArgumentError('no path or entryid specified')
        # TODO MAPI folders may contain '/' (and '\') in their names..
        if '/' in path.replace('\\/', ''):
            subfolder = self
            for name in UNESCAPED_SLASH_RE.split(path):
                subfolder = subfolder.folder(name, create=create,
                    recurse=False)
            return subfolder
        # TODO depth==0?
        if self == self.store.subtree and path in ENGLISH_FOLDER_MAP:
            f = getattr(self.store, ENGLISH_FOLDER_MAP[path], None)
            if f:
                path = f.name

        if create:
            name = path.replace('\\/', '/')
            try:
                mapifolder = self.mapiobj.CreateFolder(FOLDER_GENERIC,
                    str(name), '', None, MAPI_UNICODE)
                return Folder(self.store, _benc(HrGetOneProp(mapifolder,
                    PR_ENTRYID).Value))
            except MAPIErrorCollision:
                pass

        name = path.replace('\\/', '/')
        restriction = Restriction(SPropertyRestriction(RELOP_EQ,
            PR_DISPLAY_NAME_W, SPropValue(PR_DISPLAY_NAME_W, str(name))))

        folders = list(self.folders(recurse=recurse, restriction=restriction))
        if not folders:
            raise NotFoundError("no such folder: '%s'" % path)

        return folders[0]
示例#22
0
    def folder(self, path=None, entryid=None, recurse=False, create=False):
        """ Return :class:`Folder` with given path or entryid

            :param key: name, path or entryid
        """

        if entryid is not None:
            try:
                return Folder(self.store, entryid)
            except (MAPIErrorInvalidEntryid, MAPIErrorNotFound, TypeError):
                raise NotFoundError('cannot open folder with entryid "%s"' %
                                    entryid)

        if '/' in path.replace(
                '\\/', ''
        ):  # XXX MAPI folders may contain '/' (and '\') in their names..
            subfolder = self
            for name in UNESCAPED_SLASH_RE.split(path):
                subfolder = subfolder.folder(name,
                                             create=create,
                                             recurse=False)
            return subfolder

        if self == self.store.subtree and path in ENGLISH_FOLDER_MAP:  # XXX depth==0?
            path = getattr(self.store, ENGLISH_FOLDER_MAP[path]).name

        if create:
            name = path.replace('\\/', '/')
            try:
                mapifolder = self.mapiobj.CreateFolder(FOLDER_GENERIC,
                                                       _unicode(name), u'',
                                                       None, MAPI_UNICODE)
                return Folder(
                    self.store,
                    _benc(HrGetOneProp(mapifolder, PR_ENTRYID).Value))
            except MAPIErrorCollision:
                pass

        name = path.replace('\\/', '/')
        restriction = Restriction(
            SPropertyRestriction(RELOP_EQ, PR_DISPLAY_NAME_W,
                                 SPropValue(PR_DISPLAY_NAME_W,
                                            _unicode(name))))

        folders = list(self.folders(recurse=recurse, restriction=restriction))
        if len(folders) == 0:
            raise NotFoundError("no such folder: '%s'" % path)

        return folders[0]
示例#23
0
    def config_item(self, name):
        """Retrieve the config item for the given name.

        :param name: The config item name
        """
        table = self.subtree.mapiobj.GetContentsTable(MAPI_DEFERRED_ERRORS | MAPI_ASSOCIATED)
        table.Restrict(SPropertyRestriction(RELOP_EQ, PR_SUBJECT, SPropValue(PR_SUBJECT, name)), 0)
        rows = table.QueryRows(1,0)
        # No config item found, create new message
        if len(rows) == 0:
            item = self.subtree.associated.create_item(message_class='IPM.Zarafa.Configuration', subject=name)
        else:
            mapiobj = self.subtree.mapiobj.OpenEntry(rows[0][0].Value, None, MAPI_MODIFY)
            item = _item.Item(mapiobj=mapiobj)
        return item
示例#24
0
def test_deletedontimestamp(root, message):
    message.SetProps([SPropValue(PR_SUBJECT, b'Test')])
    message.SaveChanges(KEEP_OPEN_READWRITE)
    eid = message.GetProps([PR_ENTRYID], 0)[0]
    root.DeleteMessages([eid.Value], 0, None, 0)

    table = root.GetContentsTable(SHOW_SOFT_DELETES)
    table.SetColumns([PR_SUBJECT, PR_ENTRYID, PR_DELETED_ON], 0)
    table.FindRow(SPropertyRestriction(RELOP_EQ, PR_ENTRYID, eid), 0, 0)
    rows = table.QueryRows(1, 0)

    assert PpropFindProp(rows[0], PR_DELETED_ON)

    # Clean up message
    root.DeleteMessages([rows[0][1].Value], 0, None, 0)
示例#25
0
    def __init__(self,
                 name=None,
                 server=None,
                 email=None,
                 ecuser=None,
                 userid=None):
        self.server = server or _server.Server()
        self._ecuser = None
        self._name = None

        if ecuser:
            self._ecuser = ecuser

        elif userid:
            try:
                self._ecuser = self.server.sa.GetUser(_bdec(userid),
                                                      MAPI_UNICODE)
            except MAPIErrorNotFound:
                raise NotFoundError("no user found with userid '%s'" % userid)

        elif email or name:
            if email:
                try:
                    self._name = _unicode(
                        self.server.gab.ResolveNames(
                            [PR_EMAIL_ADDRESS_W],
                            MAPI_UNICODE | EMS_AB_ADDRESS_LOOKUP,
                            [[SPropValue(PR_DISPLAY_NAME_W, _unicode(email))]],
                            [MAPI_UNRESOLVED])[0][0][1].Value)
                except (MAPIErrorNotFound, MAPIErrorInvalidParameter,
                        IndexError):
                    raise NotFoundError("no such user '%s'" % email)
            else:
                self._name = _unicode(name)

            try:
                self._ecuser = self.server.sa.GetUser(
                    self.server.sa.ResolveUserName(self._name, MAPI_UNICODE),
                    MAPI_UNICODE)
            except (MAPIErrorNotFound, MAPIErrorInvalidParameter
                    ):  # multi-tenant, but no '@' in username..
                raise NotFoundError("no such user: '******'" % self.name)

        if self._ecuser:
            self._name = self._ecuser.Username
            self._userid = _benc(self._ecuser.UserID)

        self._mapiobj = None
示例#26
0
 def company(self):
     """Store :class:`company <Company>`."""
     if self.server.multitenant:
         table = self.server.sa.OpenUserStoresTable(MAPI_UNICODE)
         table.Restrict(SPropertyRestriction(RELOP_EQ, PR_EC_STOREGUID, SPropValue(PR_EC_STOREGUID, _bdec(self.guid))), TBL_BATCH)
         for row in table.QueryRows(1, 0):
             storetype = PpropFindProp(row, PR_EC_STORETYPE)
             if storetype.Value == ECSTORE_TYPE_PUBLIC:
                 companyname = PpropFindProp(row, PR_EC_USERNAME_W) # XXX bug in ECUserStoreTable.cpp?
                 if not companyname:
                     companyname = PpropFindProp(row, PR_EC_COMPANY_NAME_W) # XXX
             else:
                 companyname = PpropFindProp(row, PR_EC_COMPANY_NAME_W)
             return self.server.company(companyname.Value)
     else:
         return next(self.server.companies())
示例#27
0
    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:
            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

                    message._attobj.SaveChanges(KEEP_OPEN_READWRITE)

        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:
            cal_item.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
示例#28
0
    def settings_loads(self, data):
        """Deserialize (overriding) all store settings.

        :param data: Serialized data
        """
        data = _utils.pickle_loads(data)

        self.delegations_loads(data['delegations'])
        self.permissions_loads(data['permissions'])

        props = []
        for proptag, value in data['props'].items():
            if proptag in SETTINGS_PROPTAGS:
                props.append(SPropValue(proptag, value))

        self.mapiobj.SetProps(props)
        self.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
示例#29
0
def create_prop(self, mapiobj, proptag, value=None, proptype=None):
    if isinstance(proptag, int) or \
       (isinstance(proptag, str) and ':' not in proptag):
        if isinstance(proptag, str):
            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:
            # TODO exception too general?
            raise Error('Missing type to create named property')

    if value is None:
        if proptype2 in (PT_STRING8, PT_UNICODE):
            value = ''
        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:
            if value.tzinfo is None:
                value = _timezone._to_utc(value, _timezone.LOCAL)
            else:
                value = value.astimezone(_timezone.UTC)
            value = unixtime(calendar.timegm(value.utctimetuple()))

    # 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)
示例#30
0
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)