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.
Files changed (104) hide show
  1. {extract_msg-0.51.0 → extract_msg-0.52.0}/CHANGELOG.md +9 -0
  2. {extract_msg-0.51.0 → extract_msg-0.52.0}/PKG-INFO +3 -3
  3. {extract_msg-0.51.0 → extract_msg-0.52.0}/README.rst +2 -2
  4. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/__init__.py +2 -2
  5. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/constants/__init__.py +295 -294
  6. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/message_base.py +1 -1
  7. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/msg.py +1186 -1172
  8. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/ole_writer.py +1109 -1086
  9. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/PKG-INFO +3 -3
  10. {extract_msg-0.51.0 → extract_msg-0.52.0}/LICENSE.txt +0 -0
  11. {extract_msg-0.51.0 → extract_msg-0.52.0}/MANIFEST.in +0 -0
  12. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/__main__.py +0 -0
  13. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/__init__.py +0 -0
  14. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/create_doc.py +0 -0
  15. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/inject_rtf.py +0 -0
  16. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/token.py +0 -0
  17. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/_rtf/tokenize_rtf.py +0 -0
  18. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/__init__.py +0 -0
  19. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/attachment.py +0 -0
  20. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/attachment_base.py +0 -0
  21. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/broken_att.py +0 -0
  22. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att.py +0 -0
  23. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/__init__.py +0 -0
  24. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/custom_handler.py +0 -0
  25. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/lnk_obj_att.py +0 -0
  26. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/outlook_image_dib.py +0 -0
  27. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/custom_att_handler/outlook_image_meta.py +0 -0
  28. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/emb_msg_att.py +0 -0
  29. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/signed_att.py +0 -0
  30. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/unsupported_att.py +0 -0
  31. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/attachments/web_att.py +0 -0
  32. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/constants/ps.py +0 -0
  33. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/constants/re.py +0 -0
  34. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/constants/st.py +0 -0
  35. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/data/logging-config/logging-nt.json +0 -0
  36. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/data/logging-config/logging-posix.json +0 -0
  37. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/__init__.py +0 -0
  38. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/__init__.py +0 -0
  39. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_ce.py +0 -0
  40. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_cyrillic.py +0 -0
  41. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_greek.py +0 -0
  42. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_iceland.py +0 -0
  43. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_mac_turkish.py +0 -0
  44. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_win874_dec.py +0 -0
  45. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/_dt/_win950_dec.py +0 -0
  46. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/encoding/utils.py +0 -0
  47. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/enums.py +0 -0
  48. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/exceptions.py +0 -0
  49. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/__init__.py +0 -0
  50. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/appointment.py +0 -0
  51. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/calendar.py +0 -0
  52. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/calendar_base.py +0 -0
  53. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/contact.py +0 -0
  54. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/journal.py +0 -0
  55. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_cancellation.py +0 -0
  56. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_exception.py +0 -0
  57. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_forward.py +0 -0
  58. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_related.py +0 -0
  59. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_request.py +0 -0
  60. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/meeting_response.py +0 -0
  61. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/message.py +0 -0
  62. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/message_signed.py +0 -0
  63. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/message_signed_base.py +0 -0
  64. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/post.py +0 -0
  65. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/sticky_note.py +0 -0
  66. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/task.py +0 -0
  67. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/msg_classes/task_request.py +0 -0
  68. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/null_date.py +0 -0
  69. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/open_msg.py +0 -0
  70. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/properties/__init__.py +0 -0
  71. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/properties/named.py +0 -0
  72. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/properties/prop.py +0 -0
  73. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/properties/properties_store.py +0 -0
  74. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/py.typed +0 -0
  75. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/recipient.py +0 -0
  76. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/__init__.py +0 -0
  77. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/_helpers.py +0 -0
  78. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/business_card.py +0 -0
  79. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/cfoas.py +0 -0
  80. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/contact_link_entry.py +0 -0
  81. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/dev_mode_a.py +0 -0
  82. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/dv_target_device.py +0 -0
  83. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/entry_id.py +0 -0
  84. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/misc_id.py +0 -0
  85. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/mon_stream.py +0 -0
  86. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/odt.py +0 -0
  87. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/ole_pres.py +0 -0
  88. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/ole_stream_struct.py +0 -0
  89. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/recurrence_pattern.py +0 -0
  90. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/report_tag.py +0 -0
  91. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/system_time.py +0 -0
  92. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/time_zone_definition.py +0 -0
  93. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/time_zone_struct.py +0 -0
  94. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/toc_entry.py +0 -0
  95. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/structures/tz_rule.py +0 -0
  96. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg/utils.py +0 -0
  97. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/SOURCES.txt +0 -0
  98. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/dependency_links.txt +0 -0
  99. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/entry_points.txt +0 -0
  100. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/requires.txt +0 -0
  101. {extract_msg-0.51.0 → extract_msg-0.52.0}/extract_msg.egg-info/top_level.txt +0 -0
  102. {extract_msg-0.51.0 → extract_msg-0.52.0}/requirements.txt +0 -0
  103. {extract_msg-0.51.0 → extract_msg-0.52.0}/setup.cfg +0 -0
  104. {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.51.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.51.0-blue.svg
282
- :target: https://pypi.org/project/extract-msg/0.51.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.51.0-blue.svg
264
- :target: https://pypi.org/project/extract-msg/0.51.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-11'
31
- __version__ = '0.51.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.task',
226
- 'ipm.taskrequest',
227
- 'report',
228
- )
229
-
230
- # Each item is a tuple of the lowercase class type and the issue number
231
- # associated with it.
232
- REFUSED_CLASS_TYPES: Final[Tuple[Tuple[str, str], ...]] = (
233
- ('ipm.outlook.recall', '235'),
234
- )
235
-
236
- PYTPFLOATINGTIME_START: Final[datetime] = datetime(1899, 12, 30)
237
- # Do modifications before assigning to the constant.
238
- _tmp = NullDate(4500, 8, 31, 23, 59)
239
- _tmp.filetime = 915046235400000000
240
- NULL_DATE: Final[NullDate] = _tmp
241
-
242
- # Constants used for argparse stuff.
243
- KNOWN_FILE_FLAGS: Final[Tuple[str, ...]] = (
244
- '--out-name',
245
- )
246
- NEEDS_ARG: Final[Tuple[str, ...]]= (
247
- '--out-name',
248
- )
249
- REPOSITORY_URL: Final[str] = 'https://github.com/TeamMsgExtractor/msg-extractor'
250
- MAINDOC: Final[str] = f"""extract_msg:
251
- \tExtracts emails and attachments saved in Microsoft Outlook's .msg files.
252
-
253
- {REPOSITORY_URL}"""
254
-
255
- # Default class ID for the root entry for OleWriter. This should be
256
- # referencing Outlook if I understand it correctly.
257
- DEFAULT_CLSID: Final[bytes] = b'\x0b\r\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00F'
258
-
259
- PTYPES: Final[Dict[int, str]]= {
260
- 0x0000: 'PtypUnspecified',
261
- 0x0001: 'PtypNull',
262
- 0x0002: 'PtypInteger16', # Signed short.
263
- 0x0003: 'PtypInteger32', # Signed int.
264
- 0x0004: 'PtypFloating32', # Float.
265
- 0x0005: 'PtypFloating64', # Double.
266
- 0x0006: 'PtypCurrency',
267
- 0x0007: 'PtypFloatingTime',
268
- 0x000A: 'PtypErrorCode',
269
- 0x000B: 'PtypBoolean',
270
- 0x000D: 'PtypObject/PtypEmbeddedTable/Storage',
271
- 0x0014: 'PtypInteger64', # Signed longlong.
272
- 0x001E: 'PtypString8',
273
- 0x001F: 'PtypString',
274
- 0x0040: 'PtypTime', # Use filetimeToUtc to convert to unix time stamp.
275
- 0x0048: 'PtypGuid',
276
- 0x00FB: 'PtypServerId',
277
- 0x00FD: 'PtypRestriction',
278
- 0x00FE: 'PtypRuleAction',
279
- 0x0102: 'PtypBinary',
280
- 0x1002: 'PtypMultipleInteger16',
281
- 0x1003: 'PtypMultipleInteger32',
282
- 0x1004: 'PtypMultipleFloating32',
283
- 0x1005: 'PtypMultipleFloating64',
284
- 0x1006: 'PtypMultipleCurrency',
285
- 0x1007: 'PtypMultipleFloatingTime',
286
- 0x1014: 'PtypMultipleInteger64',
287
- 0x101E: 'PtypMultipleString8',
288
- 0x101F: 'PtypMultipleString',
289
- 0x1040: 'PtypMultipleTime',
290
- 0x1048: 'PtypMultipleGuid',
291
- 0x1102: 'PtypMultipleBinary',
292
- }
293
-
294
- # END CONSTANTS.
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', 'xmlreplace')
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.')