In mutt, is it possible to use a file browser such as vifm or ranger (possibly in a tmux split) instead of the default file browser to select a file to attach to an email?


You can open ranger in a tmux split (a possibility you suggested), select the file to be attached, copy the file name with its path using yp and then return to the mutt attach window, press a and paste the attachment path and file name in the line that opens at the bottom of the attach window and press Enter.

Regarding the issue of spaces in the file name (in response to the comment of @Rastapopolous), I realized I have strong habit of not using them, but re-testing the above method of pasting the path from ranger, I find that when the file name has spaces, for some reason, the attachment name pasted in mutt has a repetition of part of the name appended! One can backspace to remove the "appendage" and the attachment is readily sent even with the spaces not escaped. I tested the path copy from ranger in vim and it pastes correctly, but not in mutt.

Since I habitually use tmux, I find this a relatively simple method.

Alternatively and independently of tmux, I also have the following script in my .bashrc:

# email an attachment
function mail_attach ()
    mutt -F ~/.muttrc -a "$@" -- myemail@gmail.com;

export -f mail_attach

This is useful when you know you will attach before composing an email. So, from within ranger, one simply selects a file, types s to open a shell command line and indicates the selected file with %f, that is:

:shell mail_attach %f

Pressing Enter will open the mutt editor for composing an email which already has the selected file attached attached. However, one must then change the recipient email address to the desired one. Perhaps there is a way to change the function to open the email editor with a blank "To" field, but I don't know enough. However, I don't find this a big deal.

For multiple files, if they are in the same folder, I select them all and then press @ which is a ranger shortcut to open the shell command line like this where %s is a reference to the selected files:

:shell %s

Then one simply inserts mail_attach before %s and pressing enter will open mutt for composing the email which already has all the selected files attached. If you want to attach files from different folders, I don't know how to do that apart from gathering them into the same folder.

I would like to give credit to whoever created the function, but I no longer know where it came from. I know it wasn't me.

  • Thanks for your answer! I just posted an alternative, slightly more streamlined method, which you might find interesting. – Rastapopoulos Oct 1 at 17:16
  • Thanks very much for the alternative, however, I think I am too wedded to ranger and, at the same time, lack the skills to adapt your script to ranger! – John Flood Oct 3 at 8:05
  • I've adapted the script I posted for ranger. Only downside is it doesn't seem to work for filenames with spaces in them. (Is it just my version of mutt, or is it impossible to type a <Space> character in the 'Attach file' compose menu? – Rastapopoulos Oct 3 at 10:10
  • Nice trick, and you could also do :shell mutt -a %f directly from ranger. – Rastapopoulos Oct 3 at 10:50
  • 1
    Your explanation of "literal return character" did the trick! Your original script now works for me. Thanks @Rastapopoulos! – John Flood Oct 7 at 5:31

The answer of @John Flood inspired me to think a bit more about this, and I came up with the following workaround, which seems to work quite well.

Save the following script as mutt_attach somewhere in $PATH, with the litteral Return character instead of ^M (in vim, this is achieved by pressing <c-v><Return> in insert mode).

#!/usr/bin/env bash


vifm "$HOME" -c "set nohlsearch" --choose-files "$tmp"
# ranger "$HOME" --choosefiles="$tmp"

while IFS="" read -r file; do
    tmux send-keys -t email:Email.0 -l "a$file^M";
done < "$tmp"

In .muttrc, define

macro compose \CA "!mutt_attach\n"

Now if you open mutt in the first pane of the window Email in a tmux session named email (created with, for example, the command tmux new -s email. Specifying the session, window and pane is convenient mostly for debugging purposes) and press Control+A in the compose menu, vifm will open in choose-files mode, and the selected file will be automatically attached.

Better yet, this lets you tag several files in vifm using t (or visual mode), and in ranger using Space, and attach them all at the same time!

EDIT: I noticed that the code does not work for filenames that contain whitespaces, as it seems impossible to type a space in the attachment compose menu in my version of mutt... Here is a (somewhat ugly) workaround:

#!/usr/bin/env bash

# File in which to store the list of filenames to attach

vifm "$HOME" -c "set nohlsearch" --choose-files "$tmp"
# ranger "$HOME" --choosefiles="$tmp"

while IFS="" read -r file; do

    # Workaround for filenames that contain spaces
    if [[ "$file" = *" "* ]]; then
        file_no_space=/tmp/$(basename "$file" | sed 's/ /_/g')
        ln -s -f "$file" "$file_no_space"

    tmux send-keys -t email:Email.0 -l "a$file^M";
done < "$tmp"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.