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