Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mapiutil.py 7.1KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. # General utilities for MAPI and MAPI objects.
  2. # We used to use these old names from the 'types' module...
  3. TupleType = tuple
  4. ListType = list
  5. IntType = int
  6. import pythoncom
  7. from pywintypes import TimeType
  8. from . import mapi, mapitags
  9. prTable = {}
  10. def GetPropTagName(pt):
  11. if not prTable:
  12. for name, value in mapitags.__dict__.items():
  13. if name[:3] == "PR_":
  14. # Store both the full ID (including type) and just the ID.
  15. # This is so PR_FOO_A and PR_FOO_W are still differentiated,
  16. # but should we get a PT_FOO with PT_ERROR set, we fallback
  17. # to the ID.
  18. # String types should have 3 definitions in mapitags.py
  19. # PR_BODY = PROP_TAG( PT_TSTRING, 4096)
  20. # PR_BODY_W = PROP_TAG( PT_UNICODE, 4096)
  21. # PR_BODY_A = PROP_TAG( PT_STRING8, 4096)
  22. # The following change ensures a lookup using only the the
  23. # property id returns the conditional default.
  24. # PT_TSTRING is a conditional assignment for either PT_UNICODE or
  25. # PT_STRING8 and should not be returned during a lookup.
  26. if (
  27. mapitags.PROP_TYPE(value) == mapitags.PT_UNICODE
  28. or mapitags.PROP_TYPE(value) == mapitags.PT_STRING8
  29. ):
  30. if name[-2:] == "_A" or name[-2:] == "_W":
  31. prTable[value] = name
  32. else:
  33. prTable[mapitags.PROP_ID(value)] = name
  34. else:
  35. prTable[value] = name
  36. prTable[mapitags.PROP_ID(value)] = name
  37. try:
  38. try:
  39. return prTable[pt]
  40. except KeyError:
  41. # Can't find it exactly - see if the raw ID exists.
  42. return prTable[mapitags.PROP_ID(pt)]
  43. except KeyError:
  44. # god-damn bullshit hex() warnings: I don't see a way to get the
  45. # old behaviour without a warning!!
  46. ret = hex(int(pt))
  47. # -0x8000000L -> 0x80000000
  48. if ret[0] == "-":
  49. ret = ret[1:]
  50. if ret[-1] == "L":
  51. ret = ret[:-1]
  52. return ret
  53. mapiErrorTable = {}
  54. def GetScodeString(hr):
  55. if not mapiErrorTable:
  56. for name, value in mapi.__dict__.items():
  57. if name[:7] in ["MAPI_E_", "MAPI_W_"]:
  58. mapiErrorTable[value] = name
  59. return mapiErrorTable.get(hr, pythoncom.GetScodeString(hr))
  60. ptTable = {}
  61. def GetMapiTypeName(propType, rawType=True):
  62. """Given a mapi type flag, return a string description of the type"""
  63. if not ptTable:
  64. for name, value in mapitags.__dict__.items():
  65. if name[:3] == "PT_":
  66. # PT_TSTRING is a conditional assignment
  67. # for either PT_UNICODE or PT_STRING8 and
  68. # should not be returned during a lookup.
  69. if name in ["PT_TSTRING", "PT_MV_TSTRING"]:
  70. continue
  71. ptTable[value] = name
  72. if rawType:
  73. propType = propType & ~mapitags.MV_FLAG
  74. return ptTable.get(propType, str(hex(propType)))
  75. def GetProperties(obj, propList):
  76. """Given a MAPI object and a list of properties, return a list of property values.
  77. Allows a single property to be passed, and the result is a single object.
  78. Each request property can be an integer or a string. Of a string, it is
  79. automatically converted to an integer via the GetIdsFromNames function.
  80. If the property fetch fails, the result is None.
  81. """
  82. bRetList = 1
  83. if type(propList) not in [TupleType, ListType]:
  84. bRetList = 0
  85. propList = (propList,)
  86. realPropList = []
  87. rc = []
  88. for prop in propList:
  89. if type(prop) != IntType: # Integer
  90. props = ((mapi.PS_PUBLIC_STRINGS, prop),)
  91. propIds = obj.GetIDsFromNames(props, 0)
  92. prop = mapitags.PROP_TAG(
  93. mapitags.PT_UNSPECIFIED, mapitags.PROP_ID(propIds[0])
  94. )
  95. realPropList.append(prop)
  96. hr, data = obj.GetProps(realPropList, 0)
  97. if hr != 0:
  98. data = None
  99. return None
  100. if bRetList:
  101. return [v[1] for v in data]
  102. else:
  103. return data[0][1]
  104. def GetAllProperties(obj, make_tag_names=True):
  105. tags = obj.GetPropList(0)
  106. hr, data = obj.GetProps(tags)
  107. ret = []
  108. for tag, val in data:
  109. if make_tag_names:
  110. hr, tags, array = obj.GetNamesFromIDs((tag,))
  111. if type(array[0][1]) == type(""):
  112. name = array[0][1]
  113. else:
  114. name = GetPropTagName(tag)
  115. else:
  116. name = tag
  117. ret.append((name, val))
  118. return ret
  119. _MapiTypeMap = {
  120. type(0.0): mapitags.PT_DOUBLE,
  121. type(0): mapitags.PT_I4,
  122. type("".encode("ascii")): mapitags.PT_STRING8, # bytes
  123. type(""): mapitags.PT_UNICODE, # str
  124. type(None): mapitags.PT_UNSPECIFIED,
  125. # In Python 2.2.2, bool isn't a distinct type (type(1==1) is type(0)).
  126. # (markh thinks the above is trying to say that in 2020, we probably *do*
  127. # want bool in this map? :)
  128. }
  129. def SetPropertyValue(obj, prop, val):
  130. if type(prop) != IntType:
  131. props = ((mapi.PS_PUBLIC_STRINGS, prop),)
  132. propIds = obj.GetIDsFromNames(props, mapi.MAPI_CREATE)
  133. if val == (1 == 1) or val == (1 == 0):
  134. type_tag = mapitags.PT_BOOLEAN
  135. else:
  136. type_tag = _MapiTypeMap.get(type(val))
  137. if type_tag is None:
  138. raise ValueError(
  139. "Don't know what to do with '%r' ('%s')" % (val, type(val))
  140. )
  141. prop = mapitags.PROP_TAG(type_tag, mapitags.PROP_ID(propIds[0]))
  142. if val is None:
  143. # Delete the property
  144. obj.DeleteProps((prop,))
  145. else:
  146. obj.SetProps(((prop, val),))
  147. def SetProperties(msg, propDict):
  148. """Given a Python dictionary, set the objects properties.
  149. If the dictionary key is a string, then a property ID is queried
  150. otherwise the ID is assumed native.
  151. Coded for maximum efficiency wrt server calls - ie, maximum of
  152. 2 calls made to the object, regardless of the dictionary contents
  153. (only 1 if dictionary full of int keys)
  154. """
  155. newProps = []
  156. # First pass over the properties we should get IDs for.
  157. for key, val in propDict.items():
  158. if type(key) == str:
  159. newProps.append((mapi.PS_PUBLIC_STRINGS, key))
  160. # Query for the new IDs
  161. if newProps:
  162. newIds = msg.GetIDsFromNames(newProps, mapi.MAPI_CREATE)
  163. newIdNo = 0
  164. newProps = []
  165. for key, val in propDict.items():
  166. if type(key) == str:
  167. type_val = type(val)
  168. if type_val == str:
  169. tagType = mapitags.PT_UNICODE
  170. elif type_val == IntType:
  171. tagType = mapitags.PT_I4
  172. elif type_val == TimeType:
  173. tagType = mapitags.PT_SYSTIME
  174. else:
  175. raise ValueError(
  176. "The type of object %s(%s) can not be written"
  177. % (repr(val), type_val)
  178. )
  179. key = mapitags.PROP_TAG(tagType, mapitags.PROP_ID(newIds[newIdNo]))
  180. newIdNo = newIdNo + 1
  181. newProps.append((key, val))
  182. msg.SetProps(newProps)