extract-msg 0.51.0__tar.gz → 0.52.0__tar.gz
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-0.51.0 → extract_msg-0.52.0}/CHANGELOG.md +9 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/PKG-INFO +3 -3
- {extract_msg-0.51.0 → extract_msg-0.52.0}/README.rst +2 -2
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/__init__.py +2 -2
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/constants/__init__.py +295 -294
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/message_base.py +1 -1
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/msg.py +1186 -1172
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/ole_writer.py +1109 -1086
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/PKG-INFO +3 -3
- {extract_msg-0.51.0 → extract_msg-0.52.0}/LICENSE.txt +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/MANIFEST.in +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/__main__.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/__init__.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/create_doc.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/inject_rtf.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/token.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/tokenize_rtf.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/__init__.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/attachment.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/attachment_base.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/broken_att.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/__init__.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/custom_handler.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/lnk_obj_att.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/outlook_image_dib.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/outlook_image_meta.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/emb_msg_att.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/signed_att.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/unsupported_att.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/web_att.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/constants/ps.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/constants/re.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/constants/st.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/data/logging-config/logging-nt.json +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/data/logging-config/logging-posix.json +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/__init__.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/__init__.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_ce.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_cyrillic.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_greek.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_iceland.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_turkish.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_win874_dec.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_win950_dec.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/utils.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/enums.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/exceptions.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/__init__.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/appointment.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/calendar.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/calendar_base.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/contact.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/journal.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_cancellation.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_exception.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_forward.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_related.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_request.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_response.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/message.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/message_signed.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/message_signed_base.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/post.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/sticky_note.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/task.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/task_request.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/null_date.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/open_msg.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/properties/__init__.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/properties/named.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/properties/prop.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/properties/properties_store.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/py.typed +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/recipient.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/__init__.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/_helpers.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/business_card.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/cfoas.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/contact_link_entry.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/dev_mode_a.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/dv_target_device.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/entry_id.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/misc_id.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/mon_stream.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/odt.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/ole_pres.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/ole_stream_struct.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/recurrence_pattern.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/report_tag.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/system_time.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/time_zone_definition.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/time_zone_struct.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/toc_entry.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/tz_rule.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/utils.py +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/SOURCES.txt +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/dependency_links.txt +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/entry_points.txt +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/requires.txt +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/top_level.txt +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/requirements.txt +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/setup.cfg +0 -0
- {extract_msg-0.51.0 → extract_msg-0.52.0}/setup.py +0 -0
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
**v0.52.0**
|
|
2
|
+
* [[TeamMsgExtractor #444](https://github.com/TeamMsgExtractor/msg-extractor/issues/444)] Fix typo in string that prevented HTML body from generating from the plain text body properly.
|
|
3
|
+
* Adjusted the behavior of `MSGFile.areStringsUnicode` to prioritize the property specified by the parent MSG files for MSG files that are embedded. Additionally, added a fallback to rely on whether or not there is a stream using the `001F` type to determine the property value if it is entirely missing.
|
|
4
|
+
* Adjusted `OleWriter.fromMsg()` and `MSGFile.export()` to add the argument `allowBadEmbed` which helps to correct a few different issues that may appear in embedded MSG files. These corrections allow the embedded file to still be extracted and to open properly in Outlook.
|
|
5
|
+
* In addition to the above, the errors that some of those corrections will suppress are now significantly more informative about what went wrong.
|
|
6
|
+
|
|
7
|
+
**v0.51.1**
|
|
8
|
+
* Add class type added in last version to known class types.
|
|
9
|
+
|
|
1
10
|
**v0.51.0**
|
|
2
11
|
* [[TeamMsgExtractor #401](https://github.com/TeamMsgExtractor/msg-extractor/issues/401)] Add basic support for MSG class type `IPM.SkypeTeams.Message`.
|
|
3
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: extract_msg
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.52.0
|
|
4
4
|
Summary: Extracts emails and attachments saved in Microsoft Outlook's .msg files
|
|
5
5
|
Home-page: https://github.com/TeamMsgExtractor/msg-extractor
|
|
6
6
|
Download-URL: https://github.com/TeamMsgExtractor/msg-extractor/archives/master
|
|
@@ -278,8 +278,8 @@ your access to the newest major version of extract-msg.
|
|
|
278
278
|
.. |License: GPL v3| image:: https://img.shields.io/badge/License-GPLv3-blue.svg
|
|
279
279
|
:target: LICENSE.txt
|
|
280
280
|
|
|
281
|
-
.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.
|
|
282
|
-
:target: https://pypi.org/project/extract-msg/0.
|
|
281
|
+
.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.52.0-blue.svg
|
|
282
|
+
:target: https://pypi.org/project/extract-msg/0.52.0/
|
|
283
283
|
|
|
284
284
|
.. |PyPI2| image:: https://img.shields.io/badge/python-3.8+-brightgreen.svg
|
|
285
285
|
:target: https://www.python.org/downloads/release/python-3810/
|
|
@@ -260,8 +260,8 @@ your access to the newest major version of extract-msg.
|
|
|
260
260
|
.. |License: GPL v3| image:: https://img.shields.io/badge/License-GPLv3-blue.svg
|
|
261
261
|
:target: LICENSE.txt
|
|
262
262
|
|
|
263
|
-
.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.
|
|
264
|
-
:target: https://pypi.org/project/extract-msg/0.
|
|
263
|
+
.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.52.0-blue.svg
|
|
264
|
+
:target: https://pypi.org/project/extract-msg/0.52.0/
|
|
265
265
|
|
|
266
266
|
.. |PyPI2| image:: https://img.shields.io/badge/python-3.8+-brightgreen.svg
|
|
267
267
|
:target: https://www.python.org/downloads/release/python-3810/
|
|
@@ -27,8 +27,8 @@ https://github.com/TeamMsgExtractor/msg-extractor
|
|
|
27
27
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
28
28
|
|
|
29
29
|
__author__ = 'Destiny Peterson & Matthew Walker'
|
|
30
|
-
__date__ = '2024-10-
|
|
31
|
-
__version__ = '0.
|
|
30
|
+
__date__ = '2024-10-22'
|
|
31
|
+
__version__ = '0.52.0'
|
|
32
32
|
|
|
33
33
|
__all__ = [
|
|
34
34
|
# Modules:
|
|
@@ -1,294 +1,295 @@
|
|
|
1
|
-
"""
|
|
2
|
-
The constants used in extract_msg. If you modify any of these without explicit
|
|
3
|
-
instruction to do so from one of the contributers, please do not complain about
|
|
4
|
-
bugs.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
__all__ = [
|
|
8
|
-
# Modules.
|
|
9
|
-
'ps',
|
|
10
|
-
're',
|
|
11
|
-
'st',
|
|
12
|
-
|
|
13
|
-
# Constants.
|
|
14
|
-
'DATE_FORMAT',
|
|
15
|
-
'DEFAULT_CLSID',
|
|
16
|
-
'DT_FORMAT',
|
|
17
|
-
'FIXED_LENGTH_PROPS',
|
|
18
|
-
'FIXED_LENGTH_PROPS_STRING',
|
|
19
|
-
'HEADER_FORMAT',
|
|
20
|
-
'HEADER_FORMAT_TYPE',
|
|
21
|
-
'HEADER_FORMAT_VALUE_TYPE',
|
|
22
|
-
'KNOWN_CLASS_TYPES',
|
|
23
|
-
'KNOWN_FILE_FLAGS',
|
|
24
|
-
'MAINDOC',
|
|
25
|
-
'MSG_PATH',
|
|
26
|
-
'MULTIPLE_16_BYTES',
|
|
27
|
-
'MULTIPLE_16_BYTES_HEX',
|
|
28
|
-
'MULTIPLE_2_BYTES',
|
|
29
|
-
'MULTIPLE_2_BYTES_HEX',
|
|
30
|
-
'MULTIPLE_4_BYTES',
|
|
31
|
-
'MULTIPLE_4_BYTES_HEX',
|
|
32
|
-
'MULTIPLE_8_BYTES',
|
|
33
|
-
'MULTIPLE_8_BYTES_HEX',
|
|
34
|
-
'NEEDS_ARG',
|
|
35
|
-
'NULL_DATE',
|
|
36
|
-
'PTYPES',
|
|
37
|
-
'PYTPFLOATINGTIME_START',
|
|
38
|
-
'REFUSED_CLASS_TYPES',
|
|
39
|
-
'REPOSITORY_URL',
|
|
40
|
-
'SAVE_TYPE',
|
|
41
|
-
'VARIABLE_LENGTH_PROPS',
|
|
42
|
-
'VARIABLE_LENGTH_PROPS_STRING',
|
|
43
|
-
]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
from datetime import datetime
|
|
47
|
-
from typing import (
|
|
48
|
-
Any, Callable, Dict, Final, List, Optional, Tuple, Type, TypeVar, Union
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
from . import ps, re, st
|
|
52
|
-
from ..enums import SaveType
|
|
53
|
-
from ..null_date import NullDate
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
_T = TypeVar('_T')
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
# Constants for formating datetime objects.
|
|
60
|
-
DATE_FORMAT: Final[str] = '%d %B, %Y'
|
|
61
|
-
DT_FORMAT: Final[str] = '%a, %d %b %Y %H:%M:%S %z'
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# Typing Constants.
|
|
65
|
-
HEADER_FORMAT_VALUE_TYPE = Union[str, Tuple[Union[str, None], bool], None]
|
|
66
|
-
# Basically a dict of HEADER_FORMAT_TYPE and dicts containing them.
|
|
67
|
-
HEADER_FORMAT_TYPE = Optional[Dict[str, Union[HEADER_FORMAT_VALUE_TYPE, Dict[str, HEADER_FORMAT_VALUE_TYPE]]]]
|
|
68
|
-
SAVE_TYPE = Tuple[SaveType, Union[List[str], str, None]]
|
|
69
|
-
MSG_PATH = Union[str, List[str], Tuple[str]]
|
|
70
|
-
# Type used for the getXAs methods' overrideClass argument.
|
|
71
|
-
OVERRIDE_CLASS = Union[Type[_T], Callable[[Any], _T]]
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
FIXED_LENGTH_PROPS: Final[Tuple[int, ...]] = (
|
|
75
|
-
0x0000,
|
|
76
|
-
0x0001,
|
|
77
|
-
0x0002,
|
|
78
|
-
0x0003,
|
|
79
|
-
0x0004,
|
|
80
|
-
0x0005,
|
|
81
|
-
0x0006,
|
|
82
|
-
0x0007,
|
|
83
|
-
0x000A,
|
|
84
|
-
0x000B,
|
|
85
|
-
0x0014,
|
|
86
|
-
0x0040,
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
FIXED_LENGTH_PROPS_STRING: Final[Tuple[str, ...]] = (
|
|
90
|
-
'0000',
|
|
91
|
-
'0001',
|
|
92
|
-
'0002',
|
|
93
|
-
'0003',
|
|
94
|
-
'0004',
|
|
95
|
-
'0005',
|
|
96
|
-
'0006',
|
|
97
|
-
'0007',
|
|
98
|
-
'000A',
|
|
99
|
-
'000B',
|
|
100
|
-
'0014',
|
|
101
|
-
'0040',
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
VARIABLE_LENGTH_PROPS: Final[Tuple[int, ...]] = (
|
|
105
|
-
0x000D,
|
|
106
|
-
0x001E,
|
|
107
|
-
0x001F,
|
|
108
|
-
0x0048,
|
|
109
|
-
0x00FB,
|
|
110
|
-
0x00FD,
|
|
111
|
-
0x00FE,
|
|
112
|
-
0X0102,
|
|
113
|
-
0x1002,
|
|
114
|
-
0x1003,
|
|
115
|
-
0x1004,
|
|
116
|
-
0x1005,
|
|
117
|
-
0x1006,
|
|
118
|
-
0x1007,
|
|
119
|
-
0x1014,
|
|
120
|
-
0x101E,
|
|
121
|
-
0x101F,
|
|
122
|
-
0x1040,
|
|
123
|
-
0x1048,
|
|
124
|
-
0x1102,
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
VARIABLE_LENGTH_PROPS_STRING: Final[Tuple[str, ...]] = (
|
|
128
|
-
'000D',
|
|
129
|
-
'001E',
|
|
130
|
-
'001F',
|
|
131
|
-
'0048',
|
|
132
|
-
'00FB',
|
|
133
|
-
'00FD',
|
|
134
|
-
'00FE',
|
|
135
|
-
'0102',
|
|
136
|
-
'1002',
|
|
137
|
-
'1003',
|
|
138
|
-
'1004',
|
|
139
|
-
'1005',
|
|
140
|
-
'1006',
|
|
141
|
-
'1007',
|
|
142
|
-
'1014',
|
|
143
|
-
'101E',
|
|
144
|
-
'101F',
|
|
145
|
-
'1040',
|
|
146
|
-
'1048',
|
|
147
|
-
'1102',
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
# Multiple type properties that take up 2 bytes.
|
|
151
|
-
MULTIPLE_2_BYTES: Final[Tuple[str, ...]] = (
|
|
152
|
-
'1002',
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
MULTIPLE_2_BYTES_HEX: Final[Tuple[int, ...]] = (
|
|
156
|
-
0x1002,
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
# Multiple type properties that take up 4 bytes.
|
|
160
|
-
MULTIPLE_4_BYTES: Final[Tuple[str, ...]] = (
|
|
161
|
-
'1003',
|
|
162
|
-
'1004',
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
MULTIPLE_4_BYTES_HEX: Final[Tuple[int, ...]] = (
|
|
166
|
-
0x1003,
|
|
167
|
-
0x1004,
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
# Multiple type properties that take up 8 bytes.
|
|
171
|
-
MULTIPLE_8_BYTES: Final[Tuple[str, ...]] = (
|
|
172
|
-
'1005',
|
|
173
|
-
'1006',
|
|
174
|
-
'1007',
|
|
175
|
-
'1014',
|
|
176
|
-
'1040',
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
MULTIPLE_8_BYTES_HEX: Final[Tuple[int, ...]] = (
|
|
180
|
-
0x1005,
|
|
181
|
-
0x1006,
|
|
182
|
-
0x1007,
|
|
183
|
-
0x1014,
|
|
184
|
-
0x1040,
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
# Multiple type properties that take up 16 bytes.
|
|
188
|
-
MULTIPLE_16_BYTES: Final[Tuple[str, ...]] = (
|
|
189
|
-
'1048',
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
MULTIPLE_16_BYTES_HEX: Final[Tuple[int, ...]] = (
|
|
193
|
-
0x1048,
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
# Used to format the header for saving only the header.
|
|
198
|
-
HEADER_FORMAT: Final[str] = """From: {From}
|
|
199
|
-
To: {To}
|
|
200
|
-
Cc: {Cc}
|
|
201
|
-
Bcc: {Bcc}
|
|
202
|
-
Subject: {subject}
|
|
203
|
-
Date: {Date}
|
|
204
|
-
Message-ID: {Message-Id}
|
|
205
|
-
"""
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
KNOWN_CLASS_TYPES: Final[Tuple[str, ...]] = (
|
|
209
|
-
'ipm.activity',
|
|
210
|
-
'ipm.appointment', # [MS-OXOCAL]
|
|
211
|
-
'ipm.contact', # [MS-OXOCNTC]
|
|
212
|
-
'ipm.configuration', # [MS-OXOCFG]
|
|
213
|
-
'ipm.distlist',
|
|
214
|
-
'ipm.document',
|
|
215
|
-
'ipm.ole.class',
|
|
216
|
-
'ipm.outlook.recall',
|
|
217
|
-
'ipm.note',
|
|
218
|
-
'ipm.post',
|
|
219
|
-
'ipm.stickynote',
|
|
220
|
-
'ipm.recall.report',
|
|
221
|
-
'ipm.remote',
|
|
222
|
-
'ipm.report',
|
|
223
|
-
'ipm.resend',
|
|
224
|
-
'ipm.schedule',
|
|
225
|
-
'ipm.
|
|
226
|
-
'ipm.
|
|
227
|
-
'
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
#
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
_tmp
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
#
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
1
|
+
"""
|
|
2
|
+
The constants used in extract_msg. If you modify any of these without explicit
|
|
3
|
+
instruction to do so from one of the contributers, please do not complain about
|
|
4
|
+
bugs.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
# Modules.
|
|
9
|
+
'ps',
|
|
10
|
+
're',
|
|
11
|
+
'st',
|
|
12
|
+
|
|
13
|
+
# Constants.
|
|
14
|
+
'DATE_FORMAT',
|
|
15
|
+
'DEFAULT_CLSID',
|
|
16
|
+
'DT_FORMAT',
|
|
17
|
+
'FIXED_LENGTH_PROPS',
|
|
18
|
+
'FIXED_LENGTH_PROPS_STRING',
|
|
19
|
+
'HEADER_FORMAT',
|
|
20
|
+
'HEADER_FORMAT_TYPE',
|
|
21
|
+
'HEADER_FORMAT_VALUE_TYPE',
|
|
22
|
+
'KNOWN_CLASS_TYPES',
|
|
23
|
+
'KNOWN_FILE_FLAGS',
|
|
24
|
+
'MAINDOC',
|
|
25
|
+
'MSG_PATH',
|
|
26
|
+
'MULTIPLE_16_BYTES',
|
|
27
|
+
'MULTIPLE_16_BYTES_HEX',
|
|
28
|
+
'MULTIPLE_2_BYTES',
|
|
29
|
+
'MULTIPLE_2_BYTES_HEX',
|
|
30
|
+
'MULTIPLE_4_BYTES',
|
|
31
|
+
'MULTIPLE_4_BYTES_HEX',
|
|
32
|
+
'MULTIPLE_8_BYTES',
|
|
33
|
+
'MULTIPLE_8_BYTES_HEX',
|
|
34
|
+
'NEEDS_ARG',
|
|
35
|
+
'NULL_DATE',
|
|
36
|
+
'PTYPES',
|
|
37
|
+
'PYTPFLOATINGTIME_START',
|
|
38
|
+
'REFUSED_CLASS_TYPES',
|
|
39
|
+
'REPOSITORY_URL',
|
|
40
|
+
'SAVE_TYPE',
|
|
41
|
+
'VARIABLE_LENGTH_PROPS',
|
|
42
|
+
'VARIABLE_LENGTH_PROPS_STRING',
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
from datetime import datetime
|
|
47
|
+
from typing import (
|
|
48
|
+
Any, Callable, Dict, Final, List, Optional, Tuple, Type, TypeVar, Union
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
from . import ps, re, st
|
|
52
|
+
from ..enums import SaveType
|
|
53
|
+
from ..null_date import NullDate
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
_T = TypeVar('_T')
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# Constants for formating datetime objects.
|
|
60
|
+
DATE_FORMAT: Final[str] = '%d %B, %Y'
|
|
61
|
+
DT_FORMAT: Final[str] = '%a, %d %b %Y %H:%M:%S %z'
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# Typing Constants.
|
|
65
|
+
HEADER_FORMAT_VALUE_TYPE = Union[str, Tuple[Union[str, None], bool], None]
|
|
66
|
+
# Basically a dict of HEADER_FORMAT_TYPE and dicts containing them.
|
|
67
|
+
HEADER_FORMAT_TYPE = Optional[Dict[str, Union[HEADER_FORMAT_VALUE_TYPE, Dict[str, HEADER_FORMAT_VALUE_TYPE]]]]
|
|
68
|
+
SAVE_TYPE = Tuple[SaveType, Union[List[str], str, None]]
|
|
69
|
+
MSG_PATH = Union[str, List[str], Tuple[str]]
|
|
70
|
+
# Type used for the getXAs methods' overrideClass argument.
|
|
71
|
+
OVERRIDE_CLASS = Union[Type[_T], Callable[[Any], _T]]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
FIXED_LENGTH_PROPS: Final[Tuple[int, ...]] = (
|
|
75
|
+
0x0000,
|
|
76
|
+
0x0001,
|
|
77
|
+
0x0002,
|
|
78
|
+
0x0003,
|
|
79
|
+
0x0004,
|
|
80
|
+
0x0005,
|
|
81
|
+
0x0006,
|
|
82
|
+
0x0007,
|
|
83
|
+
0x000A,
|
|
84
|
+
0x000B,
|
|
85
|
+
0x0014,
|
|
86
|
+
0x0040,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
FIXED_LENGTH_PROPS_STRING: Final[Tuple[str, ...]] = (
|
|
90
|
+
'0000',
|
|
91
|
+
'0001',
|
|
92
|
+
'0002',
|
|
93
|
+
'0003',
|
|
94
|
+
'0004',
|
|
95
|
+
'0005',
|
|
96
|
+
'0006',
|
|
97
|
+
'0007',
|
|
98
|
+
'000A',
|
|
99
|
+
'000B',
|
|
100
|
+
'0014',
|
|
101
|
+
'0040',
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
VARIABLE_LENGTH_PROPS: Final[Tuple[int, ...]] = (
|
|
105
|
+
0x000D,
|
|
106
|
+
0x001E,
|
|
107
|
+
0x001F,
|
|
108
|
+
0x0048,
|
|
109
|
+
0x00FB,
|
|
110
|
+
0x00FD,
|
|
111
|
+
0x00FE,
|
|
112
|
+
0X0102,
|
|
113
|
+
0x1002,
|
|
114
|
+
0x1003,
|
|
115
|
+
0x1004,
|
|
116
|
+
0x1005,
|
|
117
|
+
0x1006,
|
|
118
|
+
0x1007,
|
|
119
|
+
0x1014,
|
|
120
|
+
0x101E,
|
|
121
|
+
0x101F,
|
|
122
|
+
0x1040,
|
|
123
|
+
0x1048,
|
|
124
|
+
0x1102,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
VARIABLE_LENGTH_PROPS_STRING: Final[Tuple[str, ...]] = (
|
|
128
|
+
'000D',
|
|
129
|
+
'001E',
|
|
130
|
+
'001F',
|
|
131
|
+
'0048',
|
|
132
|
+
'00FB',
|
|
133
|
+
'00FD',
|
|
134
|
+
'00FE',
|
|
135
|
+
'0102',
|
|
136
|
+
'1002',
|
|
137
|
+
'1003',
|
|
138
|
+
'1004',
|
|
139
|
+
'1005',
|
|
140
|
+
'1006',
|
|
141
|
+
'1007',
|
|
142
|
+
'1014',
|
|
143
|
+
'101E',
|
|
144
|
+
'101F',
|
|
145
|
+
'1040',
|
|
146
|
+
'1048',
|
|
147
|
+
'1102',
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# Multiple type properties that take up 2 bytes.
|
|
151
|
+
MULTIPLE_2_BYTES: Final[Tuple[str, ...]] = (
|
|
152
|
+
'1002',
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
MULTIPLE_2_BYTES_HEX: Final[Tuple[int, ...]] = (
|
|
156
|
+
0x1002,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Multiple type properties that take up 4 bytes.
|
|
160
|
+
MULTIPLE_4_BYTES: Final[Tuple[str, ...]] = (
|
|
161
|
+
'1003',
|
|
162
|
+
'1004',
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
MULTIPLE_4_BYTES_HEX: Final[Tuple[int, ...]] = (
|
|
166
|
+
0x1003,
|
|
167
|
+
0x1004,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Multiple type properties that take up 8 bytes.
|
|
171
|
+
MULTIPLE_8_BYTES: Final[Tuple[str, ...]] = (
|
|
172
|
+
'1005',
|
|
173
|
+
'1006',
|
|
174
|
+
'1007',
|
|
175
|
+
'1014',
|
|
176
|
+
'1040',
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
MULTIPLE_8_BYTES_HEX: Final[Tuple[int, ...]] = (
|
|
180
|
+
0x1005,
|
|
181
|
+
0x1006,
|
|
182
|
+
0x1007,
|
|
183
|
+
0x1014,
|
|
184
|
+
0x1040,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Multiple type properties that take up 16 bytes.
|
|
188
|
+
MULTIPLE_16_BYTES: Final[Tuple[str, ...]] = (
|
|
189
|
+
'1048',
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
MULTIPLE_16_BYTES_HEX: Final[Tuple[int, ...]] = (
|
|
193
|
+
0x1048,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
# Used to format the header for saving only the header.
|
|
198
|
+
HEADER_FORMAT: Final[str] = """From: {From}
|
|
199
|
+
To: {To}
|
|
200
|
+
Cc: {Cc}
|
|
201
|
+
Bcc: {Bcc}
|
|
202
|
+
Subject: {subject}
|
|
203
|
+
Date: {Date}
|
|
204
|
+
Message-ID: {Message-Id}
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
KNOWN_CLASS_TYPES: Final[Tuple[str, ...]] = (
|
|
209
|
+
'ipm.activity',
|
|
210
|
+
'ipm.appointment', # [MS-OXOCAL]
|
|
211
|
+
'ipm.contact', # [MS-OXOCNTC]
|
|
212
|
+
'ipm.configuration', # [MS-OXOCFG]
|
|
213
|
+
'ipm.distlist',
|
|
214
|
+
'ipm.document',
|
|
215
|
+
'ipm.ole.class',
|
|
216
|
+
'ipm.outlook.recall',
|
|
217
|
+
'ipm.note',
|
|
218
|
+
'ipm.post',
|
|
219
|
+
'ipm.stickynote',
|
|
220
|
+
'ipm.recall.report',
|
|
221
|
+
'ipm.remote',
|
|
222
|
+
'ipm.report',
|
|
223
|
+
'ipm.resend',
|
|
224
|
+
'ipm.schedule',
|
|
225
|
+
'ipm.skypeteams.message'
|
|
226
|
+
'ipm.task',
|
|
227
|
+
'ipm.taskrequest',
|
|
228
|
+
'report',
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
# Each item is a tuple of the lowercase class type and the issue number
|
|
232
|
+
# associated with it.
|
|
233
|
+
REFUSED_CLASS_TYPES: Final[Tuple[Tuple[str, str], ...]] = (
|
|
234
|
+
('ipm.outlook.recall', '235'),
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
PYTPFLOATINGTIME_START: Final[datetime] = datetime(1899, 12, 30)
|
|
238
|
+
# Do modifications before assigning to the constant.
|
|
239
|
+
_tmp = NullDate(4500, 8, 31, 23, 59)
|
|
240
|
+
_tmp.filetime = 915046235400000000
|
|
241
|
+
NULL_DATE: Final[NullDate] = _tmp
|
|
242
|
+
|
|
243
|
+
# Constants used for argparse stuff.
|
|
244
|
+
KNOWN_FILE_FLAGS: Final[Tuple[str, ...]] = (
|
|
245
|
+
'--out-name',
|
|
246
|
+
)
|
|
247
|
+
NEEDS_ARG: Final[Tuple[str, ...]]= (
|
|
248
|
+
'--out-name',
|
|
249
|
+
)
|
|
250
|
+
REPOSITORY_URL: Final[str] = 'https://github.com/TeamMsgExtractor/msg-extractor'
|
|
251
|
+
MAINDOC: Final[str] = f"""extract_msg:
|
|
252
|
+
\tExtracts emails and attachments saved in Microsoft Outlook's .msg files.
|
|
253
|
+
|
|
254
|
+
{REPOSITORY_URL}"""
|
|
255
|
+
|
|
256
|
+
# Default class ID for the root entry for OleWriter. This should be
|
|
257
|
+
# referencing Outlook if I understand it correctly.
|
|
258
|
+
DEFAULT_CLSID: Final[bytes] = b'\x0b\r\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00F'
|
|
259
|
+
|
|
260
|
+
PTYPES: Final[Dict[int, str]]= {
|
|
261
|
+
0x0000: 'PtypUnspecified',
|
|
262
|
+
0x0001: 'PtypNull',
|
|
263
|
+
0x0002: 'PtypInteger16', # Signed short.
|
|
264
|
+
0x0003: 'PtypInteger32', # Signed int.
|
|
265
|
+
0x0004: 'PtypFloating32', # Float.
|
|
266
|
+
0x0005: 'PtypFloating64', # Double.
|
|
267
|
+
0x0006: 'PtypCurrency',
|
|
268
|
+
0x0007: 'PtypFloatingTime',
|
|
269
|
+
0x000A: 'PtypErrorCode',
|
|
270
|
+
0x000B: 'PtypBoolean',
|
|
271
|
+
0x000D: 'PtypObject/PtypEmbeddedTable/Storage',
|
|
272
|
+
0x0014: 'PtypInteger64', # Signed longlong.
|
|
273
|
+
0x001E: 'PtypString8',
|
|
274
|
+
0x001F: 'PtypString',
|
|
275
|
+
0x0040: 'PtypTime', # Use filetimeToUtc to convert to unix time stamp.
|
|
276
|
+
0x0048: 'PtypGuid',
|
|
277
|
+
0x00FB: 'PtypServerId',
|
|
278
|
+
0x00FD: 'PtypRestriction',
|
|
279
|
+
0x00FE: 'PtypRuleAction',
|
|
280
|
+
0x0102: 'PtypBinary',
|
|
281
|
+
0x1002: 'PtypMultipleInteger16',
|
|
282
|
+
0x1003: 'PtypMultipleInteger32',
|
|
283
|
+
0x1004: 'PtypMultipleFloating32',
|
|
284
|
+
0x1005: 'PtypMultipleFloating64',
|
|
285
|
+
0x1006: 'PtypMultipleCurrency',
|
|
286
|
+
0x1007: 'PtypMultipleFloatingTime',
|
|
287
|
+
0x1014: 'PtypMultipleInteger64',
|
|
288
|
+
0x101E: 'PtypMultipleString8',
|
|
289
|
+
0x101F: 'PtypMultipleString',
|
|
290
|
+
0x1040: 'PtypMultipleTime',
|
|
291
|
+
0x1048: 'PtypMultipleGuid',
|
|
292
|
+
0x1102: 'PtypMultipleBinary',
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
# END CONSTANTS.
|
|
@@ -1170,7 +1170,7 @@ class MessageBase(MSGFile):
|
|
|
1170
1170
|
# Convert the plain text body to html.
|
|
1171
1171
|
logger.info('HTML body was not found, attempting to generate from plain text body.')
|
|
1172
1172
|
correctedBody = html.escape(self.body).replace('\r', '').replace('\n', '<br />')
|
|
1173
|
-
htmlBody = f'<html><body>{correctedBody}</body></head>'.encode('ascii', '
|
|
1173
|
+
htmlBody = f'<html><body>{correctedBody}</body></head>'.encode('ascii', 'xmlcharrefreplace')
|
|
1174
1174
|
|
|
1175
1175
|
if not htmlBody:
|
|
1176
1176
|
logger.info('HTML body could not be found nor generated.')
|