5

I have an arbitrary email messages file in mbox format. I would like to periodically (end of the week), and automatically (via cron) purge messages from my "alerts" mbox file (new folder) just from one sender (or with a specific subject), because one sender let's call it 'syscheck@example.com' sends dozens of messages per day.

I want to cron this so daily it will do what I manually type in with mutt -f alerts; D; syscheck@example.com; $; y (purge)

.procmailrc is not an option because I have to actually skim over them all first. Once I have skimmed they are fine. At the end of the week they are no longer needed, and want them removed.

  • Do you mean get rid of all messages, or only ones from syscheck@example.com? – John Militer Apr 29 '16 at 19:56
  • 1
    I want to delete only the ones from a particular sender (or could be subject) – Stickley Apr 29 '16 at 19:59
  • Have you considered using grep to search for that specific address? Or if you need greater utility using sed or awk? – torchhound Apr 29 '16 at 20:11
  • @Stickley: so you want cron syntax to add your mutt command to run at end of every week ? – Rahul Apr 29 '16 at 20:20
  • 1
    I think GNU Mailutils's sieve will do what you want, though I've never tried it (else I'd post this as an answer—and anyone reading this is welcome to do so). – derobert Apr 29 '16 at 20:24
4

This cron job does what you specified daily at midnight:

0 0 * * * script >/dev/null -c 'env TERM=vt100 mutt -F/dev/null -falerts -e "push <delete-pattern>syscheck@example.com<enter><sync-mailbox>y<enter><exit>"' /dev/null

Let's break that down.

script -c 'cmd' runs cmd under a fake pseudo-tty (pty) so that cmd thinks it has a terminal with cursor mobility and such. Mutt needs this, but your cron job can't have it. Script provides the shim. Script's usual job is to record a command session to a file. Its final argument, /dev/null, says to write the record to the null device since you probably don't care about a bunch of replayable curses events.

env TERM=vt100 ... means to put a vt100 terminal in the environment before running mutt. You need this because cron jobs don't have a natural terminal type (since they don't naturally have a terminal).

Everything else is part of mutt. We use -F/dev/null to ensure that your .muttrc is not read. There's nothing wrong with reading it, but changes in your muttrc could change the way mutt interaction goes. It's safer over the long term to use the default muttrc only, which is what -F/dev/null does.

The -e option tells mutt what to do when it runs. The arguments to -e are commands that you can put into a muttrc file: set, alternatives, bind, hdr_order, etc. Push is a command that "pushes" keystrokes into the keyboard buffer, so that mutt interprets what follows as if you had typed it.

Now let's look at the virtual keystrokes.

<delete-pattern>syscheck@example.com<enter> is equivalent to keystrokes Dsyscheck@example.com plus ENTER, but it uses keyboard binding symbols instead of actual keystrokes. This is best practice for macros and for pushes, because it insulates your script against changes in default or personal keybindings. You can get key binding symbols from the interactive help. All the names in the middle column (that you use with the bind statement) are symbol names.

<sync-mailbox> is equivalent to pressing $, again with the key symbol instead of the keystroke. y<enter> responds to the "Are you sure?" prompt.

Finally, <exit> quits mutt. That also terminates your script session, and your cron command ends. The >/dev/null, per usual with cron, prevents any of the noise from cron from harassing your mailbox.

Note that the whole push string is quoted! That's important. Fortunately we only need two layers of quoting, so we can use double quotes inside singles without any ludicrous quote escaping.

2

You could use mutt to do this from cron with expect (or one of its many implementations in many other languages).

#!/usr/bin/env expect
spawn mutt -f alerts
expect -ex "Mutt" # or something if you've customized the display
send -- "D"
send -- "syscheck@example.com"
...

Another option would be to write code that does a similar thing via something like Mail::Box::Mbox.

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.