The Design of Mailprint

I wrote a tool, Mailprint, for printing out nice-looking emails from Mutt and other classic Mail user agents.

(You might remember from the last article that I have recently spent some time to polish my e-mail setup for kernel development. While this is not the hip thing to do any more, some of those mails are difficult to understand, and I occasionally print them out.)

This article describes Mailprint’s internals and design philosophy. I’m fond of this approach, because it fits nicely into the UNIX environment and is reusable.

If you are interested in using Mailprint, you can find its homepage at

Design philosophy

Orthogonal software design, in the UNIX-style, building one tool for each task, is great. This applies in particular to side-projects, because it is a way to achieve a lot more with less work.

Mailprint is a tool which could have existed in similar form in the 80s already.

It makes use of a pipeline of other tools to do its job:

Interface to the outside

To the outside, Mailprint is designed to be used as part of a UNIX pipeline, reading a plain text email and outputting PDF:

cat ~/.Mail/Inbox/cur/foobar123 | mailprint > out.pdf
email mailprint PDF

This makes it easy to hook up Mailprint to mutt and other classic MUAs.

Internal design

Internally, Mailprint generates groff source code in the “mom” dialect from the input email and feeds it through a UNIX pipeline of processing tools:

email parse email headers, body convert email to groff mom (groff source) preconv mom (sanitized Unicode) groff -mom -Tpdf PDF sender address look up face filename ImageMagick convert PDF file mailprint

The steps implemented in Go are:

The remaining steps are accomplished by invoking external UNIX programs:

The pipeline is invoked from Mailprint’s top-level run() function. (code)

Turning it inside-out

If you want to build a more custom Mailprint pipeline, you can also make Mailprint expose its groff intermediary format using the -output.format=mom option, and chain it with groff yourself:

mailprint -face.picon=false -output.format=mom | preconv | groff -mom -Tpdf | lpr
email parse email headers, body convert email to groff mom (groff source) preconv mom (sanitized Unicode) groff -mom -Tpdf PDF mailprint -output.format=mom -face.picon=false