I want to determine the local path of the currently viewed mail within mutt and transfer it to a bash script, before or after saving the mail to a local project folder.


I am using mutt together with offlineimap and msmtp in order to decouple my mail infrastructure from the necessity of a permanent internet connection. In doing so, I find my mails within the mailfile structure where each <PROJECT> and <ACCOUNT> may live in its own local folder structure:

|-- <PROJECT>/
|   |-- cur/
|   |   |-- 1584016380.RPi-18:2,
|   |   |-- 1595241604.RPi-18:2,
|   |   |-- 1603636018.RPi-18:2,
|   |   `-- 1612159655.RPi-18:2,
|   |-- new/
|   `-- tmp/
|-- <ACCOUNT>/
|   |-- DRAFTS/
|   |   |-- cur/
|   |   |-- new/
|   |   `-- tmp/
|   |-- INBOX/

When I browse my mail (using the index or pager view in mutt), I can select, tag, delete, ... open the respective mail element which is read by mutt from the sketched folder structure.

Now, I want to save the current message using mutt's save-message function. But beforehand (or after the save), I want to automatically extract the message's attachment and possibly do some other stuff using the mail contents.

I already wrote a bash script which reads in the path of a mail file, e.g. ~/Mail/<PROJECT>/cur/1584016380.RPi-18:2 as its argument, and then stores the mail's attachments in a predefined location using the mu command.


I have looked within the available mutt variables (folder, spoolfile, from, ...) in order to find anything that would tell me where my currently viewed mail file is actually located. But I could not find anything. So, I don't know which path to pass to my bash script for it to find the mail locally.

Is there anything usable, here?

  • What about piping the message to the script? Would it solve the issue for you? You can write a macro doing the pipe-message and save/copy. Oct 4, 2021 at 16:51
  • Good idea. I hadn't thought about piping, yet. Will try to modify my code to accept piped content directly.
    – nnako
    Oct 6, 2021 at 4:33
  • There seems to be a problem, though. When using pipe-message, my target script does not know WHERE the piped messasge is to be saved. a target folder is determined while using mutt's save command. not before that. I see two options: (1) is there a way to set a target folder for a message (which is originally done when using the save command) and transfer it to the script? and afterwards use it in the save command? (2) alternatively, the save command could be executed first, then pipe the message to the script. would there be a way to determine the target folder used by save?
    – nnako
    Oct 24, 2021 at 7:51
  • by the way, I'm assuming, that the function pipe-message accepts an executable script as a target. not only a file. otherwise the function might better be called redirect-message, eh? would this be the case?
    – nnako
    Oct 24, 2021 at 8:02

1 Answer 1


I decided to compose an answer, because this is becomming quite large to be resolved in discussion in comments under the question.

I understand the project differes for different senders, subjects or body content.

You'll need two macros like here Neomutt run command to attach file on macro key press

The first macro does the job and needs to be in a separate file - because the shell part is expanded on macros definition. That's why You need to redefine it by the second macro that defines the first one and executes it.


<save-message>`cat /tmp/mutt_project`<enter>" \
"pipe message to extract attachments and save message"


macro index ,S \
"<enter-command>source ~/.mutt/dynamic_macro<enter>\
<enter-command>push ,s<enter>" \
"redefine macro and run it"

Now here is nonworking an example of /path/to/your/script in pseudo code (bash like). The script reads the message from stdin, parses headers or body to determine the project name (mailbox name) and iterates over parts to save the attachments - probably to some directory and subdirectories by projects?

  # parse $content to detect project from body/headers
  # save the project name to /tmp/mutt_project for the 1st macro
  # and output on stdout for save_attachemnts()
  echo $result > /tmp/mutt_project
  echo $result

  # parse $content, iterate over parts of message from $content,
  # extract attachments, decode, save to:

  content=$(cat) # read the stdin and save it into variable



  1. use language that has library for working with emails that can access the parts, decoded them etc.
  2. I'm convinced that the example above won't work with tag-prefix if you'll tag multiple messages from a different projects. The reason is that macro is executed once and all messages would be piped into /path/to/your/script at once, but the argument of <save-message> will contain project detected from the last message

Different solution: move from mutt to neomut and mu to notmuch. Neomutt has a good built-in support for notmuch. Everything here could be done by notmuch post-new hook. It's perfect for your usecase, running on background without any need of neomutt macros and removes the limitation of tag-prefix of original solution. Nomtuch post-new hook runs everytime after You sync Your messages.

  • it can tag messages based on from/to/cc/subject headers body content or other tags,
  • saving an attachment is also possible by post-new hook.

If You're interested in this, leave here a comment here and I'll expand the answer.

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.