mapiutil.py
5.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# 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
import mapi, mapitags
prTable = {}
def GetPropTagName(pt):
if not prTable:
for name, value in mapitags.__dict__.iteritems():
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(long(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__.iteritems():
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__.iteritems():
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 == 'PT_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(u''):
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, # str in py2x, bytes in 3x
type(u''): mapitags.PT_UNICODE, # unicode in py2x, str in 3x
type(None): mapitags.PT_UNSPECIFIED,
# In Python 2.2.2, bool isn't a distinct type (type(1==1) is type(0)).
}
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.iteritems():
if type(key) in [str, unicode]:
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.iteritems():
if type(key) in [str, unicode]:
type_val=type(val)
if type_val in [str, unicode]:
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)