Theresa O’Connor

Simple composition of HTML emails in Emacs using Markdown

Suppose you'd like to compose HTML emails1 in Emacs' message-mode.2 An HTML email is really just a MIME message with two parts: a text/plain part and its text/html alternative. Creating a MIME message [by hand] is boring and non-trivial. Therefore, [Emacs includes a] library called mml[…] that parses a language called MML and generates MIME messages. You can read the gory mml details in (emacs-mime) Composing. For now, though, consider this sample document:

<#multipart type=alternative>
hello, world
<#part type=text/html>
<html>
  <head>
    <title>HTML version of email</title>
  </head>
  <body>
    <p>hello, world</p>
  </body>
</html>
<#/multipart>

OK, this looks doable, but for one big, glaring problem: you have to write, by hand, both the text and HTML versions of the email. Holy redundant redundancy, Batman!

Enter Markdown. It's a text-to-HTML conversion tool [that] allows you to write using an easy-to-read, easy-to-write plain text format[.] Check it (emphasis mine):

The overriding design goal for Markdown’s formatting syntax is to make it as readable as possible. The idea is that a Markdown-formatted document should be publishable as-is, as plain text, without looking like it’s been marked up with tags or formatting instructions. While Markdown’s syntax has been influenced by several existing text-to-HTML filters, the single biggest source of inspiration for Markdown’s syntax is the format of plain text email.

If you're used to composing plain text emails, your existing writing habits are probably pretty close to Markdown, so it shouldn't be too hard to learn. So what we'd like to do is to simply use Markdown syntax for the text part, and then use a Markdown→HTML processor to generate the HTML section for us.

The first thing I did was to quickly hack up a command-line tool, mimedown, which takes Markdown-formatted text on stdin, and spits out mml containing both the text and HTML versions on stdout. I used the Python markdown library, which you can download from SourceForge.

#!/usr/bin/env python
# mimedown - generate multipart text and HTML MIME message from Markdown input.

import markdown

def mimedown(input, output):
    text = input.read()
    html = markdown.Markdown(text, safe_mode=False).toString()
    html = "<htm><head><title></title><body>%s</body></html>" % html
    print >> output, '''<#multipart type=alternative>
%s
<#part type=text/html>
%s
<#/multipart>
''' % (text, html)

if __name__ == '__main__':
    import sys
    mimedown(sys.stdin, sys.stdout)

The next step is to hook this into message-mode somehow. Here's a mimedown command which runs the message body through mimedown:

(defun mimedown ()
  (interactive)
  (save-excursion
    (message-goto-body)
    (shell-command-on-region (point) (point-max) "mimedown" nil t)))

There you have it. You can now compose HTML emails in Emacs with Markdown. Share and Enjoy!

Notes

  1. Before you get angry, know that generally, I'm against the use of HTML email.
  2. Emacs ships with two mail composition modes, mail-mode and message-mode. I read mail with Gnus, which uses message-mode by default. Also, message-mode's support for MIME composition is much, much better than that of mail-mode.