extract-msg 0.48.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- extract_msg/__init__.py +71 -0
- extract_msg/__main__.py +115 -0
- extract_msg/_rtf/__init__.py +21 -0
- extract_msg/_rtf/create_doc.py +29 -0
- extract_msg/_rtf/inject_rtf.py +174 -0
- extract_msg/_rtf/token.py +35 -0
- extract_msg/_rtf/tokenize_rtf.py +253 -0
- extract_msg/attachments/__init__.py +144 -0
- extract_msg/attachments/attachment.py +188 -0
- extract_msg/attachments/attachment_base.py +730 -0
- extract_msg/attachments/broken_att.py +42 -0
- extract_msg/attachments/custom_att.py +173 -0
- extract_msg/attachments/custom_att_handler/__init__.py +80 -0
- extract_msg/attachments/custom_att_handler/custom_handler.py +134 -0
- extract_msg/attachments/custom_att_handler/lnk_obj_att.py +109 -0
- extract_msg/attachments/custom_att_handler/outlook_image_dib.py +141 -0
- extract_msg/attachments/emb_msg_att.py +134 -0
- extract_msg/attachments/signed_att.py +234 -0
- extract_msg/attachments/unsupported_att.py +40 -0
- extract_msg/attachments/web_att.py +74 -0
- extract_msg/constants/__init__.py +294 -0
- extract_msg/constants/ps.py +46 -0
- extract_msg/constants/re.py +42 -0
- extract_msg/constants/st.py +110 -0
- extract_msg/data/logging-config/logging-nt.json +64 -0
- extract_msg/data/logging-config/logging-posix.json +64 -0
- extract_msg/encoding/__init__.py +277 -0
- extract_msg/encoding/_dt/__init__.py +4 -0
- extract_msg/encoding/_dt/_mac_ce.py +8 -0
- extract_msg/encoding/_dt/_mac_cyrillic.py +8 -0
- extract_msg/encoding/_dt/_mac_greek.py +8 -0
- extract_msg/encoding/_dt/_mac_iceland.py +8 -0
- extract_msg/encoding/_dt/_mac_turkish.py +8 -0
- extract_msg/encoding/_dt/_win874_dec.py +8 -0
- extract_msg/encoding/_dt/_win950_dec.py +6 -0
- extract_msg/encoding/utils.py +329 -0
- extract_msg/enums.py +2067 -0
- extract_msg/exceptions.py +170 -0
- extract_msg/msg_classes/__init__.py +49 -0
- extract_msg/msg_classes/appointment.py +195 -0
- extract_msg/msg_classes/calendar.py +92 -0
- extract_msg/msg_classes/calendar_base.py +496 -0
- extract_msg/msg_classes/contact.py +1335 -0
- extract_msg/msg_classes/journal.py +131 -0
- extract_msg/msg_classes/meeting_cancellation.py +108 -0
- extract_msg/msg_classes/meeting_exception.py +55 -0
- extract_msg/msg_classes/meeting_forward.py +115 -0
- extract_msg/msg_classes/meeting_related.py +65 -0
- extract_msg/msg_classes/meeting_request.py +189 -0
- extract_msg/msg_classes/meeting_response.py +74 -0
- extract_msg/msg_classes/message.py +12 -0
- extract_msg/msg_classes/message_base.py +1382 -0
- extract_msg/msg_classes/message_signed.py +17 -0
- extract_msg/msg_classes/message_signed_base.py +168 -0
- extract_msg/msg_classes/msg.py +1172 -0
- extract_msg/msg_classes/post.py +53 -0
- extract_msg/msg_classes/sticky_note.py +67 -0
- extract_msg/msg_classes/task.py +363 -0
- extract_msg/msg_classes/task_request.py +86 -0
- extract_msg/null_date.py +34 -0
- extract_msg/ole_writer.py +1086 -0
- extract_msg/open_msg.py +204 -0
- extract_msg/properties/__init__.py +23 -0
- extract_msg/properties/named.py +481 -0
- extract_msg/properties/prop.py +506 -0
- extract_msg/properties/properties_store.py +476 -0
- extract_msg/py.typed +0 -0
- extract_msg/recipient.py +362 -0
- extract_msg/structures/__init__.py +34 -0
- extract_msg/structures/_helpers.py +345 -0
- extract_msg/structures/business_card.py +422 -0
- extract_msg/structures/cfoas.py +108 -0
- extract_msg/structures/contact_link_entry.py +51 -0
- extract_msg/structures/dev_mode_a.py +621 -0
- extract_msg/structures/dv_target_device.py +168 -0
- extract_msg/structures/entry_id.py +697 -0
- extract_msg/structures/misc_id.py +222 -0
- extract_msg/structures/mon_stream.py +55 -0
- extract_msg/structures/odt.py +74 -0
- extract_msg/structures/ole_pres.py +302 -0
- extract_msg/structures/ole_stream_struct.py +117 -0
- extract_msg/structures/recurrence_pattern.py +199 -0
- extract_msg/structures/report_tag.py +127 -0
- extract_msg/structures/system_time.py +158 -0
- extract_msg/structures/time_zone_definition.py +111 -0
- extract_msg/structures/time_zone_struct.py +102 -0
- extract_msg/structures/toc_entry.py +137 -0
- extract_msg/structures/tz_rule.py +148 -0
- extract_msg/utils.py +1270 -0
- extract_msg-0.48.2.dist-info/LICENSE.txt +674 -0
- extract_msg-0.48.2.dist-info/METADATA +321 -0
- extract_msg-0.48.2.dist-info/RECORD +95 -0
- extract_msg-0.48.2.dist-info/WHEEL +5 -0
- extract_msg-0.48.2.dist-info/entry_points.txt +2 -0
- extract_msg-0.48.2.dist-info/top_level.txt +1 -0
extract_msg/recipient.py
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
'Recipient',
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import enum
|
|
10
|
+
import functools
|
|
11
|
+
import logging
|
|
12
|
+
import weakref
|
|
13
|
+
|
|
14
|
+
from typing import (
|
|
15
|
+
Any, Generic, List, Optional, Tuple, TYPE_CHECKING, Type, TypeVar, Union
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from .constants import MSG_PATH, OVERRIDE_CLASS
|
|
19
|
+
from .enums import ErrorBehavior, PropertiesType
|
|
20
|
+
from .exceptions import StandardViolationError
|
|
21
|
+
from .properties.properties_store import PropertiesStore
|
|
22
|
+
from .structures.entry_id import PermanentEntryID
|
|
23
|
+
from .utils import msgPathToString
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from .msg_classes.msg import MSGFile
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
logger.addHandler(logging.NullHandler())
|
|
31
|
+
|
|
32
|
+
_T = TypeVar('_T')
|
|
33
|
+
_RT = TypeVar('_RT', bound = enum.IntEnum)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Recipient(Generic[_RT]):
|
|
37
|
+
"""
|
|
38
|
+
Contains the data of one of the recipients in an MSG file.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, _dir: str, msg: MSGFile, recipientTypeClass: Type[_RT]):
|
|
42
|
+
self.__msg = weakref.ref(msg) # Allows calls to original msg file.
|
|
43
|
+
self.__dir = _dir
|
|
44
|
+
if not self.exists('__properties_version1.0'):
|
|
45
|
+
if ErrorBehavior.STANDARDS_VIOLATION in msg.errorBehavior:
|
|
46
|
+
logger.error('Recipients MUST have a property stream.')
|
|
47
|
+
else:
|
|
48
|
+
raise StandardViolationError('Recipients MUST have a property stream.') from None
|
|
49
|
+
self.__props = PropertiesStore(self.getStream('__properties_version1.0'), PropertiesType.RECIPIENT)
|
|
50
|
+
self.__email = self.getStringStream('__substg1.0_39FE')
|
|
51
|
+
if not self.__email:
|
|
52
|
+
self.__email = self.getStringStream('__substg1.0_3003')
|
|
53
|
+
self.__name = self.getStringStream('__substg1.0_3001')
|
|
54
|
+
self.__typeFlags = self.__props.getValue('0C150003', 0)
|
|
55
|
+
self.__type = recipientTypeClass(0xF & self.__typeFlags)
|
|
56
|
+
self.__formatted = f'{self.__name} <{self.__email}>'
|
|
57
|
+
|
|
58
|
+
def exists(self, filename: MSG_PATH) -> bool:
|
|
59
|
+
"""
|
|
60
|
+
Checks if stream exists inside the recipient folder.
|
|
61
|
+
|
|
62
|
+
:raises ReferenceError: The associated ``MSGFile`` instance has been
|
|
63
|
+
garbage collected.
|
|
64
|
+
"""
|
|
65
|
+
if (msg := self.__msg()) is None:
|
|
66
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
67
|
+
return msg.exists([self.__dir, msgPathToString(filename)])
|
|
68
|
+
|
|
69
|
+
def sExists(self, filename: MSG_PATH) -> bool:
|
|
70
|
+
"""
|
|
71
|
+
Checks if the string stream exists inside the recipient folder.
|
|
72
|
+
|
|
73
|
+
:raises ReferenceError: The associated ``MSGFile`` instance has been
|
|
74
|
+
garbage collected.
|
|
75
|
+
"""
|
|
76
|
+
if (msg := self.__msg()) is None:
|
|
77
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
78
|
+
return msg.sExists([self.__dir, msgPathToString(filename)])
|
|
79
|
+
|
|
80
|
+
def existsTypedProperty(self, id, _type = None) -> Tuple[bool, int]:
|
|
81
|
+
"""
|
|
82
|
+
Determines if the stream with the provided id exists.
|
|
83
|
+
|
|
84
|
+
The return of this function is 2 values, the first being a boolean for if anything was found, and the second being how many were found.
|
|
85
|
+
|
|
86
|
+
:raises ReferenceError: The associated ``MSGFile`` instance has been
|
|
87
|
+
garbage collected.
|
|
88
|
+
"""
|
|
89
|
+
if (msg := self.__msg()) is None:
|
|
90
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
91
|
+
return msg.existsTypedProperty(id, self.__dir, _type, True, self.__props)
|
|
92
|
+
|
|
93
|
+
def getMultipleBinary(self, filename: MSG_PATH) -> Optional[List[bytes]]:
|
|
94
|
+
"""
|
|
95
|
+
Gets a multiple binary property as a list of bytes objects.
|
|
96
|
+
|
|
97
|
+
Like :meth:`getStringStream`, the 4 character type suffix should be
|
|
98
|
+
omitted. So if you want the stream "__substg1.0_00011102" then the
|
|
99
|
+
filename would simply be "__substg1.0_0001".
|
|
100
|
+
|
|
101
|
+
:raises ReferenceError: The associated ``MSGFile`` instance has been
|
|
102
|
+
garbage collected.
|
|
103
|
+
"""
|
|
104
|
+
if (msg := self.__msg()) is None:
|
|
105
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
106
|
+
return msg.getMultipleBinary([self.__dir, msgPathToString(filename)])
|
|
107
|
+
|
|
108
|
+
def getMultipleString(self, filename: MSG_PATH) -> Optional[List[str]]:
|
|
109
|
+
"""
|
|
110
|
+
Gets a multiple string property as a list of str objects.
|
|
111
|
+
|
|
112
|
+
Like :meth:`getStringStream`, the 4 character type suffix should be
|
|
113
|
+
omitted. So if you want the stream "__substg1.0_00011102" then the
|
|
114
|
+
filename would simply be "__substg1.0_0001".
|
|
115
|
+
|
|
116
|
+
:raises ReferenceError: The associated ``MSGFile`` instance has been
|
|
117
|
+
garbage collected.
|
|
118
|
+
"""
|
|
119
|
+
if (msg := self.__msg()) is None:
|
|
120
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
121
|
+
return msg.getMultipleString([self.__dir, msgPathToString(filename)])
|
|
122
|
+
|
|
123
|
+
def getPropertyAs(self, propertyName: Union[int, str], overrideClass: OVERRIDE_CLASS[_T]) -> Optional[_T]:
|
|
124
|
+
"""
|
|
125
|
+
Returns the property, setting the class if found.
|
|
126
|
+
|
|
127
|
+
:param overrideClass: Class/function to use to morph the data that was
|
|
128
|
+
read. The data will be the first argument to the class's
|
|
129
|
+
``__init__`` method or the function itself, if that is what is
|
|
130
|
+
provided. If the value is ``None``, this function is not called. If
|
|
131
|
+
you want it to be called regardless, you should handle the data
|
|
132
|
+
directly.
|
|
133
|
+
"""
|
|
134
|
+
value = self.getPropertyVal(propertyName)
|
|
135
|
+
|
|
136
|
+
if value is not None:
|
|
137
|
+
value = overrideClass(value)
|
|
138
|
+
|
|
139
|
+
return value
|
|
140
|
+
|
|
141
|
+
def getPropertyVal(self, name: Union[int, str], default: _T = None) -> Union[Any, _T]:
|
|
142
|
+
"""
|
|
143
|
+
``instance.props.getValue(name, default)``
|
|
144
|
+
|
|
145
|
+
Can be overridden to create new behavior.
|
|
146
|
+
"""
|
|
147
|
+
return self.props.getValue(name, default)
|
|
148
|
+
|
|
149
|
+
def getSingleOrMultipleBinary(self, filename: MSG_PATH) -> Optional[Union[List[bytes], bytes]]:
|
|
150
|
+
"""
|
|
151
|
+
A combination of :meth:`getStringStream` and :meth:`getMultipleString`.
|
|
152
|
+
|
|
153
|
+
Checks to see if a single binary stream exists to return, otherwise
|
|
154
|
+
tries to return the multiple binary stream of the same ID.
|
|
155
|
+
|
|
156
|
+
Like :meth:`getStringStream`, the 4 character type suffix should be
|
|
157
|
+
omitted. So if you want the stream "__substg1.0_00010102" then the
|
|
158
|
+
filename would simply be "__substg1.0_0001".
|
|
159
|
+
|
|
160
|
+
:raises ReferenceError: The associated ``MSGFile`` instance has been
|
|
161
|
+
garbage collected.
|
|
162
|
+
"""
|
|
163
|
+
if (msg := self.__msg()) is None:
|
|
164
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
165
|
+
return msg.getSingleOrMultipleBinary([self.__dir, msgPathToString(filename)])
|
|
166
|
+
|
|
167
|
+
def getSingleOrMultipleString(self, filename: MSG_PATH) -> Optional[Union[List[str], str]]:
|
|
168
|
+
"""
|
|
169
|
+
A combination of :meth:`getStringStream` and :meth:`getMultipleString`.
|
|
170
|
+
|
|
171
|
+
Checks to see if a single string stream exists to return, otherwise
|
|
172
|
+
tries to return the multiple string stream of the same ID.
|
|
173
|
+
|
|
174
|
+
Like :meth:`getStringStream`, the 4 character type suffix should be
|
|
175
|
+
omitted. So if you want the stream "__substg1.0_0001001F" then the
|
|
176
|
+
filename would simply be "__substg1.0_0001".
|
|
177
|
+
|
|
178
|
+
:raises ReferenceError: The associated ``MSGFile`` instance has been
|
|
179
|
+
garbage collected.
|
|
180
|
+
"""
|
|
181
|
+
if (msg := self.__msg()) is None:
|
|
182
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
183
|
+
return msg.getSingleOrMultipleString([self.__dir, msgPathToString(filename)])
|
|
184
|
+
|
|
185
|
+
def getStream(self, filename: MSG_PATH) -> Optional[bytes]:
|
|
186
|
+
"""
|
|
187
|
+
Gets a binary representation of the requested stream.
|
|
188
|
+
|
|
189
|
+
This should ALWAYS return a ``bytes`` object if it was found, otherwise
|
|
190
|
+
returns ``None``.
|
|
191
|
+
|
|
192
|
+
:raises ReferenceError: The associated ``MSGFile`` instance has been
|
|
193
|
+
garbage collected.
|
|
194
|
+
"""
|
|
195
|
+
if (msg := self.__msg()) is None:
|
|
196
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
197
|
+
return msg.getStream([self.__dir, msgPathToString(filename)])
|
|
198
|
+
|
|
199
|
+
def getStreamAs(self, streamID: MSG_PATH, overrideClass: OVERRIDE_CLASS[_T]) -> Optional[_T]:
|
|
200
|
+
"""
|
|
201
|
+
Returns the specified stream, modifying it to the specified class if it
|
|
202
|
+
is found.
|
|
203
|
+
|
|
204
|
+
:param overrideClass: Class/function to use to morph the data that was
|
|
205
|
+
read. The data will be the first argument to the class's
|
|
206
|
+
``__init__`` method or the function itself, if that is what is
|
|
207
|
+
provided. If the value is ``None``, this function is not called. If
|
|
208
|
+
you want it to be called regardless, you should handle the data
|
|
209
|
+
directly.
|
|
210
|
+
"""
|
|
211
|
+
value = self.getStream(streamID)
|
|
212
|
+
|
|
213
|
+
if value is not None:
|
|
214
|
+
value = overrideClass(value)
|
|
215
|
+
|
|
216
|
+
return value
|
|
217
|
+
|
|
218
|
+
def getStringStream(self, filename: MSG_PATH) -> Optional[str]:
|
|
219
|
+
"""
|
|
220
|
+
Gets a string representation of the requested stream.
|
|
221
|
+
|
|
222
|
+
Rather than the full filename, you should only feed this function the
|
|
223
|
+
filename sans the type. So if the full name is "__substg1.0_001A001F",
|
|
224
|
+
the filename this function should receive should be "__substg1.0_001A".
|
|
225
|
+
|
|
226
|
+
This should ALWAYS return a string if it was found, otherwise returns
|
|
227
|
+
None.
|
|
228
|
+
|
|
229
|
+
:raises ReferenceError: The associated ``MSGFile`` instance has been
|
|
230
|
+
garbage collected.
|
|
231
|
+
"""
|
|
232
|
+
if (msg := self.__msg()) is None:
|
|
233
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
234
|
+
return msg.getStringStream([self.__dir, msgPathToString(filename)])
|
|
235
|
+
|
|
236
|
+
def getStringStreamAs(self, streamID: MSG_PATH, overrideClass: OVERRIDE_CLASS[_T]) -> Optional[_T]:
|
|
237
|
+
"""
|
|
238
|
+
Returns the specified string stream, modifying it to the specified
|
|
239
|
+
class if it is found.
|
|
240
|
+
|
|
241
|
+
:param overrideClass: Class/function to use to morph the data that was
|
|
242
|
+
read. The data will be the first argument to the class's
|
|
243
|
+
``__init__`` method or the function itself, if that is what is
|
|
244
|
+
provided. If the value is ``None``, this function is not called. If
|
|
245
|
+
you want it to be called regardless, you should handle the data
|
|
246
|
+
directly.
|
|
247
|
+
"""
|
|
248
|
+
value = self.getStream(streamID)
|
|
249
|
+
|
|
250
|
+
if value is not None:
|
|
251
|
+
value = overrideClass(value)
|
|
252
|
+
|
|
253
|
+
return value
|
|
254
|
+
|
|
255
|
+
def listDir(self, streams: bool = True, storages: bool = False) -> List[List[str]]:
|
|
256
|
+
"""
|
|
257
|
+
Lists the streams and or storages that exist in the recipient directory.
|
|
258
|
+
|
|
259
|
+
:returns: The paths *excluding* the recipient directory, allowing the
|
|
260
|
+
paths to be directly used for accessing a file.
|
|
261
|
+
"""
|
|
262
|
+
if (msg := self.__msg()) is None:
|
|
263
|
+
raise ReferenceError('The MSGFile for this Recipient instance has been garbage collected.')
|
|
264
|
+
return [path[1:] for path in msg.listDir(streams, storages, False)
|
|
265
|
+
if len(path) > 1 and path[0] == self.__dir]
|
|
266
|
+
|
|
267
|
+
def slistDir(self, streams: bool = True, storages: bool = False) -> List[str]:
|
|
268
|
+
"""
|
|
269
|
+
Like :meth:`listDir`, except it returns the paths as strings.
|
|
270
|
+
"""
|
|
271
|
+
return ['/'.join(path) for path in self.listDir(streams, storages)]
|
|
272
|
+
|
|
273
|
+
@functools.cached_property
|
|
274
|
+
def account(self) -> Optional[str]:
|
|
275
|
+
"""
|
|
276
|
+
The account of this recipient.
|
|
277
|
+
"""
|
|
278
|
+
return self.getStringStream('__substg1.0_3A00')
|
|
279
|
+
|
|
280
|
+
@property
|
|
281
|
+
def email(self) -> Optional[str]:
|
|
282
|
+
"""
|
|
283
|
+
The recipient's email.
|
|
284
|
+
"""
|
|
285
|
+
return self.__email
|
|
286
|
+
|
|
287
|
+
@functools.cached_property
|
|
288
|
+
def entryID(self) -> Optional[PermanentEntryID]:
|
|
289
|
+
"""
|
|
290
|
+
The recipient's Entry ID.
|
|
291
|
+
"""
|
|
292
|
+
return self.getStreamAs('__substg1.0_0FFF0102', PermanentEntryID)
|
|
293
|
+
|
|
294
|
+
@property
|
|
295
|
+
def formatted(self) -> str:
|
|
296
|
+
"""
|
|
297
|
+
The formatted recipient string.
|
|
298
|
+
"""
|
|
299
|
+
return self.__formatted
|
|
300
|
+
|
|
301
|
+
@functools.cached_property
|
|
302
|
+
def instanceKey(self) -> Optional[bytes]:
|
|
303
|
+
"""
|
|
304
|
+
The instance key of this recipient.
|
|
305
|
+
"""
|
|
306
|
+
return self.getStream('__substg1.0_0FF60102')
|
|
307
|
+
|
|
308
|
+
@property
|
|
309
|
+
def name(self) -> Optional[str]:
|
|
310
|
+
"""
|
|
311
|
+
The recipient's name.
|
|
312
|
+
"""
|
|
313
|
+
return self.__name
|
|
314
|
+
|
|
315
|
+
@property
|
|
316
|
+
def props(self) -> PropertiesStore:
|
|
317
|
+
"""
|
|
318
|
+
The Properties instance of the recipient.
|
|
319
|
+
"""
|
|
320
|
+
return self.__props
|
|
321
|
+
|
|
322
|
+
@functools.cached_property
|
|
323
|
+
def recordKey(self) -> Optional[bytes]:
|
|
324
|
+
"""
|
|
325
|
+
The record key of this recipient.
|
|
326
|
+
"""
|
|
327
|
+
return self.getStream('__substg1.0_0FF90102')
|
|
328
|
+
|
|
329
|
+
@functools.cached_property
|
|
330
|
+
def searchKey(self) -> Optional[bytes]:
|
|
331
|
+
"""
|
|
332
|
+
The search key of this recipient.
|
|
333
|
+
"""
|
|
334
|
+
return self.getStream('__substg1.0_300B0102')
|
|
335
|
+
|
|
336
|
+
@functools.cached_property
|
|
337
|
+
def smtpAddress(self) -> Optional[str]:
|
|
338
|
+
"""
|
|
339
|
+
The SMTP address of this recipient.
|
|
340
|
+
"""
|
|
341
|
+
return self.getStringStream('__substg1.0_39FE')
|
|
342
|
+
|
|
343
|
+
@functools.cached_property
|
|
344
|
+
def transmittableDisplayName(self) -> Optional[str]:
|
|
345
|
+
"""
|
|
346
|
+
The transmittable display name of this recipient.
|
|
347
|
+
"""
|
|
348
|
+
return self.getStringStream('__substg1.0_3A20')
|
|
349
|
+
|
|
350
|
+
@property
|
|
351
|
+
def type(self) -> _RT:
|
|
352
|
+
"""
|
|
353
|
+
The recipient type.
|
|
354
|
+
"""
|
|
355
|
+
return self.__type
|
|
356
|
+
|
|
357
|
+
@property
|
|
358
|
+
def typeFlags(self) -> int:
|
|
359
|
+
"""
|
|
360
|
+
The raw recipient type value and all the flags it includes.
|
|
361
|
+
"""
|
|
362
|
+
return self.__typeFlags
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""
|
|
2
|
+
extract_msg.structures - Submodule to help with parsing data structures in MSG
|
|
3
|
+
files. Broken up by structure type.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
'_helpers',
|
|
8
|
+
'contact_link_entry',
|
|
9
|
+
'business_card',
|
|
10
|
+
'cfoas',
|
|
11
|
+
'contact_link_entry',
|
|
12
|
+
'dev_mode_a',
|
|
13
|
+
'dv_target_device',
|
|
14
|
+
'entry_id',
|
|
15
|
+
'misc_id',
|
|
16
|
+
'mon_stream',
|
|
17
|
+
'odt',
|
|
18
|
+
'ole_pres',
|
|
19
|
+
'ole_stream_struct',
|
|
20
|
+
'recurrence_pattern',
|
|
21
|
+
'report_tag',
|
|
22
|
+
'system_time',
|
|
23
|
+
'time_zone_definition',
|
|
24
|
+
'time_zone_struct',
|
|
25
|
+
'toc_entry',
|
|
26
|
+
'tz_rule',
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
from . import (
|
|
30
|
+
_helpers, business_card, cfoas, contact_link_entry, dev_mode_a,
|
|
31
|
+
dv_target_device, entry_id, misc_id, mon_stream, odt, ole_pres,
|
|
32
|
+
ole_stream_struct, recurrence_pattern, report_tag, system_time,
|
|
33
|
+
time_zone_definition, time_zone_struct, toc_entry, tz_rule
|
|
34
|
+
)
|