The mhbuild directives I want for sending MIME attachments with MH

February 22, 2021

I use and like (N)MH for any number of reasons (it's a very Unix and command line focused mail system, although I often use it with exmh). However, for my sins I sometimes have to send people email with (MIME) attachments of things like PDFs and images, especially these days when I can't just give them physical printouts. This is possible in NMH, but the manual page for mhbuild, the core program you need to do this, is both relatively opaque and full of discussions about things that I mostly don't care about. Since I always wind up picking painfully through the mhbuild manpage when I need it, today I'm going to write down the magic directives you (I) need and also the simpler way that I discovered while writing this entry.

Suppose that we start with a FILE.PDF that we want to send. Our end goal is to wind up with an attachment that as at least the following MIME headers:

Content-Type: application/pdf; name="FILE.PDF"
Content-Disposition: attachment; filename="FILE.PDF"
Content-Transfer-Encoding: base64

In theory the 'name="..."' on the Content-Type is unnecessary and only exists for historical reasons. In practice, it's common practice in MIME messages to put the filename in both places. You can also have a Content-Description, and optionally a Content-ID, which I think is generally irrelevant for attachments.

The simple and often sufficient way to add one or more attachments to your message is to list them as Attach headers in your draft (and then use the 'mime' command in whatnow to activate all of mhbuild's processing). The format of these is simply:

Attach: /path/to/some/FILE.PDF

If NMH can get the MIME type right, this will do just what you want (including providing a Content-Description that's the base filename without its directory). Even if it gets the MIME type wrong, you can fix that by editing the Content-Type: by hand afterward, and for that matter you can edit the file name (in all its places) if you would like your recipient to see a different file name than you have locally. In a lot of cases I think this will be good enough for what I want to attach, especially if I rename my PDFs before hand.

(I didn't discover about Attach until now for many reasons, including that the mhbuild manpage doesn't exactly encourage extensively and carefully reading of all of it. It's very MH manpage-y, for better or worse.)

The more complex way is to use a mhbuild directive to specify everything you want. The mhbuild manpage has a lot to say about directives, but much of it is for complicated and odd cases that I don't care about. The format we want for attaching files is:

#application/pdf; name="FILE.PDF" <> {attachment; filename="FILE.PDF"} /path/argle.pdf

(Notice that this example renames the PDF; it is argle.pdf on the filesystem, but the recipient will see it called FILE.PDF.)

For my future reference, this directive breaks down as follows. The first part becomes the Content-Type. The <> tells mhbuild to not generate a Content-ID, which is generally surplus. The {...} becomes the Content-Disposition. We're specifying the filename MIME parameter here, but you can leave it out if you're happy with the recipient seeing your local file name (this is the same as with Attach). If you leave out the '{ ... }' portion entirely, the result will have no Content-Disposition header.

If you want to go the extra distance you can also also provide a Content-Description by using [...], square brackets, as in '[Amazon purchase invoice #10]'. This goes after the <> and before the {...} (or before the filename, if you leave out the {...}). I don't know how many mail clients show or care about the Content-Description; it's not all that common in my saved mail, and most of the time it's just another copy of the file name.

Given all of this, the minimal version is:

#application/pdf <> {attachment} /path/to/FILE.PDF

This will have no 'name=' parameter on the Content-Type, but will have a 'filename=' parameter on the Content-Disposition so the recipient's mail client will probably let them save it under some useful name. If you're not sure what MIME type some file should be, you can use 'file --mime' to see what it thinks or default to application/octet-stream. If you do the latter, you'll be in good company; we see plenty of attachments on incoming legitimate email that have been defaulted that way even when there are more applicable MIME types.

Written on 22 February 2021.
« How I set up testing alerts in our Prometheus environment
How (and where) Prometheus alerts get their labels »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Mon Feb 22 23:06:37 2021
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.