This commit is contained in:
Jonathan Wyss 2024-09-10 17:21:37 +02:00
parent 470a981bdd
commit a08f45a3f3
3 changed files with 2499 additions and 64 deletions

View File

@ -1,71 +1,50 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Based on:
# https://docs.python.org/3/library/email-examples.html
import sys
import os
import alot
import tempfile
import mimetypes
import webbrowser
from email import policy
from email.parser import BytesParser
from alot.helper import string_sanitize
from alot.helper import string_decode
# Helper method to extract the raw html part of a message. Note that it
# only extracts the first text/html part found.
def _get_raw_html(msg):
mail = msg.get_email()
for part in mail.walk():
ctype = part.get_content_type()
if ctype != "text/html":
continue
cd = part.get('Content-Disposition', '')
if cd.startswith('attachment'):
continue
enc = part.get_content_charset() or 'utf-8'
raw = string_decode(part.get_payload(decode=True), enc)
return string_sanitize(raw), enc
return None, None
raw = sys.stdin.buffer.read()
# Opens HTML emails in an external browser.
# Related issue:
# - https://github.com/pazz/alot/issues/1153
def open_in_browser(ui=None):
ui.notify("Opening message in browser...")
msg = ui.current_buffer.get_selected_message()
if not os.isatty(0):
fd = os.open('/dev/tty', os.O_RDONLY)
if fd < 0:
sys.stderr.write('Unable to open an input tty.\n')
sys.exit(-1)
else:
os.dup2(fd, 0)
os.close(fd)
htmlstr, enc = _get_raw_html(msg)
msg = BytesParser(policy=policy.default).parsebytes(raw)
if htmlstr == None:
ui.notify("Email has no html part")
return
# 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:
# The magic_html_parser has to rewrite the href="cid:...." attributes to
# point to the filenames in partfiles. It also has to do a safety-sanitize
# of the html. It could be written using html.parser.
template = """
<!DOCTYPE html><html>
<head><meta charset="utf-8"></head>
<body>{}</body>
</html>
"""
f.write(template.format(body.get_content()))
webbrowser.open(f.name)
# os.remove(f.name)
for fn in partfiles.values():
os.remove(fn)
temp = tempfile.NamedTemporaryFile(prefix="alot-",suffix=".html",
delete=False)
temp.write(htmlstr.encode(enc))
temp.flush()
temp.close()
webbrowser.open(temp.name)

1
kitty-themes Submodule

@ -0,0 +1 @@
Subproject commit b1abdd54ba655ef34f75a568d78625981bf1722c

2455
kitty.conf Normal file

File diff suppressed because it is too large Load Diff