Have You Ever Sent an Email with a File Attachment that is Located on a Server?

Today was a day of convergence.

Our home server/NAS had a lot of SATA-related kernel errors and drive failures in the past weeks that I couldn’t track down. I replaced the drive and the cables and things have quieted down. This means I was SSH’ing into the server quite a bit this month. Mild data loss ans corrupted file systems included.

So when I was asked to send a potentially corrupted backup record file that prevents Arq for Mac from backing up anything, I did the straight-forward and sensible thing.

The UUIDs in the path of Arq backups are quite cryptic. The file’s absolute path actually is this: /mnt/user/ct_mirror/mbp2020/EC5C50F5-96D9-4965-8849-C2E8296E12FD/backupfolders/F6BA5DBC-31E4-4DE3-9AE9-7A41873881EC/backuprecords/00170/4209506.backuprecord.

Now this is the recipe to get the file from the NAS to the nice support people:

  1. Hit “Reply” on the email. You do your email in Emacs, of course, so a mail composition buffer opens.
  2. In another window, SSH onto the server. That’s quite simple using TRAMP: start with this fake path-protocol-thingie notation, like /ssh:USER@SERVER:/, and from that absolute “path”, interactively drill down into the directory tree to get to the final directory of the path, “00170”.
  3. In that directoy listing (via dired, you’re still in Emacs, after all!), locate the file they want. You can use full text search on the buffer like I did, it’s all text after all!
  4. Use C-, to launch Embark on the file. For files, which I have an “attach the selected file to mail composition buffer” action.
  5. Compose the rest of the reply, hit send.

It’s a bit slower to attach a file that’s being transferred from the server than a local file, but since email is just weird plain text with binary blobs anyway, it’s no big deal, either.

That workflow was quite magical. How would normal people send stuff from servers via email? rsync or scp to their local machine first, I guess? It’s sort of fun that the actual location of a file was completely irrelevant for this process. That sparked a lot of joy, I must say.

Oh, I mentioned the Embark action to attach files before but never shared the code, so here it is:

(defun ct/attach-file (file)
  "Attach FILE to an email message.
The message to which FILE is attached is chosen as for `gnus-dired-attach`."
  (interactive "fAttach: ")
  (require 'gnus-dired)
  (ct/with-notmuch-as-compose-mail
   (gnus-dired-attach (list file))))

(defmacro ct/with-notmuch-as-compose-mail (&rest body)
  "Overrides `compose-mail' with `notmuch-mua-mail' for the duration of BODY."
  `(progn
     (require 'notmuch-mua)
     (advice-add 'compose-mail :override #'notmuch-mua-mail)
     (unwind-protect (progn ,@body)
       (advice-remove 'compose-mail #'notmuch-mua-mail))))

Then bind this to the a key (for “attach”) in the Embark file action keymap:

(define-key embark-file-map (kbd "a") #'ct/attach-file)

Please don’t ask how this came into being. It is a horrible mix of tips on Reddit (the original implementation was by @oantolin, creator of embark.el, if I recall correctly) and other hacks because attaching files from dired apparently is not part of the mml-* or message-* packages, but gnus. It works, so I’m not touching it.