Folks,
I need to start sending out text/html alternative parts to my messages with mutt. However, this is a rabbit hole, so if you’re afraid of those, stop reading now.
My requirements are, in decreasing order of priority:
- Compatible with all Gmail, Outlook, Hotmail, Apple Mail, Thunderbird, and whatever else many people are using these days.
- Markdown processing of
text/plain
multipart/alternative result, MIME compliant
- Attachments
- Sensible integration with mutt
- PGP signatures
- Inline images
and after surveying the field, and spending hours with the solutions I found during various web searches, I am writing in to you for some feedback, input, guidance, psycological help, and maybe even some hugs.
Since I expect (hope) there to be some insights gained from our discussion, I am going to keep updating an online version of this text.
The main question for me is: when and how is the best way to add that HTML part such that messages can be signed, encrypted, and attachments are available to all viewers?
What is the problem I’m trying to solve?
My current solution, which runs as part of the $sendmail pipeline and thus converts the message as sent by mutt to a message with a MIME tree as follows:
I 1 <no description> [multipa/alternativ, 7bit, 111K]
I 2 ├─><no description> [multipa/signed, 7bit, 110K]
I 3 │ ├─><no description> [multipa/mixed, 7bit, 109K]
I 4 │ │ ├─><no description> [text/plain, quoted, utf-8, 0,4K]
A 5 │ │ └─>Brochure.pdf [applica/pdf, base64, 108K]
I 6 │ └─>PGP signature [applica/pgp-signat, 7bit, 1,1K]
I 7 └─><no description> [text/html, quoted, utf-8, 0,7K]
This works fine with mutt, obviously, and Gmail also seems to be okay with it, but Thunderbird doesn’t give access to the attachments, and in a way that makes sense, because I am advertising the text/html part that contains no attachments as a better alternative (better because later in the tree, cf. RFC 1341) to the whole multipart/signed container.
The reason for that, rather than wrapping the text/plain part in a multipart/alternative container, and slap the text/html part into there is simply that then the PGP signature would be invalidated.
The signature also gets invalidated, if I moved the attachments out like this:
multipart/mixed
├─>multipart/alternative
│ ├─>multipart/signed
│ │ ├─>text/plain
│ │ └─>application/pgp-signature
│ └─>text/html
└─>application/pdf
So in order to make the text/html part a true alternative, it needs to be converted into a multipart/mixed part encompassing the text/html , as well as the attachment. But given that MIME doesn’t have pointers or “symlinks”, allowing me to reference other parts of the tree, the only way to do this from here on (without rethinking how I’m approaching this, more on that below) would be to duplicate the attachments into a multipart/mixed part wrapping the text/html alternative. And that’d be a terrible waste of resources, and would hit max-size limits on SMTP transactions a lot more often.
What are some other solutions you’ve considered?
Converting text to HTML prior to sending
There are plenty of solutions that filter the text/plain part once created in mutt, and turn it into HTML, replacing the text/plain part with a text/html part. This is not good enough, because I often remember something to change at the very last minute, and I also don’t want to keep just-HTML mails in my sent-mail, because I often use commands like resend-message , which would then fire up Vim on the text/html content in my setup.
Not signing/encrypting messages
If I do not sign messages, my tool does the right thing. However, this comes with the price tag that I no longer get to sign my messages, which I’ve done pretty consistently for 25 years. This is not really an option.
Obviously, encrypting messages in mutt also won’t work, because then the Markdown processor cannot actually obtain the text/plain part.
Signing/encrypting messages after post-processing
Conceivably, I could convert a multipart/alternative into a signed or encrypted message after my script processes the text/plain part and adds the text/html alternative.
It’s even conceivable that I use mutt’s pgp_sign_command not to sign, but instead add metadata that I can use later in the pipe to do the actual PGP operation non-interactively, but I suspect that this will get messy very quickly.
What does the ideal solution look like?
It would of course be ideal if mutt gave me a means to post-process an entire message after writing it to the $record folder, and before it invokes the interactive PGP stuff on it. This probably won’t be terribly hard to implement, but I haven’t even looked at the source code yet.
A central question is whether mutt should save the multipart/alternative message, i.e. including the text/html part to the sent folder ($record ), or whether the auto-generated text/html part should only be added to the outgoing message. This probably needs to be made configurable, as some people will want it one way, and others another.
On this note, however, I noticed that mutt already has $fcc_store , and if that is unset, then mutt is already doing different things for the messages it stores to the $record folder, and the messages it sends, because while the messages sent include attachments in the multipart/signed container, the locally-recorded messages are signed, but do not contain the attachments, and so they must actually get signed separately.
To me, this suggests that mutt forks message processing, at least if $fcc_store is unset (and maybe even if it’s set), which is good because now the aforementioned message post-processor can either be invoked before the fork, to keep a record of the multipart/alternative message, or after the fork and only in the branch handling the outgoing message (not the locally saved one).
If we keep a local copy of the multipart/alternative messages, then mutt needs to also learn how to handle such messages in the contact of e.g. resend-message , because currently, invoking that command on a multipart/alternative message will result in the MIME-encoded contents of the entire container being loaded in the editor, i.e.
--b2_50d94a6352b6c4c7225dabd5881a79d4
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
foo
--b2_50d94a6352b6c4c7225dabd5881a79d4
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<p>foo</p>
--b2_50d94a6352b6c4c7225dabd5881a79d4
and that’s not very useful, but could probably be addressed by dispensing with the text/html part, if mutt is configured to auto-generate it during sending anyway.
I’m looking forward to your thoughts on all this. Maybe I’m totally overthinking this. In any case, given how email has changed in the last 20 years, and how text/plain messages are causing display issues across different device types (e.g. they are not “responsive”), maybe it’s time that the least sucky of all mail clients gets a little less sucky about generating messages that are increasingly being read on mobile devices, or by users who think that bold face and images were a feature of SMTP all along.
Best regards,
-- @martinkrafft | https://riot.im/app/#/room/#madduck:madduck.net "you grabbed my hand and we fell into it, like a daydream - or a fever." -- godspeed you black emperor! spamtraps: madduck.bo...@madduck.net
|