Mutt
Mutt is a highly capable email client. It's strongest feature for me is that it's console based. This means it can run in screen on the vps which I rent from bitfolk without the requirement of an IMAP server running as it's capable of reading local mailboxes just fine.
The most confusing part of mutt is that you have to create your configuration for your mail box from scratch, but once this is done it's smooth sailing with email that's all readable as plain text and editable with your favourite editor.
Contents |
header caching
One of the most important features that I have found in mutt is the ability to cache headers. This means fewer mailbox scans and can dramatically improve the performance and load on backend NFS or local disks.
To enable header caching in mutt add the following:
set header_cache=/localdirectory/
Where localdirectory is (preferably) a local directory on your system where you can put header cache data. It's possible to make this a remote directory but you might cost yourself in network resource overhead.
maildir
Another really important thing with mutt is that you can use it with Maildir format mailboxes which makes header caching possible. The following will enable Maildir mailboxes:
set mbox_type=Maildir
from
Another great thing about mutt is that you can define the "envelope from" address field:
set from="user-xyz@s5h.net" set use_envelope_from=yes
This enables you to configure the address that your mail leaves with (I strongly suspect the -f parameter is defined when calling sendmail). One of the things I do as a qmail user is configure a user-default .qmail file and dish-out user-sitename@s5h.net addresses when using my email address on the web. When replying to this mail I have a script set the from header when replying, based on the Delivered-to header. It is then a very simple matter to filter this mail to defined Maildir boxes, which limits inbox spam.
256 colours
Not all terminals in the world can support 256 colours, but it's nice
when they do. See the xterm-256color page for a listing of these. If
you have your 256 colour terminal setup then why not make use of one of
these themes, you can try them out using the :source
command.
To enable the 256 colour set TERM=xterm-256color then make
use of the extended colours.
I've put together a colour theme for 256 colour terminals, it's available in the mutt directory, let me know what you think, it's a bit blue.
themes
I've put some themes together in the directory above, if you're after a screen shot of the mutt themes then you can take a preview in the gallery selection below.
Please give me your feed back as to the ones which you might prefer or perhaps seriously dislike, but I'd hope they're of some enjoyment to someone.
conditional configuration
Sometimes you want to keep the same configuration files but have then operate differently depending on where it's being invoked (consider running with a NFS home directory mounted on different architectures).
In these instances you might want to make use of the pipe configuration
source, consider this .muttrc snippet:
source "~/.mutt/script/editor|"
With this script contents:
#!/bin/sh
HOSTNAME=`hostname`;
if [ "$HOSTNAMEx" -eq "fileserverx" ] ; then
echo "set editor=\"/usr/local/vim-7.0/bin/vim\"";
fi;
In this case we're letting mutt process the output of this script as if
it's a config file. If the hostname matches fileserver then
we configure a different editor.
Other parameters are worth consideration on a NFS system, such as
setting header cache to a local file system which is most likely going
to be faster than where ~/.mutt (most likely a NFS), so
directing header_cache to the local disks is probably going
to improve user experience considerably.
spamcop
A very handy feature for submitting mail to spamcop is to make a key
binding for index and pager views. The job I
have set configures gpg and the from mail addresses prior to sending
and resets it to defaults after.
macro pager \cx ":set from=\"ed-spamcop@example.net\" autoedit=no \ fast_reply=yes editor=\"/bin/true\"\n:unset \ pgp_autosign\n<tag-prefix><forward-message>submit.<your \ id>@spam.spamcop.net\n<send-message>:set autoedit=yes pgp_autosign \ fast_reply=no from=\"ed@example.net\" editor=\"/usr/bin/vim\"\n" \ "Forward mail to SpamCop" macro index \cx ":set from=\"ed-spamcop@example.net\" autoedit=no \ fast_reply=yes editor=\"/bin/true\"\n:unset \ pgp_autosign\n<tag-prefix><forward-message>submit.<your \ id>@spam.spamcop.net\n<send-message>:set autoedit=yes pgp_autosign \ fast_reply=no from=\"ed@example.net\" editor=\"/usr/bin/vim\"\n" \ "Forward mail to SpamCop"
This is very handy for bulk submissions.
automatic spamcop submissions
It's become annoying for me, I often receive mail from lists which I've not been subscribed. I'm not sure what the best thing to do is, I shouldn't be on these lists, I've never asked, so I've configured mailfilter to accommodate this with a rule that automatically calls my spamcop submission script.
The script asks spamcop to process my mail attachment which is sent using mutt. I don't create the attachment with MIME myself as I prefer to let mutt store this in my Maildir/sent/ folder rather than me storing this myself, and besides, my mail system may change in the future to use a third-party IMAP or POP mailbox (however, this is incredibly unlikely and we will probably run out of ipv6 addresses first).
Currently, the processed spamcop messages arrive in my Maildir/inbox/ folder, which is ok, it's not as ideal as if the mail was arriving to a .qmail file, which would be excellent as then I'd not have to store state information about the processing.
There are three ways to process the spamcop reports:
- process with an
xfilterrule with maildrop - process the
Maildir/inbox/folder with find/xargs/cut/grep - process the mail with a
.qmailfile
Thanks to UNIX being an excellent OS it's very possible to cater for all of these with a single script, just called in different ways.
The script for processing this can read the URLs from STDIN (if received via .qmail), or via command line arguments if called through xargs or just user defined arguments.
For example:
.qmail-sc
|/home/user/services/scripts/spamcop_submit.pl -
Or, if executed from maildrop:
.mailfilter
if( /^From: spamcop@devnull.spamcop.net/ )
{
xfilter "/home/user/services/scripts/spamcop_submit.pl -"
}
Or from cron:
crontab:
* * * * * find /home/user/Maildir/.inbox -type f -mtime -1 \ | xargs cat | grep 'http://www.spamcop.net/sc?id=z' \ | perl /home/user/services/scripts/spamcop_submit.pl
However, if you'd like to send the job directly from mutt, you can make use of the message pipe, first press |:
Pipe to command: /home/user/services/scripts/spamcop_submit.pl -
Both these scripts are available from the spamcop directory.
last delivered-to header
One thing that I wanted the flexibility with was to be able to reply to
any email setting the From and mail from
envelope header to the inbound header Delivered-To. The
reason behind this was that for a while I sought pleasure in thwarting
419 scammers with actual human replies, just to consume their time.
So each time a 419 message arrived I'd respond using ed-<something
unique for them>@s5h.net. This works well, but I needed it to
happen automatically.
The resulting script looks something like this:
lastdt=$( awk '
/^$/ {
if( lastdt == "" ) {
print "<YOUREMAIL>@DOMAIN.net";
}
else {
print lastdt;
}
exit
}
/^Delivered-To: /{
if( lastdt == "" && $2 ~ /@/ ) {
lastdt=$2
}
}' )
echo "set from=\"$lastdt\"" > ~/.mutt/myfilter.out
Save it as ~/code/mutt/lastdt.sh, then just add the following macros, (alter the script name if the above doesn't suit).
macro pager,index r '<pipe-message>~/code/mutt/lastdt.sh<enter>\ <enter-command>source ~/.mutt/myfilter.out<enter><reply>' macro pager,index g '<pipe-message>~/code/mutt/lastdt.sh<enter>\ <enter-command>source ~/.mutt/myfilter.out<enter><group-reply>'
It certainly makes my life easier, especially when replying to mail
groups where I have custom .qmail rules for each list.
building on solaris
It took some tweaking to get mutt 1.5.21 to build on solaris, but I tracked the problem down (through some searching of include on linux) to missing ncurses. Since curses was on the system and 1.5.20 built ok, I simply assumed that all was still well.
Undefined first referenced symbol in file key_defined keymap.o ld: fatal: Symbol referencing errors. No output written to mutt
After putting ncurses in a home directory and building against that all was good.
cd ncurses-5.7 ./configure --prefix=$HOME/bin/ncurses --exec-prefix=$HOME/bin/ncurses gmake && gmake install
Reconfigure with ncurses:
cd mutt-1.5.21 ./configure --enable-hcache --prefix=$HOME/bin/mutt-1.5.21 \ --exec-prefix=$HOME/bin/mutt-1.5.21 --disable-iconv \ --with-bdb=/usr/local/db-4.7.25 --with-curses=$HOME/bin/ncurses gmake && gmake install
All done.
auto copy
One of the other things that I really like about Mutt is that it's possible to run it through screen on another host, but send a message to a copy program running on the system that you're using.
I have to do this on a regular basis since I have to regularly update tickets with email conversation data (yes it would be better to have the ticket program gobble this from a mail relay but life isn't perfect, mutt is nearly perfect though).
Firstly we need to have ssh installed and operational on the desktop. From here onwards we'll call the place mutt runs the "server" and the place where you are working from the "desktop".
Test the following, ssh to the "server" (no X forwarding), then from the server run:
ssh desktop "xeyes"
Do you get the xeyes program begin to run, do you get an error message:
Error: Can't open display:
If so, find out what DISPLAY is set to on your desktop X11 server,
$ export | grep DISPLAY declare -x DISPLAY=":0.0"
So, then run from the ssh session to the desktop that is running on the server,
$ DISPLAY=":0.0" xeyes
and hopefully you'll get the xeyes program. If not, did you get an auth error message, if so,
$ xhost +localhost
macro
So, once the X11 problems are resolved, you'll need to add the macro:
macro index \cx "<pipe-message>ssh desktop -t 'DISPLAY=:0.0 /usr/bin/xclip -selection p'"
This should then send the message to the xclip copy program when you press ctrl-x, so no more needing to manually select and copy things. Of course if there's only certain parts of the message that you require to copy it would serve you well to grep them in the pipeline.