Insert Cc and Bcc Mail Headers Conditionally in Emacs message-mode
In my Emacs email setup (notmuch.el
using message-mode
), I had this for the longest time:
(setq message-default-mail-headers "Cc: \nBcc: \n")
It would insert Cc and Bcc headers into email composition buffers so that I could quickly edit these fields.
However, the message-default-mail-headers
insertion is done unconditionally, so when replying to mail with people receiving a carbon copy, I would end up with two such header lines:
To: ada@example.com
Cc: bob@example.com
Cc:
Bcc:
The empty Cc/Bcc lines usually don’t cause trouble, unless there’s already a Cc/Bcc line – then some mail servers reject the email. Spam protection or something. It was not supposed to be this way, and multiple Cc header lines were permitted:
This specification permits multiple occurrences of most fields. —RFC 822, Section 4.1, 1982
See?
But here we are, post-2001, when RFC 2822 deviates with min/max occurrences. I didn’t know! So how do we get there?
Looking at the variable’s origin in code, it says this variable is intended to ease migration from mail-mode. That alerted me to look just above that declaration and find message-default-headers
, which accepts a function.
The message-mode
manual on “Message Headers” doesn’t offer any more detail on that, but my experiments show that when message-default-headers
is called, the mail composition buffer only contains From, To, Subject, and that’s it. No --
to separate header from content, no signature, yet. So I can check whether Cc/Bcc header lines exist:
(defun ct/message-insert-headers ()
"Inserts CC/BCC headers, but only if they aren't already present."
(let* ((headers (buffer-substring-no-properties (point-min) (point-max)))
(additions (list
(unless (string-match "^Cc:" headers) "Cc: \n")
(unless (string-match "^Bcc:" headers) "Bcc: \n"))))
(string-join additions)))
(setopt message-default-headers #'ct/message-insert-headers)
Well, “insert” is a lie, the function returns the headers, but for the intended use it’s fine with me.
I can perceive a brief flash of changes when composing emails: the buffer appears, then something happens and is inserted immediately. That didn’t happen before – but the call site looks like it would run this (new to me) function before inserting the (previously used) string message-default-mail-headers
. So that’s a mystery I can live with.
During all of this, I noticed that message.el
is nested in the gnus/
directory. I didn’t realize that this originated in the Gnus newsreader project.