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?
-
4Some ideas: http://mutt-users.mutt.narkive.com/IG5uScnD/external-file-manager – Arkadiusz Drabczyk Mar 27 '18 at 16:12
-
1Relevant issue for Mutt. – Matthias Braun Aug 26 '19 at 13:03
2 Answers
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.

- 31
-
Thanks for your answer! I just posted an alternative, slightly more streamlined method, which you might find interesting. – Rastapopoulos Oct 01 '19 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 03 '19 at 08: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
character in the 'Attach file' compose menu? – Rastapopoulos Oct 03 '19 at 10:10 -
Nice trick, and you could also do
:shell mutt -a %f
directly fromranger
. – Rastapopoulos Oct 03 '19 at 10:50 -
I'm now asking myself why I needed the function when you can attach files and compose the email with that simple command! I use several email accounts with mutt, each having its own muttrc file. When I use the simple command in your comment, the From field shows "user@computername", but the mail still gets sent from my "default" email account even though it uses ".muttrc_me" instead of what I assume is the default file simply named ".muttrc"! Oh, well! – John Flood Oct 04 '19 at 11:26
-
The commented line @Rastapopoulos inserted for ranger seems to work and send selected files from ranger to a file in the tmp folder, but rest of the script did not seem to work and actually attach the files if invoked from the email compose (vim) window. It would just insert the file names in the email itself. Or, from the attach window, it would do nothing. Maybe I was doing something wrong! – John Flood Oct 04 '19 at 13:42
-
the compose menu is after you have exited vim, ie when you can send by pressing 'y'. – Rastapopoulos Oct 04 '19 at 14:39
-
Thanks, I realized later that I was confused on that. I thought it was the attach menu. Unfortunately, I am still unable to attach files with your script, even from the correct compose menu. Ranger opens and files are sent to a file in the tmp directory, but they don't get attached. – John Flood Oct 04 '19 at 16:14
-
I think I'm still unsure of what you mean by "a literal
Return
character instead of^M
. – John Flood Oct 04 '19 at 16:22 -
Apologies to @Rastapopoulos, but I don't have enough points to comment directly on your answer. In any case, after changing the next to last line of your script to
tmux send-keys -t email:Email.0 -l a$file '' \; send-keys -t email:Email.0 Enter;
the script works but only after running it the second time without closing the compose window. Works OK for both single and multiple attachments with or without spaces. I've no idea why the script attaches nothing the first time although the necessary file is created with the path of the selected attachment. – John Flood Oct 05 '19 at 08:39 -
By litteral return character, I mean the character you obtain when typing
<c-v><Return>
in vim insert mode. Your adaptation seems ok to me, so I don't know why it doesn't work. You might need quotes arounda$file
, though, otherwise they can be considered as different words bybash
? Also, what is the point of the''
? – Rastapopoulos Oct 06 '19 at 15:23 -
Thanks, for your comment! When I posted the substitution in my previous comment, I was unable to in include the source [Escape keywords with tmux send] (https://unix.stackexchange.com/questions/471997/escape-keywords-with-tmux-send). As you can tell, I'm not a professional programmer, so there are many things I try to do without really understanding. BTW, when I exit mutt, I find the sent keys ("a/home/user/file") in the terminal with the message "Press any key to continue" both for the initial unsuccessful use of the macro and for the subsequent successful ones. – John Flood Oct 06 '19 at 15:44
-
1Your explanation of "literal return character" did the trick! Your original script now works for me. Thanks @Rastapopoulos! – John Flood Oct 07 '19 at 05: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
tmp=$(mktemp)
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
tmp=$(mktemp)
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"
file="$file_no_space"
fi
tmux send-keys -t email:Email.0 -l "a$file^M";
done < "$tmp"

- 1,669
-
Did you try escaping the space with a backslash instead of replacing it with an underscore? – schemar May 04 '20 at 19:42
-