• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import os
2import sys
3import tempfile
4import mimetypes
5import webbrowser
6
7# Import the email modules we'll need
8from email import policy
9from email.parser import BytesParser
10
11# An imaginary module that would make this work and be safe.
12from imaginary import magic_html_parser
13
14# In a real program you'd get the filename from the arguments.
15with open('outgoing.msg', 'rb') as fp:
16    msg = BytesParser(policy=policy.default).parse(fp)
17
18# Now the header items can be accessed as a dictionary, and any non-ASCII will
19# be converted to unicode:
20print('To:', msg['to'])
21print('From:', msg['from'])
22print('Subject:', msg['subject'])
23
24# If we want to print a preview of the message content, we can extract whatever
25# the least formatted payload is and print the first three lines.  Of course,
26# if the message has no plain text part printing the first three lines of html
27# is probably useless, but this is just a conceptual example.
28simplest = msg.get_body(preferencelist=('plain', 'html'))
29print()
30print(''.join(simplest.get_content().splitlines(keepends=True)[:3]))
31
32ans = input("View full message?")
33if ans.lower()[0] == 'n':
34    sys.exit()
35
36# We can extract the richest alternative in order to display it:
37richest = msg.get_body()
38partfiles = {}
39if richest['content-type'].maintype == 'text':
40    if richest['content-type'].subtype == 'plain':
41        for line in richest.get_content().splitlines():
42            print(line)
43        sys.exit()
44    elif richest['content-type'].subtype == 'html':
45        body = richest
46    else:
47        print("Don't know how to display {}".format(richest.get_content_type()))
48        sys.exit()
49elif richest['content-type'].content_type == 'multipart/related':
50    body = richest.get_body(preferencelist=('html'))
51    for part in richest.iter_attachments():
52        fn = part.get_filename()
53        if fn:
54            extension = os.path.splitext(part.get_filename())[1]
55        else:
56            extension = mimetypes.guess_extension(part.get_content_type())
57        with tempfile.NamedTemporaryFile(suffix=extension, delete=False) as f:
58            f.write(part.get_content())
59            # again strip the <> to go from email form of cid to html form.
60            partfiles[part['content-id'][1:-1]] = f.name
61else:
62    print("Don't know how to display {}".format(richest.get_content_type()))
63    sys.exit()
64with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
65    # The magic_html_parser has to rewrite the href="cid:...." attributes to
66    # point to the filenames in partfiles.  It also has to do a safety-sanitize
67    # of the html.  It could be written using html.parser.
68    f.write(magic_html_parser(body.get_content(), partfiles))
69webbrowser.open(f.name)
70os.remove(f.name)
71for fn in partfiles.values():
72    os.remove(fn)
73
74# Of course, there are lots of email messages that could break this simple
75# minded program, but it will handle the most common ones.
76