Skip to content

[BUG] MSG file with no properties stream raises deeply nested NoneType error instead of handling it properly. #302

Closed

Description

@piskvorky

Bug Metadata

  • Version of extract_msg: 0.36.1
  • Your python version: Python 3.8
  • How did you launch extract_msg?
    • My command line or
    • I used the extract_msg package

Describe the bug

Opening a message with extract_msg.openMsg(bytes) leads to the traceback below. Cannot share the raw MSG unfortunately.

Traceback

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/msg.py", line 180, in _ensureSet
    return getattr(self, variable)
AttributeError: 'MSGFile' object has no attribute '_classType'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/msg.py", line 553, in areStringsUnicode
    return self.__bStringsUnicode
AttributeError: 'MSGFile' object has no attribute '_MSGFile__bStringsUnicode'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/msg.py", line 720, in props
    return self._prop
AttributeError: 'MSGFile' object has no attribute '_prop'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/utils.py", line 603, in openMsg
    if not msg.classType:
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/msg.py", line 649, in classType
    return self._ensureSet('_classType', '__substg1.0_001A')
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/msg.py", line 183, in _ensureSet
    value = self._getStringStream(streamID)
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/msg.py", line 301, in _getStringStream
    if self.areStringsUnicode:
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/msg.py", line 555, in areStringsUnicode
    if self.props.has_key('340D0003'):
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/msg.py", line 722, in props
    self._prop = Properties(self._getStream('__properties_version1.0'),
  File "/usr/local/lib/python3.8/dist-packages/extract_msg/properties.py", line 26, in __init__
    self.__len = len(data)
TypeError: object of type 'NoneType' has no len()

Activity

  1. TheElementalOfDestruction commented on Nov 17, 2022

    @TheElementalOfDestruction
    Collaborator

    I see you've now reported two different issues and both have an unfortunately unclear title. In the case of tracebacks like the one you have, it's usually going to be the last error raised that is the important one, in this case that your file had no properties stream, something the module doesn't handle in any way.

    I'll double check when I have a chance, but I believe that stream is listed as being mandatory for msg files. If it is, then it should be throwing a different exception, and something is very wrong with your msg file.

  2. changed the title [-]AttributeError: 'MSGFile' object has no attribute '_classType'[/-] [+][BUG] MSG file with no properties stream raises deeply nested NoneType error instead of handling it properly.[/+] on Nov 18, 2022
  3. added
    In ProgressThis issue or feature request has been confirmed or approved, respectively, and is being worked on.
    on Nov 18, 2022
  4. TheElementalOfDestruction commented on Nov 18, 2022

    @TheElementalOfDestruction
    Collaborator

    Confirmed, you have a bad MSG file. The properties stream is mandatory, as stated here in the documentation:
    image

    I'll make it so that it raises a proper error instead of giving a weird None type error, but something is very wrong with the provided file.

    If you'd like me to take a closer look at the file, you can send me the list of streams inside of the file, which should not contain any personal data of any kind, just the names of the internal files. You can censor any that you feel are sensitive, but if it is actually meant to be a message file then the streams should just be the names of the properties contained, rather than the values of any of the properties. You can do this with the olefile module, a dependency of this one.

    The following code will print out all of the streams in the file represented by the raw bytes. Given that the file managed to get past opening as an olefile, this should still work.

    import olefile
    
    with olefile.OleFileIO(rawBytes) as ole:
        for x in ole.listdir():
            print(x)
  5. added a commit that references this issue on Nov 18, 2022
  6. TheElementalOfDestruction commented on Nov 18, 2022

    @TheElementalOfDestruction
    Collaborator

    Fixed in 0.37.0. It now raises a much more clear exception.

  7. piskvorky commented on Nov 18, 2022

    @piskvorky
    Author

    Excellent, thank you!

    Yes, it's quite possible that I have a malformed MSG – many of them even, unfortunately. #294 is also mine :)

    I choose ticket titles in hopes that they will help others discover them in the future, when they google for the error message… like I did before opening the ticket. TypeError: object of type 'NoneType' has no len() was too generic.

    Of course your analysis is deeper and title more descriptive. I didn't know the root cause when I created the ticket. Thanks for clarifying.

  8. TheElementalOfDestruction commented on Nov 18, 2022

    @TheElementalOfDestruction
    Collaborator

    The first error could in theory lead to any number of other errors as it was in the process of being handled. And much of the code here uses try except blocks that end up occurring inside one another, as you can see. That's why I say the last error, the one that happened most recently and was ultimately the result that the code couldn't continue past, is usually the most important, as it will typically either by an error that wasn't expected to happen at all or an error being explicitly raised.

    I actually can't really think of any situation where I start from the top of the traceback (and traceback stack) instead of the very bottom

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

In ProgressThis issue or feature request has been confirmed or approved, respectively, and is being worked on.bug

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions