forked from akkana/scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
viewhtmlmail
executable file
·126 lines (102 loc) · 4.61 KB
/
viewhtmlmail
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#! /usr/bin/env python
# Take an mbox HTML message (e.g. from mutt), split it
# and rewrite it so it can be viewed in an external browser.
# Can be run from within a mailer like mutt, or independently
# on a single message file.
#
# Usage: viewhtmlmail
#
# Inspired by John Eikenberry <[email protected]>'s view_html_mail.sh
# which sadly no longer works, at least with mail from current Apple Mail.
#
# Copyright 2013 by Akkana Peck. Share and enjoy under the GPL v2 or later.
# Changes:
# Holger Klawitter 2014: create a secure temp file and avoid temp mbox
# To use it from mutt, put the following lines in your .muttrc:
# macro index <F10> "<pipe-message>~/bin/viewhtmlmail\n" "View HTML in browser"
# macro pager <F10> "<pipe-message>~/bin/viewhtmlmail\n" "View HTML in browser"
import os, sys
import re
import time
import shutil
import email, mimetypes
import tempfile
def view_html_message(tmpdir):
msg = email.message_from_string(sys.stdin.read())
html_part = None
counter = 1
subfiles = []
for part in msg.walk():
# print ""
# part has, for example:
# items: [('Content-Type', 'image/jpeg'), ('Content-Transfer-Encoding', 'base64'), ('Content-ID', '<[email protected]>'), ('Content-Disposition', 'attachment; filename="ATT0001414.jpg"')]
# keys: ['Content-Type', 'Content-Transfer-Encoding', 'Content-ID', 'Content-Disposition']
# values: ['image/jpeg', 'base64', '<[email protected]>', 'attachment; filename="ATT0001414.jpg"']
# multipart/* are just containers
#if part.get_content_maintype() == 'multipart':
if part.is_multipart() or part.get_content_type == 'message/rfc822':
continue
if part.get_content_subtype() == 'html':
if html_part:
print "Eek, more than one html part!"
html_part = part
# Save it to a file in the temp dir.
filename = part.get_filename()
if not filename:
ext = mimetypes.guess_extension(part.get_content_type())
if not ext:
# Use a generic bag-of-bits extension
ext = '.bin'
filename = 'part-%03d%s' % (counter, ext)
# Applications should really sanitize the given filename so that an
# email message can't be used to overwrite important files.
# As a first step, guard against ../
if '../' in filename:
print "Eek! Possible security problem in filename", filename
continue
filename = os.path.join(tmpdir, filename)
# print "%10s %5s %s" % (part.get_content_type(), ext, filename)
# Mailers may use Content-Id or Content-ID (or, presumably, various
# other capitalizations). So we can't just look it up simply.
content_id = None
for k in part.keys():
if k.lower() == 'content-id':
# Remove angle brackets, if present.
# part['Content-Id'] is unmutable -- attempts to change it
# are just ignored -- so copy it to a local mutable string.
content_id = part[k]
if content_id.startswith('<') and content_id.endswith('>'):
content_id = content_id[1:-1]
subfiles.append({ 'filename': filename,
'Content-Id': content_id })
counter += 1
fp = open(filename, 'wb')
fp.write(part.get_payload(decode=True))
# print "wrote", os.path.join(tmpdir, filename)
fp.close()
break # no need to look at other keys
if not content_id:
print filename, "doesn't have a Content-Id, not saving"
# print "keys:", part.keys()
# for sf in subfiles:
# print sf
# We're done saving the parts. It's time to save the HTML part.
htmlfile = os.path.join(tmpdir, "viewhtml.html")
fp = open(htmlfile, 'wb')
htmlsrc = html_part.get_payload(decode=True)
# Substitute all the filenames for CIDs:
for sf in subfiles:
htmlsrc = re.sub('cid: ?' + sf['Content-Id'],
'file://' + sf['filename'],
htmlsrc, flags=re.IGNORECASE)
fp.write(htmlsrc)
fp.close()
# Now we have the file. Call firefox on it.
print "Calling firefox for file://" + htmlfile
os.system("firefox -new-window file://" + htmlfile)
# Wait a while to make sure firefox has loads the imgaes, then clean up.
time.sleep(6)
shutil.rmtree(tmpdir)
if __name__ == '__main__':
tmpdir = tempfile.mkdtemp()
view_html_message(tmpdir)