mu icon indicating copy to clipboard operation
mu copied to clipboard

Add ability to mute messages

Open stefanv opened this issue 9 years ago • 8 comments

Often, one comes across email threads you'd like to ignore in perpetuity. Gmail has the "mute" functionality. I can think of at least two ways of doing this in mu4e:

  • Add a label to one or more message(s) in a thread. If such a label is found, do not show the message in the headers list.
  • Add a message action that adds the current subject to a list. Add a flag to the headers search that suppresses messages with topics matching the list.

stefanv avatar Jul 07 '15 19:07 stefanv

I'd also use something like this. But I'd personally rather see this handled on the message-filing side than the view side. Having messages in my inbox that exist in the Maildir but are just not shown by the client, because they've been muted, breaks the simple all-state-is-in-the-maildirs model I think of mu as having. If I don't want a message in my inbox, imo it should actually be removed from the Maildir, too. Either trashed, or refiled into another directory.

For my own use what I'd personally do is the second option: if a thread is muted, new messages are marked as read and refiled, but not otherwise treated specially. That way such threads wouldn't show up in my inbox or in the "show unread messages" search, but I'd be able to find them if I navigated to the folder they're filed into (e.g. my local archive of a mailing list). But people who don't use refiling to keep archives might prefer mark-as-read-and-trash.

Either way, mu would need procmail-style support for filtering incoming mail, which it doesn't currently have.

anadrome avatar Jul 28 '15 07:07 anadrome

@anadrome I don't understand why you say that breaks the all-state-is-in-the-maildirs model. One of mu4e's central features is that you can do smart filtering on the list of messages based on some search criterium.

Note that the solution proposed here does not require procmail-style filtering support.

stefanv avatar Jul 28 '15 21:07 stefanv

I am also very interested in this feature.

In the meantime I have a quite nice solution for me. I have a script which will called after mu-update-mail-and-index. This script adds the value muted to the header X-Keywords if there is a thread with at least one message with the tag 'muted'. I use 'formail' for the tagging of the messages.

The script could be something like this:

muted_tag="muted"
header_field="X-Keywords"

mkdir -p /tmp/mu

for f in `mu find tag:${muted_tag} -r -f l`; do
    labels=$(cat ${f} | formail -x"${header_field}" | tr -d ",")
    check_muted=false
    for l in ${labels}; do
    if [[ "${l}" == "${muted_tag}" ]]; then
        check_muted=true
    fi
    done
    if [[ "${check_muted}" == "false" ]]; then
    old_labels=$(cat ${f} | formail -x"${header_field}")
    new_labels="${old_labels}"
    if [[ "${old_labels}" == "" ]]; then
        new_labels+="${muted_tag}"
    else
        new_labels+=", ${muted_tag}"
    fi
    cat ${f} | formail -I"${header_field}:${new_labels}" > /tmp/mu/muted-message
    mu remove ${f}
    mv /tmp/mu/muted-message ${f}
    fi
done

rm -rf /tmp/mu

You have to do a mu index before and after that script.

For calling this script within mu4e I have expanded the function mu4e-update-mail-and-index with a new hook called mu4e-update-post-hook and this hook calls the function:

(defun mu4e-mute-messages ()
  (call-process "/home/odi/bin/mu-mute-messages.sh")
  (mu4e-update-index))

After that there are all messages in a 'muted' thread marked as muted. Then you can make a find query e.g.: mu find maildir:/list/mu4e and not tag:muted and all 'muted' messages are hidden in the result.

For simple usage in mue4 I use a custom mark for muting messages:

  (add-to-list
   'mu4e-marks
   '(muted
     :char "M"
     :prompt "Muted"
     :show-target (lambda (target) "muted")
     :action (lambda (docid msg target)
               (mu4e-action-retag-message msg (concat "+" "muted"))
               (mu4e~proc-move docid nil "+S-u-N"))))

  (mu4e~headers-defun-mark-for muted)
  (define-key mu4e-headers-mode-map (kbd "M") 'mu4e-headers-mark-for-muted)

I am sure that is not a perfect solution but it works quit nice for me and my workflow.

odi avatar Jul 30 '16 16:07 odi

You need that shell script because mu lacks a way to return message headers right? Otherwise that could be a scm script run by mu.

shaleh avatar Jun 07 '17 06:06 shaleh

For calling this script within mu4e I have expanded the function mu4e-update-mail-and-index with a new hook called mu4e-update-post-hook

@odi can you share your patch for this?

brycethomas avatar Dec 08 '18 23:12 brycethomas

You need that shell script because mu lacks a way to return message headers right? Otherwise that could be a scm script run by mu.

@shaleh sure. This script changes the content of the file/message with formail so it has to be indexed afterwards again. You have to trigger the script after mu4e~update-mail-and-index-real is called in the function mu4e-update-mail-and-index.

odi avatar Mar 28 '19 09:03 odi

For calling this script within mu4e I have expanded the function mu4e-update-mail-and-index with a new hook called mu4e-update-post-hook

@odi can you share your patch for this?

@brycethomas I have currently no patch for that but it's something like that

Define a new hook

(defvar mu4e-update-post-hook nil)

Extend the function mu4e-update-mail-and-index with that hook

(defun mu4e-update-mail-and-index (run-in-background)
  "Get a new mail by running `mu4e-get-mail-command'. If
run-in-background is non-nil (or called with prefix-argument), run
in the background; otherwise, pop up a window."
  (interactive "P")
  (unless mu4e-get-mail-command
    (mu4e-error "`mu4e-get-mail-command' is not defined"))
  (if (and (buffer-live-p mu4e~update-buffer)
	(process-live-p (get-buffer-process mu4e~update-buffer)))
    (mu4e-message "Update process is already running")
    (progn
      (run-hooks 'mu4e-update-pre-hook)
      (mu4e~update-mail-and-index-real run-in-background)
      (run-hooks 'mu4e-update-post-hook))))

And then add the function to the hook

(add-hook 'mu4e-update-post-hook 'mu4e-mute-messages)

Because of currently not using this script (I found a workflow for me where I do not need the mute tag anymore) it's from my memory and not tested!

odi avatar Mar 28 '19 09:03 odi

This works pretty well except I get error in process filter: mu4e-error-handler: Error 3: unknown error occasionally.

matthew-piziak avatar Aug 10 '19 14:08 matthew-piziak

Doing this correctly would be quite a bit of work, and since this is not expected anytime soon, I'm closing this. I've moved a mention to the IDEAS.org file, who knows what might happen in the future.

djcb avatar Mar 05 '24 23:03 djcb