123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- # General utilities for MAPI and MAPI objects.
- # We used to use these old names from the 'types' module...
- TupleType=tuple
- ListType=list
- IntType=int
- from pywintypes import TimeType
- import pythoncom
- 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)
|