I’ve used Mutt on and off for “a long time”.

Its easily the best console mail client, and is arguably in the top 5 for all mail clients. It supports local mail (mbox, maildir) and POP3, IMAP, and (recently) SMTP protocols. One of the advantages that Mutt offers is actually showing you the content of an email, as opposed to a rendered interpretation. Most email clients, when they get an HTML formatted email, render it. This allows the sender to do things like use fonts, bold face type, or show images. The downside of these capabilities is that it allows a malicious actor (spammer, malware, etc) to make it more difficult to know if the message you’re reading has links to (for example) your bank, or some website in Romania.

Additionally, its now common practice for many marketing (potentially legitimate) emails to include an image (typically a 1px X 1px, and also typically transparent, or invisible) in an email so they can track who reads the email. This can be used legitimately to determine who actually reads email and should be followed up. It could also be used to track people. More experienced consumers of email will point out that many graphical clients offer the ability to disable the rendering of remote graphics. I suggest people make use of this feature on desktop and mobile platforms.

As a subtext of this post, I will be getting as many of the components to communicate via Tor as I can. I already covered installation and configuration of Tor and Polipo in this post.

Mutt installation

Being on a Mac, I installed Mutt via homebrew (covered in this post)1. Part way through fiddling around with the muttrc, I remembered that I wanted side-bar support (Mutt calls the folder list the side-bar). With 1.5.24, homebrew doesn’t offer a patch for sidebar. After some reading, it seems they don’t like patches in general and are working to get rid of all of them. They suggest creating your own tap where you can make formulas and add patches yourself.

sigh

After more digging around, I landed here2. Editing the Mutt formula (brew edit mutt) and pasting in these bits:

option "with-sidebar-patch", "Apply sidebar patch"

and

patch do
   url "https://raw.githubusercontent.com/Kdecherf/mutt-lightweight-sidebar/master/mutt-lightweight-sidebar.patch"
   sha1 "4c4f9516b1d507fa70dc88574ad65d1fc8c29c3d"
end if build.with? "sidebar-patch"

You will probably end up with a different sha1 because there are likely to be changes to this file as it gets updated with fixes, or changes to apply to new(er) versions of Mutt.

Now that we’ve patched the formula, we can execute

$ brew install mutt --with-sidebar

The right things happen, and we end up with a Mutt that can have a sidebar.

Mutt configuration

I started off with an a muttrc from years ago. The world has changed since I last used Mutt, and it was easier to start with a new config. I got a muttrc from Calomel3. They do a good job of providing very sane defaults. I knew I wouldn’t be able to just drop somebody else’s config into place and use it. To start with, I wanted to setup 4 email accounts in Mutt, not the traditional 1. With this configuration, I can use F2, F3, F4, F5 to select different accounts. The only bit that is a little tricky is that any settings that are unique to an account need to go into a different account specific file. Additionally, anything you set for one account, needs to be unset (or overwritten) for all other accounts.

#######################################################
###  (Modified) Calomel.org .muttrc   BEGIN
#######################################################
# System configuration file for Mutt ( .muttrc )
#
### Account cryptomonkeys.org settings
source ~/.mutt/cryptomonkeys.org/config
folder-hook 'cryptomonkeys.org' 'source ~/.mutt/cryptomonkeys.org/config'

### Account cryptomonkeys.com settings
folder-hook 'cryptomonkeys.com' 'source ~/.mutt/cryptomonkeys.com/config'

### Account louiskowolowski.com settings
folder-hook 'louiskowolowski.com' 'source ~/.mutt/louiskowolowski.com/config'

### Account louiskphoto.com settings
folder-hook 'louiskphoto.com' 'source ~/.mutt/louiskphoto.com/config'

#######################################################
###  Pager
#######################################################
#ignore *
#unignore  X-Bogosity From: Reply-To: To: Cc: date = Subject:
#hdr_order X-Bogosity From: Reply-To: To: Cc: date = Subject:

#######################################################
###  Macros
#######################################################
### Facilitate multiple accounts. Push button to change accounts.
macro index <f2> '<sync-mailbox><enter-command>source ~/.mutt/cryptomonkeys.org/config<enter><change-folder>!<enter>'
macro index <f3> '<sync-mailbox><enter-command>source ~/.mutt/cryptomonkeys.com/config<enter><change-folder>!<enter>'
macro index <f4> '<sync-mailbox><enter-command>source ~/.mutt/louiskowolowski.com/config<enter><change-folder>!<enter>'
macro index <f5> '<sync-mailbox><enter-command>source ~/.mutt/louiskphoto.com/config<enter><change-folder>!<enter>'

### change mailbox
macro index <f6> 'c =INBOX^M'
macro pager <f6> 'c =INBOX^M'
macro index <f7> 'c =Sent^M'
macro pager <f7> 'c =Sent^M'
macro index <f8> 'c =Junk^M'
macro pager <f8> 'c =Junk^M'

### save attachments to incoming
macro attach s <save-entry><bol>~/Downloads/

macro index 'c' '<change-folder>?<change-dir><home>^K=<enter>'

### Toggle sidebar visibility
macro index b '<enter-command>toggle sidebar_visible<enter>'
macro pager b '<enter-command>toggle sidebar_visible<enter>'

#######################################################
###  Headers
#######################################################
# When OutLook receives email it will put it at the
# top of their mailbox list and flag it with an "urgent"
# red box. Just another way to play with Outlook users.
my_hdr X-Message-Flag: OUTLOOK WARNING!! Use Open Source
my_hdr Reply-By: `perl -MPOSIX -le '@now = localtime; $now[3] -= 3; print scalar localtime mktime @now'`
my_hdr X-MSMail-Priority: High

#######################################################
###  Options
#######################################################
bind editor <BackSpace> backspace

### Setup Sidebar navigation controls
### Shift-C, Shift-P, etc
bind index CP sidebar-prev
bind index CN sidebar-next
bind index CO sidebar-open
bind pager CP sidebar-prev
bind pager CN sidebar-next
bind pager CO sidebar-open

# If enter-command is available from the UI, it is possible to see the
# password unencrypted, which my be undesired if anybody else than you has
# access to your session while Mutt is running. You may want to disable it for
# this reason. As a consequence, every command that the user intends to use
# must be bound to a key in advance, otherwise it will never be accessible.
bind generic,alias,attach,browser,editor,index,compose,pager,pgp,postpone ':' noop

### Autoview attachments
unset implicit_autoview
alternative_order text/plain *
auto_view text/html text/enriched application/x-gunzip application/postscript image/gif application/x-tar-gz text/x-vcard application/octet-stream

  # check mail every 5min
  set mail_check=600

  # We can define special actions for certain types of files here
  set mailcap_path=~/.mailcap

  # locally defined aliases
  set alias_file="~/.mutt/aliases"

  # little brother db query string. Used to connect to external sources such as
  # ldap, apple contacts, etc.
  set query_command="/usr/local/bin/lbdbq '%s'"


unset abort_nosubject


unset abort_unmodified

  # 8bit isn't safe
  set noallow_8bit


unset arrow_cursor

  # don't restrict to ascii characters when displaying trees
unset ascii_chars


  set autoedit

  # We <3 beeping software.
unset beep
unset beep_new


unset bounce_delivered


  set check_new


  # Just append, don't hassle me.
  set noconfirmappend

  # Keep copies of outgoing mail...
  set copy


  set delete


unset edit_headers

  # keep vim from writing backup or swapfiles
  set editor="vim +13 -c 'set nobackup' -c 'set noswapfile' -c 'set nowritebackup' -c 'set tw=72 ft=mail noautoindent'"

  # set the envelope-from information
  set envelope_from

  # skip initial prompts when replying
  set fast_reply


unset fcc_attach

  # Keep fcc's clear of signatues and encryption
  set fcc_clear


  set forward_decode

  # Display download progress every 10k
  set net_inc=10


  set forward_quote=yes


  set forward_format="Fwd: %s"

  # show the help line at the bottom
  set help

  # Include the message in replies.
  set include


  set index_format="%3C %Z %(%D) %-27.27L (%4c) %s"


  set indent_string=">"


  set ispell="clear;aspell -e -c"


  set mailcap_sanitize

  # want any wrap markers.
unset markers


unset mark_old


  set menu_scroll


unset metoo

  # Forward message as MIME attachments.
  set mime_forward=yes


  set mime_forward_decode


  set mime_forward_rest


  set pager="builtin"


  set pager_format=""

  # Don't skip msgs on next page.
  set pager_stop

  # Display 15 lines of context in pager.
  set pager_context=15

  # Display 20 lines of index in pager.
  #set pager_index_lines=20


unset postpone

  # Ask before printing.
  set print=ask-no


  set print_command="~/.config/mutt/mutt_print.sh"

  # Read counter ticks every 100 msgs.
  set read_inc=2


unset reply_self


  set reply_to

  # put dashes between message and signature
  set sig_dashes=yes


  set smart_wrap

  # always sort by thread
  set sort=threads

  # sort in reverse
  set sort_re

  # Sort threads by date received (in reverse)
  set sort_aux=reverse-date-sent


  set status_on_top

  # Don't do fuzzy threading.
unset strict_threads


unset suspend

  # Fill out messages with '~'.
  set tilde


  set timeout=300


  set thorough_search


unset user_agent


unset wait_key


unset write_bcc


  set attribution="* %n <%a> [%{%Y-%m-%d %H:%M:%S %Z}]:\n"


  set smileys="(>From )|(:[-^]?[][)(><}{|/DP])"


  set send_charset="us-ascii:iso-8859-1:utf-8"

  # What we consider to be a quote.
  set quote_regexp="^( {0,4}[>|:#%]| {0,4}[a-z0-9]+[>|]+)+"
  set to_chars=" +TCF "                     # Drop the "L".

  ### Sidebar customization
  set sidebar_visible=yes
  set sidebar_width=30
  set sidebar_delim='  '
  set sidebar_sort=yes
  set sidebar_indentstr="-> "
  set sidebar_folderindent=yes
  set sidebar_format='%! %B'
  set sidebar_shortpath=yes

  ### Imap settings that apply to all accounts
  set imap_delim_chars="."
  set imap_idle=yes
  set imap_check_subscribed=yes
  set imap_list_subscribed=yes
  set imap_keepalive=60
  set imap_passive=no

  ### SSL Hardening
  set ssl_force_tls=yes
  set ssl_starttls=yes
  set ssl_use_sslv2=no
  set ssl_use_sslv3=no
  set ssl_use_tlsv1=no
  set ssl_use_tlsv1_1=no
  set ssl_use_tlsv1_2=yes
  set ssl_verify_dates=yes
  set ssl_verify_host=yes
  unset ssl_usesystemcerts
  set certificate_file=~/.mutt/muttcerts

#######################################################
###  Hooks
#######################################################
### Hooks
send-hook . "set signature=~/.signature"
send-hook . 'unset pgp_autoencrypt pgp_autosign'

### Mark mail as read
#folder-hook archive push '<tag-pattern>.*\r<tag-prefix><clear-flag>N<untag-pattern>.*\r'

### Delete old mail after a set number of days
#folder-hook archive push 'D~r>32d!~F\n'
#folder-hook SPAM push 'D~r>60d!~F\n'

### Include Colors
#####################################################################
# colors
###
### color pager
# Rados' colors
#source colors_rado

source `case $TERM in\
		*256color) echo '~/.mutt/colors256-dark'; break ;;\
		*rxvt-unicode) echo '~/.mutt/colors256-dark'; break ;;\
	esac`

#source ~/.mutt/mutt-colors.muttrc
#source ~/.mutt/mutt-colors-solarized-light-16.muttrc

### Include mailboxes we want to check for new mail
source ~/.mutt/mailboxes

### Include headers we want to see
source ~/.mutt/headers

#######################################################
###  Calomel.org .muttrc  END
#######################################################

Example account specific IMAP config file (this is what gets sourced when I use the F(2-5) keys.

# Include the profile name in the status line
set status_format="cm.org(%r): %f [Msgs:%?M?%M/?%m%?n? New:%n?%?o? Old:%o?%?d? Del:%d?%?F? Flag:%F?%?t? Tag:%t?%?p? Post:%p?%?b? Inc:%b? %?l? %l?]---(%s/%S)-default-%>-(%P)---"

my_hdr From: louisk@ cryptomonkeys.org (Louis Kowolowski)
my_hdr Reply-To: louisk@ cryptomonkeys.org (Louis Kowolowski)
my_hdr Errors-To: louisk@ cryptomonkeys.org
my_hdr Organization: Open Source Software Supporter (OSSs)

set hostname="cryptomonkeys.org"
set folder='imaps://mail.cryptomonkeys.org/'
set imap_authenticators="login"
source "gpg2 -dq $HOME/.mutt/cryptomonkeys.org/cm.org.gpg |"
set imap_pass=$my_cm_org_password
set imap_user='louisk@ cryptomonkeys.org'
set postponed='imaps://mail.cryptomonkeys.org/Drafts'
set record='imaps://mail.cryptomonkeys.org/Sent'
set spoolfile='imaps://mail.cryptomonkeys.org/INBOX'
set sendmail="/usr/local/bin/msmtp -a cryptomonkeys.org"

#######################################################
###  GPG Hooks
#######################################################
my_hdr X-GPG-Key-Server: http://keyserver.pgp.com
my_hdr X-GPG-Key-FingerPrint: DCED 3E1E 6AAF DDB1 C40F A379 9C88 F73C 2602 A9FC

send-hook louisk@ cryptomonkeys.org 'set pgp_autosign; set pgp_autoencrypt'
pgp-hook louisk@ cryptomonkeys.org 2602A9FC

set pgp_decode_command="gpg %?p?--passphrase-fd 0? --no-verbose --batch --output - %f"
set pgp_verify_command="gpg --no-verbose --batch --output - --verify %s %f"
set pgp_decrypt_command="gpg --passphrase-fd 0 --no-verbose --batch --output - %f"
set pgp_sign_command="gpg --no-verbose --batch --output - --passphrase-fd 0 --armor --detach-sign --textmode %?a?-u %a? %f"
set pgp_clearsign_command="gpg --no-verbose --batch --output - --passphrase-fd 0 --armor --textmode --clearsign %?a?-u %a? %f"
set pgp_encrypt_only_command="/usr/local/bin/pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust --encrypt-to 2602A9FC -- -r %r -- %f"
set pgp_encrypt_sign_command="/usr/local/bin/pgpewrap gpg --passphrase-fd 0 --batch --quiet --no-verbose --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust --encrypt-to E316DAB9 -- -r %r -- %f"
set pgp_import_command="gpg --no-verbose --import -v %f"
set pgp_export_command="gpg --no-verbose --export --armor %r"
set pgp_verify_key_command="gpg --no-verbose --batch --fingerprint --check-sigs %r"
set pgp_list_pubring_command="gpg --no-verbose --batch --with-colons --list-keys %r"
set pgp_list_secring_command="gpg --no-verbose --batch --with-colons --list-secret-keys %r"
unset pgp_retainable_sigs
set pgp_ignore_subkeys
set pgp_verify_sig=yes
set pgp_create_traditional=no
set pgp_autosign=no
set pgp_autoencrypt=no
set pgp_sign_as=2602A9FC
set pgp_replysignencrypted
set pgp_replyencrypt=yes
set pgp_replysign=yes
set pgp_timeout=3600
set pgp_good_sign="^gpg: Good signature from"

# GPG/PGP colors
color body brightblack cyan "^gpg: Signature made.*"
color body brightblack green "^gpg: Good signature from.*"
color body brightblack yellow "^gpg: Can't check signature.*"
color body brightblack yellow "^gpg: WARNING: .*"
color body brightwhite red "^gpg: BAD signature from.*"

What I’ve done here is specify all the variables that are unique to an account. I have to make sure that these are either set, or unset (This is the collection of all variables across all accounts. Each account needs the complete collection, and they need to be either set or unset. Otherwise they will spill across accounts and result in unintended effects.) for each account.

I’ve also move the password for the account into a gpg encrypted file. Mutt decrypts this for me when I activate the account. If you’re going to do this, there are a couple things to note.

In your PGP encrypted file, you should have a line that looks like this:

set my_pw=some_great_password

If you haven’t created one, you can create a plain text file with the right contents, and then you can encrypt the file with:

$ gpg -e -r 'Your Name' ~/.mutt/account/account-pwd

You should end up with a file account-pwd.gpg. You can now delete the plain text version (use shred if you want, but really, you should have whole-disk encryption/full disk encryption already enabled).

Use the same variable in the account config for mutt, it would look something like this:

set imap_pass=$my_pw

Make sure that the variable starts with my_ so Mutt knows its a personal variable.

Now, when you access the account, Mutt should decrypt the file, read the password, and connect.

If you do this, you probably also want to ensure that you have this in your muttrc. It should prevent somebody from extracting the password from Mutt while its running.

# If enter-command is available from the UI, it is possible to see the
# password unencrypted, which my be undesired if anybody else than you has
# access to your session while Mutt is running. You may want to disable it for
# this reason. As a consequence, every command that the user intends to use
# must be bound to a key in advance, otherwise it will never be accessible.
bind generic,alias,attach,browser,editor,index,compose,pager,pgp,postpone ':' noop

Mutt headers config

The particulars of this will depend on a couple of things. The X-Virus* and X-Spam* headers may or may not be the same as what your email provider uses. You should look at some of your messages headers and determine what headers are there and which ones you’d like to see. Once you know that, customizing this file is very straightforward.

# -*- muttrc -*-
#
# Configure header displays.
#

# Ignore all headers
ignore *

# Then un-ignore the ones I want to see
unignore From:
unignore To:
unignore Reply-To:
unignore Mail-Followup-To:
unignore Subject:
unignore date =
unignore Organization:
unignore Newsgroups:
unignore CC:
unignore BCC:
unignore X-Mailer:
unignore User-Agent:
unignore X-Virus-Status:
unignore X-Spam-Status:
unignore X-Spam-Flag:

# Now order the visable header lines
hdr_order From: Subject: To: CC: BCC: Reply-To: Mail-Followup-To: date = Organization: User-Agent: X-Virus-Status: X-Spam-Status: X-Spam-Flag:

mutt_print.sh

This might surprise you. Instead of doing the typical “send to the printer” kind of thing you might expect from a printing script, this generates a PDF file and then opens it with Preview (yup, still on a Mac). You can then choose to keep the PDF, or print via the normal collection of already configured Mac printers (taking advantage of things like duplex, collation, finishing, etc).

#!/bin/sh
pfile="${1}"
pdir="${HOME}/.mutt/mutt_print"

if [ ! -d ${pdir} ]; then
    mkdir -p ${pdir}
fi

# delete any old temporary files first
rm -f ${pdir}/mutt_*.pdf

tmpfile="`mktemp ${pdir}/mutt_$$`"
mv -f ${tmpfile} ${tmpfile}.pdf
enscript --font=Times-Roman10 --pretty-print ${1} -o - 2>/dev/null | pstopdf -i -o ${tmpfile}.pdf
open ${tmpfile}.pdf

msmtp installation

Msmtp is a drop in replacement for something like Sendmail, Postfix, Exim, etc. It doesn’t offer all the features of a traditional MTA, but it is trivial to configure for a system where you don’t need to (or want to) setup an MTA just so you can connect to some server and send a few emails.

Installation is very simple:

$ brew install msmtp

msmtp configuration

msmtp offers the ability to dynamically slurp a password in from a gpg encrypted file. This means we don’t have to have a plaintext file sitting around with a password in it. Yey!

$ chmod 600 ~/.msmtprc

To avoid saving the password in plain text in the configuration file, use passwordeval to launch an external program. This example using GnuPG is commonly used to perform decryption of the password:

$ echo -e "password\n" | gpg --encrypt -o msmtp-account.gpg

Warning: Most shells save command history(e.g. .bash_history .zhistory). To avoid this use gpg with shell stdin: gpg --encrypt -o msmtp-account.gpg -r <email> -. The ending dash is not a typo, rather it causes gpg to use stdin. After running that snippet of code, type in your password, press enter, and press Control-d so gpg can encrypt your password.

Here is the line from the ~/.msmtprc

passwordeval    "gpg2 --no-tty -q -d ~/msmtp-account.gpg"

After we are done testing for gpg, here is what the .msmtprc file looks like:

defaults
auth on
port 587
tls on
tls_certcheck on
tls_starttls on
logfile        ~/.config/msmtp.log
proxy_host 127.0.0.1
proxy_port 9050
tls_fingerprint D6:08:64:7C:AF:58:59:4B:C7:16:20:91:40:BC:09:B9:D8:4E:C0:20

account cryptomonkeys.org
host mail.cryptomonkeys.org
from louisk@ cryptomonkeys.org
user louisk@ cryptomonkeys.org
passwordeval "gpg2 --no-tty -q -d ~/.config/msmtprc-cryptomonkeys.org.gpg"

account default : cryptomonkeys.org

I’ve done a couple things worth mentioning here.

  1. I’ve taken the SSL fingerprint from the server and put it in the config file. Now, if somebody MITM’s me, msmtp won’t connect because it won’t get the correct fingerprint. This also means if the cert changes, I can’t send mail until I update the msmtprc config file.
  2. msmtp supports the use of a socks proxy. I’ve configured it to use my local tor instance.

Unfortunately, you can’t get granular about the version of SSL/TLS that is used on the client, so you have to do it on the server (if you can).

mailcap

There may be times when we want to define custom applications to open certain kinds of files. I’ve included an example of opening image files in quick-look.

#MS office documents
application/excel; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'
application/ms-exc; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'
application/msword; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Word.app'
application/vnd.ms-exc; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'
application/vnd.ms-excel; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'
application/x-msexcel; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'

# Images
image/*; $HOME/.mutt/view_attachment.sh %s "-" 'qlmanage -p'

# PDFs
application/pdf; $HOME/.mutt/view_attachment.sh %s

# HTML
text/html; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/TorBrowser.app'
text/html; w3m -I %{charset} -T text/html -dump %s; copiousoutput

view_attachments.sh

This is just a simple helper script referenced in the mailcap. Nothing terribly fancy.

#!/bin/bash
#
# author = "  Eric Gebhart
#
# Purpose:  To be called by Mutt as indicated by .mailcap to handle mail attachments.
#
# Function: Copy the given file to a temporary directory so mutt
#           Won't delete it before it is read by the application.
#
#           Along the way, discern the file type or use the type
#           That is given.
#
#           Finally use 'open' or 'open -a' if the third argument is
#           given.
#
#
# Arguments:
#
#     $1 is the file
#     $2 is the type - for those times when file magic isn't enough.
#                      I frequently get html mail that has no extension
#                      and file can't figure out what it is.
#
#                      Set to '-' if you don't want the type to be discerned.
#                      Many applications can sniff out the type on their own.
#                      And they do a better job of it too.
#
#                      Open Office and MS Office for example.
#
#     $3 is open with.  as in open -a 'open with this .app' foo.xls
#
# Examples:  These are typical .mailcap entries which use this program.
#
#     Image/JPEG; /Users/vdanen/.mutt/view_attachment %s
#     Image/PNG; /Users/vdanen/.mutt/view_attachment %s
#     Image/GIF; /Users/vdanen/.mutt/view_attachment %s
#
#     Application/PDF; /Users/vdanen/.mutt/view_attachment %s
#
#         #This HTML example passes the type because file doesn't always work and
#         #there aren't always extensions.
#
#     text/html; /Users/vdanen/.mutt/view_attachment %s html
#
#         # If your Start OpenOffice.org.app is spelled with a space like this one, <--
#         # then you'll need to precede the space with a \ .  I found that too painful
#         # and renamed it with an _.
#
#     Application/vnd.ms-excel; /Users/vdanen/.mutt/view_attachment %s "-" '/Applications/OpenOffice.org1.1.2/Start_OpenOffice.org.app'
#     Application/msword; /Users/vdanen/.mutt/view_attachment %s "-" '/Applications/OpenOffice.org1.1.2/Start_OpenOffice.org.app'
#
#
# Debugging:  If you have problems set debug to 'yes'.  That will cause a debug file
#             be written to /tmp/mutt_attach/debug so you can see what is going on.
#
# See Also:  The man pages for open, file, basename
#

# the tmp directory to use.
tmpdir="$HOME/.mutt/mutt_attach"

# the name of the debug file if debugging is turned on.
debug_file=$tmpdir/debug

# debug.  yes or no.
#debug="no"
debug="yes"

type=$2
open_with=$3

# make sure the tmpdir exists.
mkdir -p $tmpdir

# clean it out.  Remove this if you want the directory
# to accumulate attachment files.
rm -f $tmpdir/*

# Mutt puts everything in /tmp by default.
# This gets the basic filename from the full pathname.
filename=`basename $1`

# get rid of the extenson and save the name for later.
file=`echo $filename | cut -d"." -f1`

if [ $debug = "yes" ] ; then
    echo "1:" $1 " 2:" $2 " 3:" $3 > $debug_file
    echo "Filename:"$filename >> $debug_file
    echo "File:"$file >> $debug_file
    echo "===========================" >> $debug_file
fi

# if the type is empty then try to figure it out.
if [ -z $type ] ; then
    type=`file -bi $1 | cut -d"/" -f2`
fi

# if the type is '-' then we don't want to mess with type.
# Otherwise we are rebuilding the name.  Either from the
# type that was passed in or from the type we discerned.
if [ $type = "-" ] ; then
    newfile=$filename
else
    newfile=$file.$type
fi

newfile=$tmpdir/$newfile

# Copy the file to our new spot so Mutt can't delete it
# before the app has a chance to view it.
cp $1 $newfile

if [ $debug = "yes" ] ; then
    echo "File:" $file "TYPE:" $type >> $debug_file
    echo "Newfile:" $newfile >> $debug_file
    echo "Open With:" $open_with >> $debug_file
fi

# If there's no 'open with' then we can let preview do it's thing.
# Otherwise we've been told what to use.  So do an open -a.

if [ -z $open_with ] ; then
    open $newfile
else
    open -a "$open_with" $newfile
fi

Installing w3m

Why do we need w3m? Some email only shows up as HTML (text/html). We can ignore it (may not be a good idea, there are legitimate services that send HTML-only email), try to render it in our heads (kind of gives you a headache thinking about it), or have a utility that will let us view the content. My first idea was to use Firefox and open an HTML page in a new private window (the private window would keep things fairly disconnected from any other browsing on the system). Thus far, I’ve been unable to solve the problem of “you already have firefox open” when I attempt to use the command line and launch firefox with a URL. The next idea was to use the TorBrowser. This works quite nicely. It has the benefit of not keeping any tracking bits around between uses, communicating over the Tor network, and it can render the page in a more pleasing way if, for example, the goal is to print it.

So, 2 solutions here: 1 for simple reading of content, and 1 for pretty viewing of content.

$ brew install w3m

Configuring w3m

The config lives in ~/.w3m/config. The relevant bits that I set are:

ssl_forbid_method SSLv2, SSLv3
ftp_proxy 127.0.0.1:8118
https_proxy 127.0.0.1:8118
http_proxy 127.0.0.1:8118
use_proxy 1

This bumps the security if we pull anything over SSL, and it runs any external request over Tor.

Installing Little brother database

We need a way for Mutt to interact with a modern addressbook. One that you could use from other devices, such as a phone you might be carting around with you everywhere you go, making it convenient to add contact information. Enter Little Brother database4.

Installing lbdb via homebrew. Again, nice and simple.

$ brew install lbdb

Configuring Little brother database

Edit the /usr/local/lbdb/etc/lbdb.rc file and make the following changes:

This

# METHODS="m_inmail m_passwd m_finger"

Becomes this:

METHODS="m_muttalias m_osx_addressbook"

Uncomment these 2 lines:

#MUTT_DIRECTORY="$HOME/.mutt"
#MUTTALIAS_FILES=".muttrc .mail_aliases muttrc aliases"

Ensure this is in your muttrc

set query_command="/usr/local/lbdb/bin/lbdbq '%s'"

Now, when you compose a message, you can enter part of an address, followed by Cntl-T. Mutt will now show you all the entries that match and you can select the entry you want.

GnuPG over Tor

Part of the effort of getting mail and related services running over Tor5 includes GnuPG. Some this I had previously, some was added, courtesy of Ben Naggy 6.


keyserver-options http-proxy=http://127.0.0.1:8118,auto-key-retrieve
no-mangle-dos-filenames
auto-key-locate keyserver
charset utf-8
keyserver hkp://keyserver.pgp.com
keyserver hkp://pgp.mit.edu
default-key DCED3E1E6AAFDDB1C40FA3799C88F73C2602A9FC
no-emit-version
no-greeting
default-recipient-self
require-cross-certification
utf8-strings
no-comments

# IMPORTANT! GPG still defaults to bad choices for digests and symmetric
# ciphers. This doesn't totally eliminate the risk of a peer deliberately
# downgrading to weaker algorithms, but it makes the defaults strong when
# you communicate with good faith actors with up-to-date software.

personal-cipher-preferences AES256 AES192 AES
personal-digest-preferences SHA512 SHA384 SHA256 SHA224

# Don't include key-id metadata! The makes it a bit harder to link
# the parties that are communicating.
throw-keyids

# More like "Web of Mistrust", amirite??
trust-model always

Conclusion

Did you notice that there is mention of a system wide Tor in addition to using the Tor Browser? Its true, I have both installed. Most things can be (and have been) configured to use the system-wide proxy. The Tor Browser runs its own Tor instance and its more trouble than its worth to go dig around and reconfigure it to use the system instance.

Now, we have a mail setup using mutt, which connects over IMAP (SSL) with multiple accounts (Unfortunately, Mutt doesn’t seem to offer the ability to communicate over a socks proxy, so no Tor support for now). It sends mail via Submission (TLS) or SMTP (SSL) and optionally tunnelled via Tor. We have support for multiple accounts. Notifications for mail delivered to any of the mailboxes we listed. Integration with the OS X Contacts application, and the ability to view attachments with appropriate applications. What do we lose out on? Using a mouse. Not such a bad compromise.


Footnotes and References

*[Mutt]: Mutt is a text-based email client for Unix-like systems. It was originally written by Michael Elkins in 1995 and released under the GNU General Public License version 2 or any later version. *[a long time]: Somewhere between 10-20yrs


  1. http://brew.sh/ ↩︎

  2. https://github.com/Kdecherf/mutt-lightweight-sidebar ↩︎

  3. https://calomel.org/mutt_config.html ↩︎

  4. http://hints.macworld.com/article.php?story=20041024163030501 ↩︎

  5. https://trac.torproject.org/projects/tor/wiki/doc/TorifyHOWTO/GnuPG ↩︎

  6. https://gist.github.com/bnagy/8914f712f689cc01c267 ↩︎