| import os | |
| import sys | |
| import tempfile | |
| import mimetypes | |
| import webbrowser | |
| # Import the email modules we'll need | |
| from email import policy | |
| from email.parser import BytesParser | |
| def magic_html_parser(html_text, partfiles): | |
| """Return safety-sanitized html linked to partfiles. | |
| Rewrite the href="cid:...." attributes to point to the filenames in partfiles. | |
| Though not trivial, this should be possible using html.parser. | |
| """ | |
| raise NotImplementedError("Add the magic needed") | |
| # In a real program you'd get the filename from the arguments. | |
| with open('outgoing.msg', 'rb') as fp: | |
| msg = BytesParser(policy=policy.default).parse(fp) | |
| # Now the header items can be accessed as a dictionary, and any non-ASCII will | |
| # be converted to unicode: | |
| print('To:', msg['to']) | |
| print('From:', msg['from']) | |
| print('Subject:', msg['subject']) | |
| # If we want to print a preview of the message content, we can extract whatever | |
| # the least formatted payload is and print the first three lines. Of course, | |
| # if the message has no plain text part printing the first three lines of html | |
| # is probably useless, but this is just a conceptual example. | |
| simplest = msg.get_body(preferencelist=('plain', 'html')) | |
| print() | |
| print(''.join(simplest.get_content().splitlines(keepends=True)[:3])) | |
| ans = input("View full message?") | |
| if ans.lower()[0] == 'n': | |
| sys.exit() | |
| # We can extract the richest alternative in order to display it: | |
| richest = msg.get_body() | |
| partfiles = {} | |
| if richest['content-type'].maintype == 'text': | |
| if richest['content-type'].subtype == 'plain': | |
| for line in richest.get_content().splitlines(): | |
| print(line) | |
| sys.exit() | |
| elif richest['content-type'].subtype == 'html': | |
| body = richest | |
| else: | |
| print("Don't know how to display {}".format(richest.get_content_type())) | |
| sys.exit() | |
| elif richest['content-type'].content_type == 'multipart/related': | |
| body = richest.get_body(preferencelist=('html')) | |
| for part in richest.iter_attachments(): | |
| fn = part.get_filename() | |
| if fn: | |
| extension = os.path.splitext(part.get_filename())[1] | |
| else: | |
| extension = mimetypes.guess_extension(part.get_content_type()) | |
| with tempfile.NamedTemporaryFile(suffix=extension, delete=False) as f: | |
| f.write(part.get_content()) | |
| # again strip the <> to go from email form of cid to html form. | |
| partfiles[part['content-id'][1:-1]] = f.name | |
| else: | |
| print("Don't know how to display {}".format(richest.get_content_type())) | |
| sys.exit() | |
| with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: | |
| f.write(magic_html_parser(body.get_content(), partfiles)) | |
| webbrowser.open(f.name) | |
| os.remove(f.name) | |
| for fn in partfiles.values(): | |
| os.remove(fn) | |
| # Of course, there are lots of email messages that could break this simple | |
| # minded program, but it will handle the most common ones. |