Skip to content
Patrick Totzke edited this page Feb 2, 2020 · 1 revision

As of version 0.9, alot has rudimentary features to add, edit and remove HTML alternatives to plaintext message contents. This is done using txt2html and html2txt commands in envelope mode.

Overview

Envelopes store both html and plaintext alternatives until you send a mail. If at that time, a html body text is present, alot will create a text/multipart message that contains both these texts. Most MUAs on the receiving end will display only the html part.

No HTML part is initially present for envelopes, and if there is one, you can remove it using the (envelope mode) command removehtml. To change which part alot shows in envelope mode you can use the display command: display html switches to HTML and display plaintext switches to displaying the envelope's plaintext.

To add a HTML part, use the txt2html command. It will pipe your plaintext message body through a pre-defined shell script and add the resulting text as HTML part to the envelope. The defaultshell command to use is read from the config setting envelope_txt2html, but you can also just give it as a parameter to the txt2html command directly (see bottom of this page for an example).

The command html2txt works analogously, but translates the HTML text back into a plaintext alternative and overwrites the current one in the envelope. You can directly edit the HTML part by passing a parameter to the edit command: edit --part=plaintext.

Markdown to HTML

I write emails in pandoc's Markdown and generate HTML from it like so:

envelope_txt2html = "pandoc -f markdown -t html -s --self-contained"
envelope_html2txt = "pandoc -t markdown -f html"

Pandoc templates

Pandoc allows to adjust the template HTML to use and I've found this pretty awesome one for myself.

To use it, download the template file and store it as ~.pandoc/templates/email.html5. Then adjust alot's txt2html command as follows.

envelope_txt2html = "pandoc -f markdown -t html -s --self-contained --template=email.html5"

I actually keep several templates around and have bindings for txt2html with different templates. For example, I use a template called email-official.html5 that includes a fancy signature.

previewing outgoing emails

I use and external browser to preview the generated HTML parts before sending emails.

This is not part of mailine alot but uses a hook. My code is below.

import alot
import tempfile
import webbrowser
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)
    return None


# 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...")
    cb = ui.current_buffer
    htmlstr = None
    if isinstance(cb, alot.buffers.EnvelopeBuffer):
        htmlstr = cb.envelope.body_html
    elif isinstance(cb, alot.buffers.ThreadBuffer):
        msg = ui.current_buffer.get_selected_message()
        htmlstr = _get_raw_html(msg)
    if htmlstr == None:
        ui.notify("no html part found")
        return

    temp = tempfile.NamedTemporaryFile(prefix="alot-",suffix=".html",
                                       delete=False)
    temp.write(htmlstr.encode("utf-8"))
    temp.flush()
    temp.close()
    webbrowser.open(temp.name)

Full related configs

envelope_txt2html = "pandoc -f markdown -t html -s --self-contained --template=email.html5"
envelope_html2txt = "pandoc -t markdown -f html"

[bindings]
  [[envelope]]
  enter = "edit --part=plaintext; txt2html; display html"
  ', b' = "call hooks.open_in_browser(ui)"
  '_' = "txt2html pandoc -f markdown -t html -s --self-contained --template=email-official.html5; display html"