From de3b3616891049f3d2258c37818b93b139d74edb Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Thu, 24 Oct 2024 12:46:12 -0700 Subject: [PATCH 01/10] Add additional tests --- CHANGELOG.md | 3 +++ README.rst | 4 +-- extract_msg/__init__.py | 4 +-- extract_msg_tests/__init__.py | 2 ++ extract_msg_tests/util_tests.py | 43 +++++++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 extract_msg_tests/util_tests.py diff --git a/CHANGELOG.md b/CHANGELOG.md index d78b4056..9685198d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +**v0.52.1** +* Added tests for many functions in `extract_msg.utils`. + **v0.52.0** * [[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. * 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. diff --git a/README.rst b/README.rst index f03156c3..ce5ef6f7 100644 --- a/README.rst +++ b/README.rst @@ -260,8 +260,8 @@ your access to the newest major version of extract-msg. .. |License: GPL v3| image:: https://img.shields.io/badge/License-GPLv3-blue.svg :target: LICENSE.txt -.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.52.0-blue.svg - :target: https://pypi.org/project/extract-msg/0.52.0/ +.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.52.1-blue.svg + :target: https://pypi.org/project/extract-msg/0.52.1/ .. |PyPI2| image:: https://img.shields.io/badge/python-3.8+-brightgreen.svg :target: https://www.python.org/downloads/release/python-3810/ diff --git a/extract_msg/__init__.py b/extract_msg/__init__.py index df0b14ad..28a39d7c 100644 --- a/extract_msg/__init__.py +++ b/extract_msg/__init__.py @@ -27,8 +27,8 @@ # along with this program. If not, see . __author__ = 'Destiny Peterson & Matthew Walker' -__date__ = '2024-10-22' -__version__ = '0.52.0' +__date__ = '2024-10-24' +__version__ = '0.52.1' __all__ = [ # Modules: diff --git a/extract_msg_tests/__init__.py b/extract_msg_tests/__init__.py index a31b4cc0..3f2ba1ee 100644 --- a/extract_msg_tests/__init__.py +++ b/extract_msg_tests/__init__.py @@ -4,6 +4,7 @@ 'OleWriterEditingTests', 'OleWriterExportTests', 'PropTests', + 'UtilTests', 'ValidationTests', ] @@ -11,4 +12,5 @@ from .cmd_line_tests import CommandLineTests from .ole_writer_tests import OleWriterEditingTests, OleWriterExportTests from .prop_tests import PropTests +from .util_tests import UtilTests from .validation_tests import ValidationTests diff --git a/extract_msg_tests/util_tests.py b/extract_msg_tests/util_tests.py new file mode 100644 index 00000000..e4e3371c --- /dev/null +++ b/extract_msg_tests/util_tests.py @@ -0,0 +1,43 @@ +__all__ = [ + 'UtilTests', +] + + +import unittest + +from extract_msg import utils + + +class UtilTests(unittest.TestCase): + def testDictGetCasedKey(self): + caseDict = {'hello': 1, 'HeUtQjWkW': 2} + + self.assertEqual(utils.dictGetCasedKey(caseDict, 'Hello'), 'hello') + self.assertEqual(utils.dictGetCasedKey(caseDict, 'heutqjwkw'), 'HeUtQjWkW') + with self.assertRaises(KeyError): + utils.dictGetCasedKey(caseDict, 'jjjjj') + + def testDivide(self): + inputString = '12345678901234567890' + expectedOutputs = { + 1: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], + 2: ['12', '34', '56', '78', '90', '12', '34', '56', '78', '90'], + 3: ['123', '456', '789', '012', '345', '678', '90'], + 4: ['1234', '5678', '9012', '3456', '7890'], + 5: ['12345', '67890', '12345', '67890'], + 6: ['123456', '789012', '345678', '90'], + 7: ['1234567', '8901234', '567890'], + 8: ['12345678', '90123456', '7890'], + 9: ['123456789', '012345678', '90'], + 10: ['1234567890', '1234567890'], + 11: ['12345678901', '234567890'], + } + + for divideBy, expectedResult in expectedOutputs.items(): + self.assertListEqual(utils.divide(inputString, divideBy), expectedResult) + + def testMakeWeakRef(self): + self.assertIsNone(utils.makeWeakRef(None)) + class TestClass: + pass + self.assertIsNotNone(utils.makeWeakRef(TestClass())) \ No newline at end of file From d86fd23c1f900d688840583226293564ebe0bf85 Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Thu, 24 Oct 2024 13:49:26 -0700 Subject: [PATCH 02/10] Fix issue in msgPathToString (thank you tests) --- CHANGELOG.md | 1 + extract_msg/utils.py | 2 +- extract_msg_tests/util_tests.py | 17 +++++++++++++---- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9685198d..bd180d48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ **v0.52.1** * Added tests for many functions in `extract_msg.utils`. +* Fix an issue in `extract_msg.utils.msgPathToString()` that prevented backslashes from being replaced with forward slashes. **v0.52.0** * [[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. diff --git a/extract_msg/utils.py b/extract_msg/utils.py index 1639191c..22c36cab 100644 --- a/extract_msg/utils.py +++ b/extract_msg/utils.py @@ -709,7 +709,7 @@ def msgPathToString(inp: Union[str, Iterable[str]]) -> str: """ if not isinstance(inp, str): inp = '/'.join(inp) - inp.replace('\\', '/') + inp = inp.replace('\\', '/') return inp diff --git a/extract_msg_tests/util_tests.py b/extract_msg_tests/util_tests.py index e4e3371c..fa82912b 100644 --- a/extract_msg_tests/util_tests.py +++ b/extract_msg_tests/util_tests.py @@ -9,7 +9,7 @@ class UtilTests(unittest.TestCase): - def testDictGetCasedKey(self): + def test_dictGetCasedKey(self): caseDict = {'hello': 1, 'HeUtQjWkW': 2} self.assertEqual(utils.dictGetCasedKey(caseDict, 'Hello'), 'hello') @@ -17,7 +17,7 @@ def testDictGetCasedKey(self): with self.assertRaises(KeyError): utils.dictGetCasedKey(caseDict, 'jjjjj') - def testDivide(self): + def test_divide(self): inputString = '12345678901234567890' expectedOutputs = { 1: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], @@ -36,8 +36,17 @@ def testDivide(self): for divideBy, expectedResult in expectedOutputs.items(): self.assertListEqual(utils.divide(inputString, divideBy), expectedResult) - def testMakeWeakRef(self): + def test_makeWeakRef(self): self.assertIsNone(utils.makeWeakRef(None)) class TestClass: pass - self.assertIsNotNone(utils.makeWeakRef(TestClass())) \ No newline at end of file + self.assertIsNotNone(utils.makeWeakRef(TestClass())) + + def test_minutesToDurationStr(self): + pass + + def test_msgPathToStr(self): + self.assertEqual(utils.msgPathToString('hello/world/one'), 'hello/world/one') + self.assertEqual(utils.msgPathToString('hello/world\\one'), 'hello/world/one') + self.assertEqual(utils.msgPathToString(['hello', 'world', 'one']), 'hello/world/one') + self.assertEqual(utils.msgPathToString(['hello\\world', 'one']), 'hello/world/one') \ No newline at end of file From 72d3180e70529b0485dd05475e9ec76b61af1588 Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Thu, 24 Oct 2024 13:50:21 -0700 Subject: [PATCH 03/10] Simplify msgPathToString --- extract_msg/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extract_msg/utils.py b/extract_msg/utils.py index 22c36cab..24837244 100644 --- a/extract_msg/utils.py +++ b/extract_msg/utils.py @@ -709,8 +709,7 @@ def msgPathToString(inp: Union[str, Iterable[str]]) -> str: """ if not isinstance(inp, str): inp = '/'.join(inp) - inp = inp.replace('\\', '/') - return inp + return inp.replace('\\', '/') def parseType(_type: int, stream: Union[int, bytes], encoding: str, extras: Sequence[bytes]): From 88b3cce43adff8e681924dbbc888e814ce98a78f Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Sun, 3 Nov 2024 14:28:41 -0800 Subject: [PATCH 04/10] More tests, adjustment to duration strings --- CHANGELOG.md | 3 ++- README.rst | 4 ++-- extract_msg/__init__.py | 2 +- extract_msg/utils.py | 9 +++++++++ extract_msg_tests/util_tests.py | 11 ++++++++++- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd180d48..cc262278 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ -**v0.52.1** +**v0.53.0** * Added tests for many functions in `extract_msg.utils`. * Fix an issue in `extract_msg.utils.msgPathToString()` that prevented backslashes from being replaced with forward slashes. +* Change the behavior of `extract_msg.utils.minutesToDurationStr()` to properly use plurals. **v0.52.0** * [[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. diff --git a/README.rst b/README.rst index ce5ef6f7..c1cd6ba2 100644 --- a/README.rst +++ b/README.rst @@ -260,8 +260,8 @@ your access to the newest major version of extract-msg. .. |License: GPL v3| image:: https://img.shields.io/badge/License-GPLv3-blue.svg :target: LICENSE.txt -.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.52.1-blue.svg - :target: https://pypi.org/project/extract-msg/0.52.1/ +.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.53.0-blue.svg + :target: https://pypi.org/project/extract-msg/0.53.0/ .. |PyPI2| image:: https://img.shields.io/badge/python-3.8+-brightgreen.svg :target: https://www.python.org/downloads/release/python-3810/ diff --git a/extract_msg/__init__.py b/extract_msg/__init__.py index 28a39d7c..3c5642cd 100644 --- a/extract_msg/__init__.py +++ b/extract_msg/__init__.py @@ -28,7 +28,7 @@ __author__ = 'Destiny Peterson & Matthew Walker' __date__ = '2024-10-24' -__version__ = '0.52.1' +__version__ = '0.53.0' __all__ = [ # Modules: diff --git a/extract_msg/utils.py b/extract_msg/utils.py index 24837244..bd2d0249 100644 --- a/extract_msg/utils.py +++ b/extract_msg/utils.py @@ -696,8 +696,17 @@ def minutesToDurationStr(minutes: int) -> str: return '1 minute' elif minutes < 60: return f'{minutes} minutes' + elif minutes == 60: + return '1 hour' elif minutes % 60 == 0: return f'{minutes // 60} hours' + elif minutes < 120: + if minutes == 61: + return f'1 hour 1 minute' + else: + return f'1 hour {minutes - 60} minutes' + elif minutes % 60 == 1: + return f'{minutes // 60} hours 1 minute' else: return f'{minutes // 60} hours {minutes % 60} minutes' diff --git a/extract_msg_tests/util_tests.py b/extract_msg_tests/util_tests.py index fa82912b..4ec20755 100644 --- a/extract_msg_tests/util_tests.py +++ b/extract_msg_tests/util_tests.py @@ -43,7 +43,16 @@ class TestClass: self.assertIsNotNone(utils.makeWeakRef(TestClass())) def test_minutesToDurationStr(self): - pass + self.assertEqual(utils.minutesToDurationStr(0), '0 hours') + self.assertEqual(utils.minutesToDurationStr(1), '1 minute') + self.assertEqual(utils.minutesToDurationStr(2), '2 minutes') + self.assertEqual(utils.minutesToDurationStr(59), '59 minutes') + self.assertEqual(utils.minutesToDurationStr(60), '1 hour') + self.assertEqual(utils.minutesToDurationStr(61), '1 hour 1 minute') + self.assertEqual(utils.minutesToDurationStr(62), '1 hour 2 minutes') + self.assertEqual(utils.minutesToDurationStr(120), '2 hours') + self.assertEqual(utils.minutesToDurationStr(121), '2 hours 1 minute') + self.assertEqual(utils.minutesToDurationStr(122), '2 hours 2 minutes') def test_msgPathToStr(self): self.assertEqual(utils.msgPathToString('hello/world/one'), 'hello/world/one') From db440744131709edf26c88a8344132d152db3511 Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Tue, 5 Nov 2024 13:16:16 -0800 Subject: [PATCH 05/10] Fix issue with unwrapMsg --- CHANGELOG.md | 1 + extract_msg/utils.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc262278..e70614af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Added tests for many functions in `extract_msg.utils`. * Fix an issue in `extract_msg.utils.msgPathToString()` that prevented backslashes from being replaced with forward slashes. * Change the behavior of `extract_msg.utils.minutesToDurationStr()` to properly use plurals. +* Fixed issue in `extract_msg.utils.unwrapMsg()` that would prevent it from working on signed messages due to an API change. **v0.52.0** * [[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. diff --git a/extract_msg/utils.py b/extract_msg/utils.py index bd2d0249..6741737f 100644 --- a/extract_msg/utils.py +++ b/extract_msg/utils.py @@ -1102,7 +1102,7 @@ def unwrapMsg(msg: MSGFile) -> Dict[str, List]: msgFiles.append(att.data) toProcess.append(att.data) if isinstance(currentItem, MessageSignedBase): - raw += currentItem._rawAttachments + raw += currentItem.rawAttachments return { 'attachments': attachments, From fb49fb9df30b07421fb78e096cc7897225fd1caa Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Sat, 23 Nov 2024 20:07:22 -0800 Subject: [PATCH 06/10] Covers #448, fix logic, more complete form of #447 --- CHANGELOG.md | 3 +++ extract_msg/__init__.py | 2 +- extract_msg/exceptions.py | 5 ++++ extract_msg/msg_classes/message_base.py | 36 ++++++++++++++++++++----- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e70614af..cc8e7cd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ * Fix an issue in `extract_msg.utils.msgPathToString()` that prevented backslashes from being replaced with forward slashes. * Change the behavior of `extract_msg.utils.minutesToDurationStr()` to properly use plurals. * Fixed issue in `extract_msg.utils.unwrapMsg()` that would prevent it from working on signed messages due to an API change. +* Added new exception `MimetypeFailureError`. +* Modified the logic of `MessageBase.asEmailMessage()` to use `AttachmentBase/SignedAttachment.name` instead of `getFilename()` which only exists on AttachmentBase. +* Modified the logic of `MessageBase.htmlBodyPrepared()` to properly put the mimetype in image tags to ensure rendering. Logic was also modified to use `encode` instead of `prettify` to reduce computation and output size. **v0.52.0** * [[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. diff --git a/extract_msg/__init__.py b/extract_msg/__init__.py index 3c5642cd..ab0c8024 100644 --- a/extract_msg/__init__.py +++ b/extract_msg/__init__.py @@ -27,7 +27,7 @@ # along with this program. If not, see . __author__ = 'Destiny Peterson & Matthew Walker' -__date__ = '2024-10-24' +__date__ = '2024-11-23' __version__ = '0.53.0' __all__ = [ diff --git a/extract_msg/exceptions.py b/extract_msg/exceptions.py index b186c0c2..157c481f 100644 --- a/extract_msg/exceptions.py +++ b/extract_msg/exceptions.py @@ -92,6 +92,11 @@ class InvalidPropertyIdError(ExMsgBaseException): The provided property ID was invalid. """ +class MimetypeFailureError(ExMsgBaseException): + """ + The mimetype was unable to be properly determined when it was mandatory. + """ + class NotWritableError(ExMsgBaseException): """ Modification was attempted on an instance that is not writable. diff --git a/extract_msg/msg_classes/message_base.py b/extract_msg/msg_classes/message_base.py index 40ca0fa7..e2f34a3f 100644 --- a/extract_msg/msg_classes/message_base.py +++ b/extract_msg/msg_classes/message_base.py @@ -39,7 +39,8 @@ ) from ..exceptions import ( ConversionError, DataNotFoundError, DeencapMalformedData, - DeencapNotEncapsulated, IncompatibleOptionsError, WKError + DeencapNotEncapsulated, IncompatibleOptionsError, MimetypeFailureError, + WKError ) from .msg import MSGFile from ..structures.report_tag import ReportTag @@ -178,7 +179,7 @@ def asEmailMessage(self) -> EmailMessage: if att.dataType: if hasattr(att.dataType, 'asEmailMessage'): # Replace the extension with '.eml'. - filename = att.getFilename() + filename = att.name or '' if filename.lower().endswith('.msg'): filename = filename[:-4] + '.eml' msgMain.add_attachment( @@ -1198,12 +1199,35 @@ def htmlBodyPrepared(self) -> Optional[bytes]: for tag in tags: # Iterate through the attachments until we get the right one. cid = tag['src'][4:] - data = next((attachment.data for attachment in self.attachments if attachment.cid == cid), None) + att = next((attachment for attachment in self.attachments if hasattr(attachment, 'cid') and attachment.cid == cid), None) # If we found anything, inject it. - if data: - tag['src'] = (b'data:image;base64,' + base64.b64encode(data)).decode('utf-8') + if att and isinstance(att.data, bytes): + # Try to get the mimetype. If we can't, see if the item has an + # extension and guess the mimtype for a few known ones. + mime = att.mimetype + if not mime: + ext = (att.name or '').split('.')[-1].lower() + if ext == 'png': + mime = 'image/png' + elif ext == 'jpg' or ext == 'jpeg': + mime = 'image/jpeg' + elif ext == 'gif': + mime = 'image/gif' + elif ext == 'tiff' or ext == 'tif': + mime = 'image/tif' + elif ext == 'bmp': + mime = 'image/bmp' + elif ext == 'svg': + mime = 'image/svg+xml' + # Final check. + if mime: + tag['src'] = (b'data:' + mime.encode() + b';base64,' + base64.b64encode(att.data)).decode('utf-8') + else: + # We don't know what to actually put for this item, and we + # really should never end up here, so throw an error. + raise MimetypeFailureError('Could not get the mimetype to use for htmlBodyPrepared.') - return soup.prettify('utf-8') + return soup.encode('utf-8') @functools.cached_property def htmlInjectableHeader(self) -> str: From 568602b5b7612b09730b59640058e287e809bc8d Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Mon, 30 Dec 2024 13:52:43 -0800 Subject: [PATCH 07/10] Attempt to fix issue with asEmailMessage, allow more versions of redblack --- CHANGELOG.md | 4 ++++ README.rst | 4 ++-- extract_msg/__init__.py | 4 ++-- extract_msg/msg_classes/message_base.py | 5 +---- requirements.txt | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc8e7cd6..6ee906ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +**v0.53.1** +* Expanded allowable range for `red-black-tree-mod`. +* Fix issue with `MessageBase.asEmailMessage()` that prevented embedded MSG files from being attached. + **v0.53.0** * Added tests for many functions in `extract_msg.utils`. * Fix an issue in `extract_msg.utils.msgPathToString()` that prevented backslashes from being replaced with forward slashes. diff --git a/README.rst b/README.rst index c1cd6ba2..2ff4b8a2 100644 --- a/README.rst +++ b/README.rst @@ -260,8 +260,8 @@ your access to the newest major version of extract-msg. .. |License: GPL v3| image:: https://img.shields.io/badge/License-GPLv3-blue.svg :target: LICENSE.txt -.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.53.0-blue.svg - :target: https://pypi.org/project/extract-msg/0.53.0/ +.. |PyPI3| image:: https://img.shields.io/badge/pypi-0.53.1-blue.svg + :target: https://pypi.org/project/extract-msg/0.53.1/ .. |PyPI2| image:: https://img.shields.io/badge/python-3.8+-brightgreen.svg :target: https://www.python.org/downloads/release/python-3810/ diff --git a/extract_msg/__init__.py b/extract_msg/__init__.py index ab0c8024..97393a07 100644 --- a/extract_msg/__init__.py +++ b/extract_msg/__init__.py @@ -27,8 +27,8 @@ # along with this program. If not, see . __author__ = 'Destiny Peterson & Matthew Walker' -__date__ = '2024-11-23' -__version__ = '0.53.0' +__date__ = '2024-12-30' +__version__ = '0.53.1' __all__ = [ # Modules: diff --git a/extract_msg/msg_classes/message_base.py b/extract_msg/msg_classes/message_base.py index e2f34a3f..62a39271 100644 --- a/extract_msg/msg_classes/message_base.py +++ b/extract_msg/msg_classes/message_base.py @@ -182,10 +182,7 @@ def asEmailMessage(self) -> EmailMessage: filename = att.name or '' if filename.lower().endswith('.msg'): filename = filename[:-4] + '.eml' - msgMain.add_attachment( - att.data.asEmailMessage(), - filename = filename, - cid = att.contentId) + msgMain.attach(att.data.asEmailMessage()) else: if issubclass(att.dataType, bytes): data = att.data diff --git a/requirements.txt b/requirements.txt index 4a702882..d8985638 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,4 @@ compressed-rtf>=1.0.6,<2 ebcdic>=1.1.1,<2 beautifulsoup4>=4.11.1,<4.13 RTFDE>=0.1.1,<0.2 -red-black-tree-mod==1.20 +red-black-tree-mod>=1.20, <=1.23 From 83f135cde72d49a5e37b214487311693f5fff4a8 Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Wed, 5 Feb 2025 13:13:15 -0800 Subject: [PATCH 08/10] Expand allowable versions of bs4 --- CHANGELOG.md | 1 + extract_msg/__init__.py | 2 +- requirements.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ee906ed..f3aebed8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ **v0.53.1** * Expanded allowable range for `red-black-tree-mod`. * Fix issue with `MessageBase.asEmailMessage()` that prevented embedded MSG files from being attached. +* Expand allowable versions of BeautifulSoup4. **v0.53.0** * Added tests for many functions in `extract_msg.utils`. diff --git a/extract_msg/__init__.py b/extract_msg/__init__.py index 97393a07..3367f63c 100644 --- a/extract_msg/__init__.py +++ b/extract_msg/__init__.py @@ -27,7 +27,7 @@ # along with this program. If not, see . __author__ = 'Destiny Peterson & Matthew Walker' -__date__ = '2024-12-30' +__date__ = '2025-02-05' __version__ = '0.53.1' __all__ = [ diff --git a/requirements.txt b/requirements.txt index d8985638..4261c061 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,6 @@ olefile==0.47 tzlocal>=4.2,<6 compressed-rtf>=1.0.6,<2 ebcdic>=1.1.1,<2 -beautifulsoup4>=4.11.1,<4.13 +beautifulsoup4>=4.11.1,<4.14 RTFDE>=0.1.1,<0.2 red-black-tree-mod>=1.20, <=1.23 From 2b57b7ae01f275144c12a5d0b9c134cbe1dd0318 Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Wed, 5 Feb 2025 13:14:21 -0800 Subject: [PATCH 09/10] Fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3aebed8..18fcbdd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ **v0.53.1** * Expanded allowable range for `red-black-tree-mod`. * Fix issue with `MessageBase.asEmailMessage()` that prevented embedded MSG files from being attached. -* Expand allowable versions of BeautifulSoup4. +* Expand allowable versions of `BeautifulSoup4`. **v0.53.0** * Added tests for many functions in `extract_msg.utils`. From efd2a7a229f30afe27a7382ba8ffad7e9d0e9316 Mon Sep 17 00:00:00 2001 From: TheElementalOfDestruction Date: Wed, 5 Feb 2025 13:16:43 -0800 Subject: [PATCH 10/10] Update python versions range for testing --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 435247c9..00235552 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4