NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1459 most downloaded on PyPI
Extracts emails and attachments saved in Microsoft Outlook's .msg files
Last release 1 months ago
14 Aug 2026
Release timing varies
gaps range from 9 days to 11 months
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
8 years old
130 releases · first in 2018
[ TeamMsgExtractor #484 ] Corrected the way the HTML body is decoded in MessageBase.asEmailMessage() to prevent encoding errors.
v0.56.1
MessageBase.asEmailMessage() to prevent encoding errors.[TeamMsgExtractor #478] Expand allowable versions of ebcdic to include 2.x. The 2.0 release is a pure technical release with no functional changes; it
v0.56.0
ebcdic to include 2.x. The 2.0 release is a pure technical release with no functional changes; it only drops support for Python 2 and 3.8. The lower bound is unchanged so installs on Python 3.8 will continue to resolve to ebcdic 1.1.1.beautifulsoup to allow for versions up to 5.*.*. I was previously hesitant to do so because they sometimes do what seems like non backwards compatible changes in minor versions, but it looks like this should be fine..strip() to file name determination to ensure that folders with trailing spaces would be corrected before being used.</head> instead of </html>.MessageBase.asEmailMessage() raising ValueError when a message has multiple To recipients.One column per quarter.
[TeamMsgExtractor #465] Added missing msg.close() to openMsg(). If the MSG file was actually just a plain OLE file, it would be left open.
v0.55.0
msg.close() to openMsg(). If the MSG file was actually just a plain OLE file, it would be left open.maxNameLength for MessageBase.save() to 40 instead of 256.MessageBase.save() to properly report the reason a folder fails to be created.MessageBase.save().[TeamMsgExtractor #462] Fix potential issue where child MSG might have incompatible encoding to parent MSG when trying to grab a stream from the paren
v0.54.1
RTFDE. This shows improvements on all files that take more than one second. Currently, this actually fixes some files previously outputting wrong from RTFDE when deencapsulating the HTML body, specifically around non breaking spaces sometimes not transferring over.[TeamMsgExtractor #456] Changed the prepared html output to use plainly encoded HTML instead of prettified, since current prettification options used
v0.54.0
[TeamMsgExtractor #452] Adjusted code to allow html encoding to be cached to try to speed up bs4 operations.
v0.53.2
bs4 operations.enumerate.TOCEntry not initializing DVTargetDevice correctly.ContentID to SignedAttachment. AFAIK these can't ever be set, but this prevents errors in some places.Expanded allowable range for red-black-tree-mod.
v0.53.1
red-black-tree-mod.MessageBase.asEmailMessage() that prevented embedded MSG files from being attached.BeautifulSoup4.[TeamMsgExtractor #444] Fix typo in string that prevented HTML body from generating from the plain text body properly.
v0.52.0
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.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.Add class type added in last version to known class types.
v0.51.1
[TeamMsgExtractor #401] Add basic support for MSG class type IPM.SkypeTeams.Message.
v0.51.0
IPM.SkypeTeams.Message.[TeamMsgExtractor #434] Fix bug introduced in previous version.
v0.50.1
[TeamMsgExtractor #432] Adjust html header code to replace non-ascii characters with escaped versions. Also adujusted plain text to html conversion to
v0.50.0
NullDate.[TeamMsgExtractor #427] Adjusted code for converting time stamps to create null dates for any time stamp beyond a certain point. The point was determi
v0.49.0
tryGetMimetype were the code didn't properly check if the data type was bytes (it only checked if it had a type).ErrorBehavior value CUSTOM_ATTACH_TOLERANT to allow skipping checks for unused data that is normally validated.[TeamMsgExtractor #420] Fixed typo introduced in last version.
v0.48.7
[TeamMsgExtractor #417] Fixed issues with openMsg where some corrupted MSG files could end up throwing an uncaught exception and leaving the file hand
v0.48.6
openMsg where some corrupted MSG files could end up throwing an uncaught exception and leaving the file handle open.[TeamMsgExtractor #414] Fixed typo in message_signed_base.py.
v0.48.5
message_signed_base.py.[TeamMsgExtractor #411] Fix console script throwing error due to changed console args not defaulting.
v0.48.4
[TeamMsgExtractor #409] Added missing private method to SignedAttachment.
v0.48.3
SignedAttachment.Fixed bugs with MessageBase.asEmailMessage(). Numerous improvements to how it handles the data.
v0.48.2
MessageBase.asEmailMessage(). Numerous improvements to how it handles the data.Added an option (-s, --stdin) to the command line to take an MSG file from stdin. This allows the user to pipe the MSG data from another program direc
v0.48.1
-s, --stdin) to the command line to take an MSG file from stdin. This allows the user to pipe the MSG data from another program directly instead of having to write a middleman that uses the extract-msg library directly or having to write the file to the disk first.AttachmentBase for creation and modification time. These can be accessed through createdAt or creationTime and lastModificationTime or modifiedAt.OleWriter tests to output the name of the test file being done if an error occurs.Adjusted error handling for named properties to handle critical streams being missing and to allow suppression of those errors.
v0.48.0
ErrorBehavior.NAMED_NAME_STREAM is provided to the MSGFile instance, a warning will be logged and that entry will simply be dropped.OleWriter to prepare the code for being able to write version 4 files. Version 3 files are currently the only one's supported, but much of the code had hard-coded values that could be replaced with variables and small conditionals. This will have very little performance impact, and should not be noticeable.OleWriter to make private sections more understandable.MessageSignedBase._rawAttachments to MessageSignedBase.rawAttachments to provide non-private access in a reliable way.Changed the public API for PropertiesStore to improve the quality of its code. The properties type is now mandatory, and the intelligence field (and t
v0.47.0
PropertiesStore to improve the quality of its code. The properties type is now mandatory, and the intelligence field (and the related enum) has been removed.
toBytes and __bytes__ methods will both generate based on the contents of this class, allowing for new properties to be created and for existing properties to be modified or removed if the class is set to writable on creation.Named.getPropNameByStreamID. This method takes the ID of a stream (or property stream entry) and returns the property name (as a tuple of the property name/ID and the property set) that is stored there. Returns None if the stream is not used to store a named property. This name can be directly used (if it is not None) to get the NamedPropertyBase instance associated. This method is most useful for people looking at the raw data of a stream and trying to figure out what named property it refers to.extract_msg.properties.props.extract_msg.attachments.enums and constants submodule.PtypGuid was being parsed by the wrong property type. Despite having a fixed size, it is still a variable length property.BCTextFormat and BCLabelFormat to IntFlag enums. The values that exist are for the individual flags and not the groups of flags.FieldInfo writable, however it can no longer be directly converted to bytes since it requires additional information outside of itself to convert to bytes. It still retains a toBytes method, however it requires an argument for the additional data.UnsupportedAttachment inverting the skipNotImplemented keyword argument.DMPaperSize not being a subclass of Enum.DMPaperSize.extract_msg.constants.st.Recipient.existsTypedProperty and AttachmentBase.existsTypedProperty having the wrong return type.OleStreamStruct and finalized it to only handle the OLEStream for embedded objects.extract_msg.utils.fromTimeStamp.extract_msg.properties.prop.createNewProp. This function allows a new property to be created with default data based on the name. The name MUST be an 8 character hex string, the first 4 characters being the value for the property ID and the second 4 being the value for the type.VariableLengthProp.reservedFlags returning the wrong type.ServerID using the wrong struct (would have thrown an exception for not having enough data).PtypCurrency.extract_msg.constants.NULL_DATE to be a subclass of datetime.datetime instead of just a fixed value. Functions that return null dates may end up returning distinct versions of NullDate (the newly created subclass), however all instances of NullDate will register as being equal to each other. Existing equality comparisons to the NULL_DATE constant will all function as intended, however is checks may fail for some null dates.Decimal instance for higher precision.FixedLengthProp and VariableLengthProp writable. Only the property flags from PropBase is writable. This also includes the ability to convert them to bytes based on their value.VariableLengthProp regarding it's calculation of sizes.hasLen function.InvaildPropertyIdError to InvalidPropertyIdError.olefile version 0.47.RTFDE minimum version to 0.1.1.compressed-rtf to remove minor typo (it should forward to the correct place regardless, but just to be safe).OleWriter when it comes to large sets of data. Most issues would fail silently and only be noticeable when trying to open the file. If your file is less than 2 GB, you would likely not have notices and issues at all. This includes adding a new exception that is throw from the write method, TooManySectorsError.OleWriter that could cause entries to end up partially added if the data was an issue.Adjusted typing information on regular expressions. They were using a subscript that was added in Python 3.9 (apparently that is something the type ch
v0.46.2
[TeamMsgExtractor #394] Fix typo in props that caused the wrong number of bytes to be given to a struct.
v0.46.1
Removed methods deprecated in v0.45.0.
v0.46.0
overrideEncoding property of MSGFile to allow automatic encoding detection. Simply set the property to the string "chardet" and, assuming the chardet module is installed, it will analyze a number of the strings to try and form a consensus about the encoding. This will ignore the specified encoding only if if successfully detects. Otherwise it will log a warning and fall back to the default behavior.extract_msg.utils.decodeRfc2047 to not throw decoding errors if the content given is not ASCII.email.policy.compat32 to prevent partial parsing of quoted header fields.MSGFile.export to specify that updated fields on an MSGFile instance (and it's subclasses) will not be reflected in the result of the function. Many of the functions do use the newest version of a cached_property, but this is not one of them.v0.45.0.EntryID from no base class to abc.ABC.position property to EntryID to tell how many bytes were used to create the EntryID.MSGFile from [MS-OXCMSG].MessageBase from it's subclasses.PermanentEntryID to correctly parse the data. Previously the distinguished name did not actually end at the null character, instead ending at the end of the bytes provided. If there was trailing data, it would be captured inadvertently.StoreObjectEntryID.dateFormat and datetimeFormat. These allow the user to easily override the strings being used for format dates and dates that include a time component, respectively.
MessageBase.parsedDate which could have incorrect values.MessageBase.date and related things either being incorrectly documented or doing things that are not specified by the documentation. It was supposed to have been changed to use datetime objects, but it was still using strings.extract_msg.utils.isEmptyString.extract_msg.utils.properHex.getStream helper function to CustomAttachmentHandler.getStreamAs helper function to CustomAttachmentHandler.EntryID.autoCreate to return None if given None or empty bytes.EntryID.autoCreate to raise a FeatureNotImplemented exception if no valid entry ID class is found.CustomAttachmentHandler.imapclient dependency.getJson to have values be null if they aren't found rather than an empty string.getJson method correctly for a number of classes.Task.percentComplete to always return a float.NotImplementedError for custom attachment handler not being found to FeatureNotImplemented. Additionally, changed the error message to specify the CLSID found on the attachment to better enable people to report issues.Recipient and MessageBase that makes it rely on MessageBase.recipientTypeClass to determine the class to use for the recipientType property. Adjusted the typing of Recipient to have it reflect the type that will be used.ResponseStatus.fromIter to actually return a List instead of a set.DVAspect enum.OLEPresentationStream.NNTPNewsgroupFolderEntryID.newsgroupName to bytes instead of string since it is ANSI.listDir and slistDir as methods to AttachmentBase, Recipient, and Named. These always exclude the prefix, returning as if their directory is the root of the object. This allows the named to be directly used for accessing those files.MessageBase. Much of this initialization was there from before a lot of stuff changed to cached_property and a number of internal variables were being used. Now all of the relevant variables will be initialized by the way they are accessed.DependencyError.ImportError to DependencyError.rawData property in favor of the toBytes method. For now, many of these will simply return the raw data used, specifically those that are still unmodifiable. Any whose properties have the ability to be modified will have properly implemented versions. These classes also allow None to be passed as the value for their data, which will be the default if no arguments have been passed to the constructor. If no arguments or None is given as the data, it will create a new instance with default values. This is all in an effort to move towards the ability to create new MSG files and the MSGWriter class. All toBytes methods will either exclusively return bytes or will return None to specify that the structure isn't valid to convert to bytes. Structures that may be invalid will be annotated as Optional[bytes] for the return type.
__bytes__ method. If the object returned is not bytes, the method will throw a TypeError.PropBase flag properties and changed the main flags property to return an enum containing the flags.TZRule to use unsigned values where applicable.TZRule to require the 14 null bytes (I commented it out completely on accident instead of swapping it to a plain read). It now logs a warning about the bytes not being null.windowsUnicode.FixedLengthProperty.parseType to the private API. This was not intended for external use anyways, so leaving it as public API didn't make sense.ContactAddressEntryID being the wrong value.inputToBytes to support objects with the __bytes__ method. If the method exists and works then it will be used as a last resort.OleWriter to accept objects with a __bytes__ method for the data to use for an entry.__bytes__ method to MSGFile. This is equivalent to calling MSGFile.exportBytes.Deprecated many private functions, including methods on many of the classes. Of primary note are _getStream and _getStringStream, which have been move…
v0.45.0
MessageSignedBase.attachments that would cause it to return None instead of an empty list if the number of normal attachments was 0 was the error behavior was set to ignore violations of the standard.MessageSignedBase.attachments to use functools.cached_property instead of property.NamedPropertyBase a subclass of abc.ABC.PropBase to be a subclass of abc.ABC._getStream and _getStringStream, which have been moved to the public API as getStream and getStringStream. Any deprecated functions still exist and will forward to a public API function if they are not being removed. Additionally, all internal usage of them has been removed. This change is one of the big preparations that is needed for the 1.0.0 release.
0.42.0._genRecipient. This is not intended for use outside of the module except for subclasses. The change removed the allowance of ints for the second argument, requiring that it be a valid enum type.IntEnum.PropertiesStore to allow for integer property names and getting a property based on just the ID. You can also get a list of all properties that use a given ID.PropertiesStore.getProperties which gets a list of all properties matching the property ID. Return type is a list of PropBase instances.PropertiesStore.getValue which looks for the first matching FixedLengthProp and returns the value from it.MSGFile, AttachmentBase, PropertiesStore, and Recipient objects:
getMultipleBinary: Gets a multiple binary property as a list of bytes objects.getSingleOrMultipleBinary: A combination of getStream and getMultipleBinary which prefers a single binary stream. Returns a single bytes object or a list of bytes objects.getMultipleString: Gets a multiple string property as a list of str objects.getSingleOrMultipleString: A combination of getStringStream and getMultipleString which prefers a single string stream. Returns a single bytes objecct or a list of bytes objects.getPropertyVal: Shortcut for instance.props.getValue that allows new behavior to be added by overriding it.getNamedProp: Shortcut for instance.namedProperties.get((propertyName, guid), default) that allows new behavior to be added by overriding it.Named._getStringStream and Named.sExists. The named properties storage will always use regular streams and not string streams.Named methods to no longer have a prefix argument. The prefix should always be false sense the named property mapping will only exist in the top level directory.tryGetMimeType to allows any attachments whose data property would return a bytes instance.AttachmentBase.clsid which had the potential to cause some attachments to fail to generate a CLSID._getNamedAs -> getNamedAs: Changed to always require a conversion argument. If you were previously using it to plainly get a named property or to handle the properly being None or a real value, you should use the return value of getNamedProp instead._getPropertyAs -> getPropertyAs: Same as above, use getPropertyVal instead for None or plain access._getStreamAs -> getStreamAs, getStringStreamAs: Once again, see above. Use getStream and getStringStream, respectively.Fixed a bug that caused MessageBase.headerInit to always return False after the 0.42.0 update.
v0.44.0
MessageBase.headerInit to always return False after the 0.42.0 update.MessageBase.headerInit to a property.extract_msg.utils.__all__.extract_msg/utils.py.extract_msg.utils.decodeRfc2047.[TeamMsgExtractor #56] [TeamMsgExtractor #248] Added new function MessageBase.asEmailMessage which will convert the MessageBase instance, if possible,
v0.43.0
MessageBase.asEmailMessage which will convert the MessageBase instance, if possible, to an email.message.EmailMessage object. If an embedded MSG file on a MessageBase object is of a class that does not have this function, it will simply be attached to the instance as bytes.message_base.py to help with type checkers.email.parser.EmailParser to email.parser.HeaderParser in MessageBase.header.MessageBase.header. This should improve usage of it, and should not have any noticeable negative changes. You man notice some of the values parse slightly differently, but this effect should be mostly suppressed.Fix bug in AttachmentBase.mimetype that would cause it to throw an error when accessed. This bug was introduced in v0.42.0.
v0.42.2
AttachmentBase.mimetype that would cause it to throw an error when accessed. This bug was introduced in v0.42.0.Fixed some constants being accessed with the wrong name (names were changed in reorganization).
v0.42.1
All features like this will be opt-in to reduce possible vulnerabilities.
v0.42.0
overwriteExisting keyword argument from code or the --overwrite-existing option from the command line.custom_attachments. This submodule provides an extendable way to handle custom attachment types, attachment types whose structure and formatting are not defined in the Microsoft documentation for MSG files. This includes a handler to at least partially cover support for Outlook images.encoding submodule for encoding tasks, including proper support for Microsoft's implementation of CP950. This gets added to the codecs list as "windows-950".
AttachmentBase.clsid which returns the listed CLSID value of the data stream/storage of the attachment.MSGFile.attachments. This should not cause any noticeable changes to the output.__main__ using the wrong enum for error behavior.Named.get being severely out of date (it's not used anywhere by the module which is why it wasn't noticed).Named.__getitem__ being entirely case-sensitive.treePath property of all classes that have it) to using weakref.ReferenceType to avoid hard cyclic references.Recipient._getTypedStream never returning a value.knownMsgClass to a private function since it is explicitly not being exported by any part of the module.getFullClassName.preparedHtml/--prepared-html option.AttachmentBase.
Attachment class is to override the function used when creating attachments. This can be done by passing attachmentInit = myFunction as an option to openMsg. This function MUST return an instance of AttachmentBase.skipNotImplemented = True is passed to the save function.RTFDE errors to fall under the ErrorBehavior enum. Usage of the original option will be allowable, but is being marked as deprecated. However, it is still a dedicated option from the command line.
RTFDE errors, specifically the ones that it is normal for the module to throw.RTFDE version 0.1.0. Users encountering random errors from that module should find that those errors have disappeared. If you get errors from it still, bring up the issue on their GitHub.IPM.StickyNote.__init__ functions for MSG classes.chardet dependency.Contact.__init__ as it didn't provide any unique behavior.openMsg to specify that it accepts all options recognized by MSGFile subclasses, allowing the doc string to not be modified every time one of them is changed.
__init__ methods to do the same thing.dataType property to AttachmentBase and SignedAttachment for checking the class that the data will be, if accessible. Returns None if the data is inaccessible, including because accessing it would throw an exception.InsecureFeatures and option insecureFeatures. This option will allow certain features with security implications to be used for files that you trust. Currently the only feature it supports is the usage of PIL/Pillow to open and modify images. All features like this will be opt-in to reduce possible vulnerabilities.prefix option for MSGFile.__init__ (and therefore openMsg). If you are not setting this manually, you should notice little difference.fromBits to be IntFlag enums.CalendarBase.keywords being blatantly incorrect (it was so bad I don't know how it slipped through).Contact.gender being blatantly incorrect.MSGFile to have olefile raise defects of type DEFECT_INCORRECT and above instead of just DEFECT_FATAL. Uncaught issues of DEFECT_INCORRECT can often cause the module to have parsing issues that may be misleading, this just ensures the issue is clarified. This behavior can be reverted back to the previous with ErrorBehavior.OLE_DEFECT_INCORRECT.Fixed an issue from version 0.41.3 where the header being present but missing the From field would cause an exception.
v0.41.5
0.41.3 where the header being present but missing the From field would cause an exception.Fixed an issue in the last version that would break the decoding function if the contents were not encoded.
v0.41.4
tzlocal and allow future updates for compressed_rtf and ebcdic.[TeamMsgExtractor #365] Fixed an issue that would cause certain values retrieved from the header to not be decoded properly. It does this when retriev
v0.41.3
MessageBase.headerText which is the text content of the header stream. Adjusted other things to use this instead of trying to retrieve the stream directly in multiple places.MessageBase.header.Updated annotations on MessageBase.save.
v0.41.2
MessageBase.save.BodyTypes.MessageBase.detectedBodies for detecting what bodies have been stored (not generated by the module) in the .msg file.[TeamMsgExtractor #362] Fixed an issue with the removal of the --dev option missing one of the checks (I swear I actually tested it).
v0.41.1
--dev option missing one of the checks (I swear I actually tested it).Deprecated AttachErrorBehavior in favor of the new ErrorBehavior enum which controls the error behavior for the various parts of the MSG file. Uses of…
v0.41.0
StandardViolationError for poorly created files. This may cause issues you might not expect since this exception is meant to stop the processing for a reason.SignedAttachment.data now returns either bytes or MSGFile. SignedAttachment also now has a asBytes property that will return the bytes that created the signed attachment, regardless of if it is an MSG or not, making it unnecessary to call MSGFile.exportBytes to get the bytes of the embedded MSG file, which can add a small delay to your code. As Attachment is a much more complex class, it does not (at least yet) have this property. Also unlike Attachment, SignedAttachment will not throw an exception if the data is an MSG file but is not supported. Instead, it will simply be logged as a exception, but the code will continue. If the data is successfully read as an embedded MSG file, the AttachmentType will be AttachmentType.SIGNED_EMBEDDED.AttachErrorBehavior in favor of the new ErrorBehavior enum which controls the error behavior for the various parts of the MSG file. Uses of the former will work until the next major version.attachmentErrorBehavior parameter of MSGFile in favor of errorBehavior. Uses of the previous will work until the next major version.treePath property to SignedAttachment to bring it more in line with AttachmentBase.dev and dev_classes submodules, as most of their features are possible using the base code. Additionally, the classes involved because significantly outdated over time.--dev argument from the command line.Properties that caused the __contains__ method to always be False. This occurred because it was missing a return statement. Fortunately, it looks like only one part of the module was affected due to other parts using a properly written function.in for checking that a property exists as opposed to has_key. The function was there to act more like Python 2.Properties.has_key.validation submodule and all related references. It was pretty outdated and has minimal usage at this point in time. It may come back at some later point.MessageBase.save so it doesn't save raw when an exception occurs. This behavior may have ended up creating unexpected output which is why it was removed. It was mainly there for debugging in the first place, but is no longer necessary.__contains__ function to Named class.message_base.py that would only cause problems if something was wrong with the HTML.OleWriter using an empty path.InvalidFileFormatError for a missing property stream to a StandardViolationError._rtf.tokenize_rtf which would cause an exception to handle incorrectly and throw an unclear error.__all__ entries and added some where they should be.UnrecognizedMSGTypeError exception in favor of exporting the exceptions module.properHex.RecurrencePattern.[TeamMsgExtractor #338] Added new code to handle injection of text into the RTF body. For many cases, this will be much more effective as it relies on
v0.40.0
_rtf module. This module in it's entirety is considered to be implementation details, and I give no guarantee that it will remain in it's current state even across patch versions. As such, it is not recommended to use it outside of the module.MessageBase.rtfEncapInjectableHeader and MessageBase.rtfPlainInjectableHeader from str to bytes. They always get encoded anyways, so I don't know why I had them returning as str.README.Fixed issues with AttachmentBase.name that could cause it to generate wrong.
v0.39.2
AttachmentBase.name that could cause it to generate wrong.MSGFile.exportBytes which returns the exported version from MSGFile.export as bytes instead of writing it to a file or file-like object.[TeamMsgExtractor #333] Fixed typo in a warning.
v0.39.1
__del__ method from MSGFile. It was there for cleanup, but wasn't planned well enough to stop it from causing issues. It may be reintroduced in the future if I can manage to remove the issues.extract_msg.utils.getCommandArgs having invalid logic after a previous (rather old) update that caused exceptions when using certain options.treePath to AttachmentBase and MSGFile (which adds it to nearly every class). This property is the path to the current instance, represented as a tuple of instances that would be used to get to the current instance.OleWriter that would produce corrupted OLE files if the DIFAT needed more than the header.This release fixed several issues while also significantly increasing the functionality of the OleWriter class.
This release fixed several issues while also significantly increasing the functionality of the OleWriter class.
v0.39.0
AttachMethod property. The code will log a warning, attempt to detect the method, and throw a StandardViolationError if it fails.None.OleWriter.MSGFile regarding the filename keyword argument.rootPath to OleWriter.fromOleFile for saving a specific directory from an OLE file instead of just copying the entire file. That directory will become the root of the new one.OleWriter to generate certain values only at save time to make them more dynamic. This allows for existing streams to be properly edited (although has issues with allowing storages to be edited).OleWriter.deleteEntry to remove an entry that was already added. If the entry is a storage, all children will be removed too.OleWriter.editEntry to edit an entry that was already added.OleWriter.addEntry to add a new entry to the writer without an OleFileIO instance. Properties of the entry are instead set using the same keyword arguments as described in OleWriter.editEntry._DirectoryEntry to DirectoryEntry to make the more finalized version public. Access to the originals that the OleWriter class creates should never happen, instead copies should be returned to ensure the behavior is as expected.OleWriter.getEntry which returns a copy of the DirectoryEntry instance for that stream or storage in the writer. Use this function to see the current internal state of an entry.OleWriter.renameEntry which allows the user to rename a stream or storage (in place). This only changes it's direct name and not it's location in the new OLE file.OleWriter.walk which is similar to os.walk but for walking the structure of the new OLE file.OleWriter.listItems which is functionally equivalent to olefile.OleFileIO.listdir which returns a list of paths to every item. Optionally a user can get the paths just for streams, just for storages, or both. Requesting neither will simply return an empty list. Default is to just return streams.inputToMsgPath which is used in a lot of places where user input for a path is accepted. It ensures illegal characters don't exist and that the path segments (each name for a storage or stream) are less than 32 characters. This will be most helpful for OleWriter.OleWriter to make extensions easier and consolidate common code. Many of these involve direct access to internal data which is why they are private.Fix line in OleWriter that was causing exporting to fail.
v0.38.4
OleWriter that was causing exporting to fail.README.Fixed issues in HTML generation that caused line breaks to be omitted from large sections of the text.
v0.38.3
Fixed new NameError accidentally introduced in the previous version.
v0.38.2
NameError accidentally introduced in the previous version.Added a __del__ method to MSGFile to ensure a bit of proper cleanup should all references to an MSGFile instance be removed before the file is closed.
v0.38.1
__del__ method to MSGFile to ensure a bit of proper cleanup should all references to an MSGFile instance be removed before the file is closed. OleFileIO doesn't appear to have one, so it's up to us to ensure it is properly closed. Note that the del keyword does not guarantee the immediate deletion of the object, and you should take care to close the file yourself. If this is not possible, importing the gc module and using it's collect method will free the files if your code has no references to them.While the update doesn't add many features, it adds one of the features that has been requested since about the time I joined the module 4 years ago:
While the update doesn't add many features, it adds one of the features that has been requested since about the time I joined the module 4 years ago: The ability to extract embedded MSG files as .msg files. This is one of the more important milestones.
v0.38.0
OleWriter to allow the writing of OLE files, which allows for embedded MSG files to be extracted.MSGFile.export which copies all streams and storages from an MSG file into a new file. This can "clone" an MSG file or be used for extracting an MSG file that is embedded inside of another.MSGFile for getting the OleDirectoryEntry for a storage or stream. This is mainly for use by the OleWriter class.extractEmbedded to Attachment.save (--extract-embedded on the command line) which causes embedded MSG files to be extracted instead of running their save methods.utils.inputToMsgPath (renamed from utils.inputToMsgpath).utils.msgpathToString to utils.msgPathToString.Added option to save function (including MSGFile.saveAttachments) to skip any attachments marked as hidden. This can also be done from the command lin
v0.37.1
MSGFile.saveAttachments) to skip any attachments marked as hidden. This can also be done from the command line with --skip-hidden.MSGFile to be included in the attachment names instead of just strings.Removed MSGFile.mainProperties after deprecating it in v0.36.0.
v0.37.0
InvalidFileFormatError.README to contain documentation on command line option added in previous version.MSGFile.mainProperties after deprecating it in v0.36.0.Properties Intelligence type: ERROR. This type is used when a properties instance is created but has something wrong with it that is not necessarily fatal. Currently the only thing that will cause it is the properties stream being 0 bytes.Documented and exposed to the command line the ability to save the headers to it's own file when saving the msg file. Thanks to martin-mueller-cemas o
v0.36.5
Changed the way wkhtmltopdf is called to patch a possible security vulnerability. This also seems to have fixed [TeamMsgExtractor #291].
v0.36.4
MSGFile.saveRaw that may have existed for a significant amount of time. It was using the wrong function (same name, but with different capitalization) but was hidden until MSGFile stopped being derived from OleFileIO.MessageBase.getSavePdfBody to log the list that is going to be used to run wkhtmltopdf. This is mainly for debugging purposes, to allow users to potentially see why their arguments may be failing.README with more ways to support the module's development.MessageBase.getSavePdfBody not using an fstring which caused it to omit information.wkhtmltopdf is called to patch a possible security vulnerability. This also seems to have fixed [TeamMsgExtractor #291].Added an option to skip the body if it could not be found, rather than throwing an error. This will cause no file to be made for it in the event no va
v0.36.3
skipBodyNotFound and from the command line the option is --skip-body-not-found.[TeamMsgExtractor #286] Fix missing import.
v0.36.2
[TeamMsgExtractor #283] Added file for typing recognition.
v0.36.1
NotImplementedError attachments to at least save everything not related to them. From the command line this would be --skip-not-implemented or --skip-ni. From the save function, this would be the skipNotImplemented option.…of a standard GUID string. This is considered a breaking change and is the reason for the full version increase.
v0.36.0
reportTag property to MessageBase. I noticed this was one of the properties for IPM.Outlook.Recall so I decided to implement it. I'll work on ensuring all of [MS-OXOMSG] and [MS-OXCMSG] are implemented at a later date, including splitting off REPORT into it's own class, because it is it's own class.bool returning properties should have been returning False when they were not found instead of None. Ones that may return None are specifically typed as optional in the source code. Unfortunately using the help command doesn't seem to show the return type for properties for me at least on Python 3.9 and below.Attachment.save returning a pathlib.Path object instead of a str after the conversion to pathlib.pathlib objects in utils.openMsgBulk. It uses glob.glob which cannot take a pathlib object.PermanentEntryID from EntryID.autoCreate. It shares a provider ID with AddressBookEntryID, and as such would never generate from it anyways. If you specifically need a PermanentEntryID you will have to instantiate it manually. Additionally, the entry has been removed from enums.EntryIDType.rawData as the property name.MSGFile to use the same name for Properties instances as all other classes. MSGFile.mainProperties will currently raise a DeprecationWarning instead of outright failing to help ease the transition. Use MSGFile.props instead.[TeamMsgExtractor #280] Fix typing issue in message_base.py.
v0.35.3
message_base.py.Made a change to the argument handling for --no-folders. Since it requires --attachmentsOnly to work, I simply made it error when it's not given to av
v0.35.2
--no-folders. Since it requires --attachmentsOnly to work, I simply made it error when it's not given to avoid confusion.-v to be used instead of --verbose. This allows you to do -vvv for verbosity level 3.Fixed a few property conflicts that I missed in the last release (forgot to run the helper script before releasing).
v0.35.1
[TeamMsgExtractor #206] Implemented full support for Post objects, including the ability to save them.
v0.35.0
Appointment objects to include all of the objects specified in [MS-OXOCAL]. Name changed to AppointmentMeeting. Completed support for Appointment objects, including the ability to save them.mimetype-magic (installable using the mime extra) which helps to identify attachments that do not give a mime-type.allowFallback will change the message to specify that current options were not usable for getting a valid body.extract_msg.constants.NULL_DATE to represent this that you can use in your code to not have to worry about changing your code if we check it.enums.extract_msg.data to submodule extract_msg.structures.python_requires to setup.py as I noticed that it was missing.MessageBase. getSaveXBody functions have also been moved down to be defined in MessageBase. If the extension class needs to specify custom behaviors for creating the save bodies, these functions will need to be overridden.
MessageBase (being the lowest one to currently contain bodies) has a few new properties. These properties represent the injection strings that will be injected into the bodies for the header, with an additional property to specify what properties map to what part of the format string. See MessageBase.headerFormatProperties for more information and an example of how to implement this in your own class.Message into MessageBase for convenience. Message exists now for specific checking and for future specializations. This also means that anything that is a MessageBase now has the entire framework for saving built-in, with easy way to change details.Contact.Contact. Saving, though it exists, is rather minimal and is limited to plain text and HTML.Contact class's properties.Contact properties to better match the microsoft names.
firstName -> givenName.lastName -> surname.businessPhone -> businessTelephoneNumberTask properties being incorrect.Properties.date to only return the submit time. This is to ensure messages that were never sent do not have a sent date.MessageBase.date to only return a send date if the message has been sent. For messages with no flags, it assumes True.SignedAttachment and BaseAttachment more similar by adding properties to each that are shared. BaseAttachment now have a name property and SignedAttachment now have longFilename and shortFilename.__init__ methods from MSG classes that don't change it. This ensures notes are easily passed down.PtypTime is handled, making it a single function in utils.tzlocal, for best results). Included dependencies are beautifulsoup4 and tzlocal.OleFileIO. While I would prefer to do that, the __init__ method for it is rather expensive, and allowing embedded msg files to directly share each other's instances of OleFileIO would improve speed immensely.delayAttachments was False.utils.openMsg now delays attachments while loading the file to get the class type. This means all time for attachments is cut in half as they are only ever loaded once. It also means that files that won't open due to attachments will error a little later, but this shouldn't be a problem.Guid back to constants. This has to do with the next entry.--no-folders to the command line allowing you to save all attachments from a set of MSG files into a single folder.--skip-embedded to the command line to skip saving embedded MSG files.skipEmbedded to Attachment.save (and all other related save methods that call it) to skip saving an embedded MSG file.__main__ so that it opens the zip file there instead of relying on everything it calls to do it again and again.--verbose to allow it to be stacked for more verboseness. Specifying it once turns on warnings, twice for info, and three times for debug. Not specifying it only turns on error logging.Fixed issue that may have caused other olefile types to raise the wrong type of error when passed to openMsg.
v0.34.3
openMsg.MessageBase (and subsequently openMsg) that allows you to override the code being used for deencapsulation. See MessageBase.__init__ for details on how to create an override function.[TeamMsgExtractor #267] Fixed issue that caused signed messages that were .eml files to have their data field *not* be a bytes instance. This field wi
0.34.2
utils.unwrapMultipart that takes a multipart message and acquires a plain text body, an HTML body, and a list of attachments from it. These attachments are returned as dicts that can easily be converted to SignedAttachments. It replaces the logic mailbits was being used for, and as such mailbits is no longer required. The module may be reintroduced in the future.emailMessage to SignedAttachment, which returns the email Message instance used to get data for the attachment.Your coding agent can read these notes before it upgrades. Set up the MCP server →