multipart messages can be nested within each other

An example of something that does this is GPG, when operating in PGP/MIME
mode.

The Python documentation remarks that an attachment is anything that isn't
a body - meaning that if there are multipart messages nested within each
other, the containers will be flagged as an attachment.

When get_content() is called on the attachment, it fails with an unhandled
KeyError as there is no attachment handler for multipart.

This change wraps the get_content() call in a try...catch, and returns if
an attachment type unsupported by the runtime is present.

```
Traceback (most recent call last):
  File "/Users/adamb/mail_to_misp/tests/tests.py", line 89, in test_nested_mime
    self.mail2misp.process_email_body()
  File "./mail2misp/mail2misp.py", line 188, in process_email_body
    self._find_attached_forward()
  File "./mail2misp/mail2misp.py", line 88, in _find_attached_forward
    attachment_content = attachment.get_content()
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/email/message.py", line 1096, in get_content
    return content_manager.get_content(self, *args, **kw)
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/email/contentmanager.py", line 25, in get_content
    raise KeyError(content_type)
KeyError: 'multipart/mixed'
```
pull/42/head
Adam Bishop 2020-06-07 00:16:17 +01:00
parent 721d806e8d
commit 8c2777585a
2 changed files with 13 additions and 1 deletions

View File

@ -85,7 +85,12 @@ class Mail2MISP():
def _find_attached_forward(self):
forwarded_emails = []
for attachment in self.original_mail.iter_attachments():
attachment_content = attachment.get_content()
try:
attachment_content = attachment.get_content()
except KeyError:
# Attachment type has no handler
continue
# Search for email forwarded as attachment
# I could have more than one, attaching everything.
if isinstance(attachment_content, message.EmailMessage):

View File

@ -82,6 +82,13 @@ class TestMailToMISP(unittest.TestCase):
self.assertEqual(self.mail2misp.misp_event.analysis, '0')
self.mail2misp.add_event()
def test_nested_mime(self):
config = importlib.import_module('tests.config_forward')
self.mail2misp = Mail2MISP('', '', '', config=config, offline=True)
with open('tests/mails/test_nested_mime.eml', 'rb') as f:
self.mail2misp.load_email(BytesIO(f.read()))
self.mail2misp.process_email_body()
self.assertEqual(self.mail2misp.clean_email_body, 'example.org\r\nwww.example.org\r\n')
if __name__ == '__main__':
unittest.main()