123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- # General utilities for MAPI and MAPI objects.
- # We used to use these old names from the 'types' module...
- TupleType = tuple
- ListType = list
- IntType = int
- import pythoncom
- from pywintypes import TimeType
-
- from . import mapi, mapitags
-
- prTable = {}
-
-
- def GetPropTagName(pt):
- if not prTable:
- for name, value in mapitags.__dict__.items():
- if name[:3] == "PR_":
- # Store both the full ID (including type) and just the ID.
- # This is so PR_FOO_A and PR_FOO_W are still differentiated,
- # but should we get a PT_FOO with PT_ERROR set, we fallback
- # to the ID.
-
- # String types should have 3 definitions in mapitags.py
- # PR_BODY = PROP_TAG( PT_TSTRING, 4096)
- # PR_BODY_W = PROP_TAG( PT_UNICODE, 4096)
- # PR_BODY_A = PROP_TAG( PT_STRING8, 4096)
- # The following change ensures a lookup using only the the
- # property id returns the conditional default.
-
- # PT_TSTRING is a conditional assignment for either PT_UNICODE or
- # PT_STRING8 and should not be returned during a lookup.
-
- if (
- mapitags.PROP_TYPE(value) == mapitags.PT_UNICODE
- or mapitags.PROP_TYPE(value) == mapitags.PT_STRING8
- ):
- if name[-2:] == "_A" or name[-2:] == "_W":
- prTable[value] = name
- else:
- prTable[mapitags.PROP_ID(value)] = name
-
- else:
- prTable[value] = name
- prTable[mapitags.PROP_ID(value)] = name
-
- try:
- try:
- return prTable[pt]
- except KeyError:
- # Can't find it exactly - see if the raw ID exists.
- return prTable[mapitags.PROP_ID(pt)]
- except KeyError:
- # god-damn bullshit hex() warnings: I don't see a way to get the
- # old behaviour without a warning!!
- ret = hex(int(pt))
- # -0x8000000L -> 0x80000000
- if ret[0] == "-":
- ret = ret[1:]
- if ret[-1] == "L":
- ret = ret[:-1]
- return ret
-
-
- mapiErrorTable = {}
-
-
- def GetScodeString(hr):
- if not mapiErrorTable:
- for name, value in mapi.__dict__.items():
- if name[:7] in ["MAPI_E_", "MAPI_W_"]:
- mapiErrorTable[value] = name
- return mapiErrorTable.get(hr, pythoncom.GetScodeString(hr))
-
-
- ptTable = {}
-
-
- def GetMapiTypeName(propType, rawType=True):
- """Given a mapi type flag, return a string description of the type"""
- if not ptTable:
- for name, value in mapitags.__dict__.items():
- if name[:3] == "PT_":
- # PT_TSTRING is a conditional assignment
- # for either PT_UNICODE or PT_STRING8 and
- # should not be returned during a lookup.
- if name in ["PT_TSTRING", "PT_MV_TSTRING"]:
- continue
- ptTable[value] = name
-
- if rawType:
- propType = propType & ~mapitags.MV_FLAG
- return ptTable.get(propType, str(hex(propType)))
-
-
- def GetProperties(obj, propList):
- """Given a MAPI object and a list of properties, return a list of property values.
-
- Allows a single property to be passed, and the result is a single object.
-
- Each request property can be an integer or a string. Of a string, it is
- automatically converted to an integer via the GetIdsFromNames function.
-
- If the property fetch fails, the result is None.
- """
- bRetList = 1
- if type(propList) not in [TupleType, ListType]:
- bRetList = 0
- propList = (propList,)
- realPropList = []
- rc = []
- for prop in propList:
- if type(prop) != IntType: # Integer
- props = ((mapi.PS_PUBLIC_STRINGS, prop),)
- propIds = obj.GetIDsFromNames(props, 0)
- prop = mapitags.PROP_TAG(
- mapitags.PT_UNSPECIFIED, mapitags.PROP_ID(propIds[0])
- )
- realPropList.append(prop)
-
- hr, data = obj.GetProps(realPropList, 0)
- if hr != 0:
- data = None
- return None
- if bRetList:
- return [v[1] for v in data]
- else:
- return data[0][1]
-
-
- def GetAllProperties(obj, make_tag_names=True):
- tags = obj.GetPropList(0)
- hr, data = obj.GetProps(tags)
- ret = []
- for tag, val in data:
- if make_tag_names:
- hr, tags, array = obj.GetNamesFromIDs((tag,))
- if type(array[0][1]) == type(""):
- name = array[0][1]
- else:
- name = GetPropTagName(tag)
- else:
- name = tag
- ret.append((name, val))
- return ret
-
-
- _MapiTypeMap = {
- type(0.0): mapitags.PT_DOUBLE,
- type(0): mapitags.PT_I4,
- type("".encode("ascii")): mapitags.PT_STRING8, # bytes
- type(""): mapitags.PT_UNICODE, # str
- type(None): mapitags.PT_UNSPECIFIED,
- # In Python 2.2.2, bool isn't a distinct type (type(1==1) is type(0)).
- # (markh thinks the above is trying to say that in 2020, we probably *do*
- # want bool in this map? :)
- }
-
-
- def SetPropertyValue(obj, prop, val):
- if type(prop) != IntType:
- props = ((mapi.PS_PUBLIC_STRINGS, prop),)
- propIds = obj.GetIDsFromNames(props, mapi.MAPI_CREATE)
- if val == (1 == 1) or val == (1 == 0):
- type_tag = mapitags.PT_BOOLEAN
- else:
- type_tag = _MapiTypeMap.get(type(val))
- if type_tag is None:
- raise ValueError(
- "Don't know what to do with '%r' ('%s')" % (val, type(val))
- )
- prop = mapitags.PROP_TAG(type_tag, mapitags.PROP_ID(propIds[0]))
- if val is None:
- # Delete the property
- obj.DeleteProps((prop,))
- else:
- obj.SetProps(((prop, val),))
-
-
- def SetProperties(msg, propDict):
- """Given a Python dictionary, set the objects properties.
-
- If the dictionary key is a string, then a property ID is queried
- otherwise the ID is assumed native.
-
- Coded for maximum efficiency wrt server calls - ie, maximum of
- 2 calls made to the object, regardless of the dictionary contents
- (only 1 if dictionary full of int keys)
- """
-
- newProps = []
- # First pass over the properties we should get IDs for.
- for key, val in propDict.items():
- if type(key) == str:
- newProps.append((mapi.PS_PUBLIC_STRINGS, key))
- # Query for the new IDs
- if newProps:
- newIds = msg.GetIDsFromNames(newProps, mapi.MAPI_CREATE)
- newIdNo = 0
- newProps = []
- for key, val in propDict.items():
- if type(key) == str:
- type_val = type(val)
- if type_val == str:
- tagType = mapitags.PT_UNICODE
- elif type_val == IntType:
- tagType = mapitags.PT_I4
- elif type_val == TimeType:
- tagType = mapitags.PT_SYSTIME
- else:
- raise ValueError(
- "The type of object %s(%s) can not be written"
- % (repr(val), type_val)
- )
- key = mapitags.PROP_TAG(tagType, mapitags.PROP_ID(newIds[newIdNo]))
- newIdNo = newIdNo + 1
- newProps.append((key, val))
- msg.SetProps(newProps)
|