Mutt and Msmtp on OS X

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:

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

and

1patch do
2   url "https://raw.githubusercontent.com/Kdecherf/mutt-lightweight-sidebar/master/mutt-lightweight-sidebar.patch"
3   sha1 "4c4f9516b1d507fa70dc88574ad65d1fc8c29c3d"
4end 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

1$ 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.

  1#######################################################
  2###  (Modified) Calomel.org .muttrc   BEGIN
  3#######################################################
  4# System configuration file for Mutt ( .muttrc )
  5#
  6### Account cryptomonkeys.org settings
  7source ~/.mutt/cryptomonkeys.org/config
  8folder-hook 'cryptomonkeys.org' 'source ~/.mutt/cryptomonkeys.org/config'
  9
 10### Account cryptomonkeys.com settings
 11folder-hook 'cryptomonkeys.com' 'source ~/.mutt/cryptomonkeys.com/config'
 12
 13### Account louiskowolowski.com settings
 14folder-hook 'louiskowolowski.com' 'source ~/.mutt/louiskowolowski.com/config'
 15
 16### Account louiskphoto.com settings
 17folder-hook 'louiskphoto.com' 'source ~/.mutt/louiskphoto.com/config'
 18
 19#######################################################
 20###  Pager
 21#######################################################
 22#ignore *
 23#unignore  X-Bogosity From: Reply-To: To: Cc: date = Subject:
 24#hdr_order X-Bogosity From: Reply-To: To: Cc: date = Subject:
 25
 26#######################################################
 27###  Macros
 28#######################################################
 29### Facilitate multiple accounts. Push button to change accounts.
 30macro index <f2> '<sync-mailbox><enter-command>source ~/.mutt/cryptomonkeys.org/config<enter><change-folder>!<enter>'
 31macro index <f3> '<sync-mailbox><enter-command>source ~/.mutt/cryptomonkeys.com/config<enter><change-folder>!<enter>'
 32macro index <f4> '<sync-mailbox><enter-command>source ~/.mutt/louiskowolowski.com/config<enter><change-folder>!<enter>'
 33macro index <f5> '<sync-mailbox><enter-command>source ~/.mutt/louiskphoto.com/config<enter><change-folder>!<enter>'
 34
 35### change mailbox
 36macro index <f6> 'c =INBOX^M'
 37macro pager <f6> 'c =INBOX^M'
 38macro index <f7> 'c =Sent^M'
 39macro pager <f7> 'c =Sent^M'
 40macro index <f8> 'c =Junk^M'
 41macro pager <f8> 'c =Junk^M'
 42
 43### save attachments to incoming
 44macro attach s <save-entry><bol>~/Downloads/
 45
 46macro index 'c' '<change-folder>?<change-dir><home>^K=<enter>'
 47
 48### Toggle sidebar visibility
 49macro index b '<enter-command>toggle sidebar_visible<enter>'
 50macro pager b '<enter-command>toggle sidebar_visible<enter>'
 51
 52#######################################################
 53###  Headers
 54#######################################################
 55# When OutLook receives email it will put it at the
 56# top of their mailbox list and flag it with an "urgent"
 57# red box. Just another way to play with Outlook users.
 58my_hdr X-Message-Flag: OUTLOOK WARNING!! Use Open Source
 59my_hdr Reply-By: `perl -MPOSIX -le '@now = localtime; $now[3] -= 3; print scalar localtime mktime @now'`
 60my_hdr X-MSMail-Priority: High
 61
 62#######################################################
 63###  Options
 64#######################################################
 65bind editor <BackSpace> backspace
 66
 67### Setup Sidebar navigation controls
 68### Shift-C, Shift-P, etc
 69bind index CP sidebar-prev
 70bind index CN sidebar-next
 71bind index CO sidebar-open
 72bind pager CP sidebar-prev
 73bind pager CN sidebar-next
 74bind pager CO sidebar-open
 75
 76# If enter-command is available from the UI, it is possible to see the
 77# password unencrypted, which my be undesired if anybody else than you has
 78# access to your session while Mutt is running. You may want to disable it for
 79# this reason. As a consequence, every command that the user intends to use
 80# must be bound to a key in advance, otherwise it will never be accessible.
 81bind generic,alias,attach,browser,editor,index,compose,pager,pgp,postpone ':' noop
 82
 83### Autoview attachments
 84unset implicit_autoview
 85alternative_order text/plain *
 86auto_view text/html text/enriched application/x-gunzip application/postscript image/gif application/x-tar-gz text/x-vcard application/octet-stream
 87
 88  # check mail every 5min
 89  set mail_check=600
 90
 91  # We can define special actions for certain types of files here
 92  set mailcap_path=~/.mailcap
 93
 94  # locally defined aliases
 95  set alias_file="~/.mutt/aliases"
 96
 97  # little brother db query string. Used to connect to external sources such as
 98  # ldap, apple contacts, etc.
 99  set query_command="/usr/local/bin/lbdbq '%s'"
100
101
102unset abort_nosubject
103
104
105unset abort_unmodified
106
107  # 8bit isn't safe
108  set noallow_8bit
109
110
111unset arrow_cursor
112
113  # don't restrict to ascii characters when displaying trees
114unset ascii_chars
115
116
117  set autoedit
118
119  # We <3 beeping software.
120unset beep
121unset beep_new
122
123
124unset bounce_delivered
125
126
127  set check_new
128
129
130  # Just append, don't hassle me.
131  set noconfirmappend
132
133  # Keep copies of outgoing mail...
134  set copy
135
136
137  set delete
138
139
140unset edit_headers
141
142  # keep vim from writing backup or swapfiles
143  set editor="vim +13 -c 'set nobackup' -c 'set noswapfile' -c 'set nowritebackup' -c 'set tw=72 ft=mail noautoindent'"
144
145  # set the envelope-from information
146  set envelope_from
147
148  # skip initial prompts when replying
149  set fast_reply
150
151
152unset fcc_attach
153
154  # Keep fcc's clear of signatues and encryption
155  set fcc_clear
156
157
158  set forward_decode
159
160  # Display download progress every 10k
161  set net_inc=10
162
163
164  set forward_quote=yes
165
166
167  set forward_format="Fwd: %s"
168
169  # show the help line at the bottom
170  set help
171
172  # Include the message in replies.
173  set include
174
175
176  set index_format="%3C %Z %(%D) %-27.27L (%4c) %s"
177
178
179  set indent_string=">"
180
181
182  set ispell="clear;aspell -e -c"
183
184
185  set mailcap_sanitize
186
187  # want any wrap markers.
188unset markers
189
190
191unset mark_old
192
193
194  set menu_scroll
195
196
197unset metoo
198
199  # Forward message as MIME attachments.
200  set mime_forward=yes
201
202
203  set mime_forward_decode
204
205
206  set mime_forward_rest
207
208
209  set pager="builtin"
210
211
212  set pager_format=""
213
214  # Don't skip msgs on next page.
215  set pager_stop
216
217  # Display 15 lines of context in pager.
218  set pager_context=15
219
220  # Display 20 lines of index in pager.
221  #set pager_index_lines=20
222
223
224unset postpone
225
226  # Ask before printing.
227  set print=ask-no
228
229
230  set print_command="~/.config/mutt/mutt_print.sh"
231
232  # Read counter ticks every 100 msgs.
233  set read_inc=2
234
235
236unset reply_self
237
238
239  set reply_to
240
241  # put dashes between message and signature
242  set sig_dashes=yes
243
244
245  set smart_wrap
246
247  # always sort by thread
248  set sort=threads
249
250  # sort in reverse
251  set sort_re
252
253  # Sort threads by date received (in reverse)
254  set sort_aux=reverse-date-sent
255
256
257  set status_on_top
258
259  # Don't do fuzzy threading.
260unset strict_threads
261
262
263unset suspend
264
265  # Fill out messages with '~'.
266  set tilde
267
268
269  set timeout=300
270
271
272  set thorough_search
273
274
275unset user_agent
276
277
278unset wait_key
279
280
281unset write_bcc
282
283
284  set attribution="* %n <%a> [%{%Y-%m-%d %H:%M:%S %Z}]:\n"
285
286
287  set smileys="(>From )|(:[-^]?[][)(><}{|/DP])"
288
289
290  set send_charset="us-ascii:iso-8859-1:utf-8"
291
292  # What we consider to be a quote.
293  set quote_regexp="^( {0,4}[>|:#%]| {0,4}[a-z0-9]+[>|]+)+"
294  set to_chars=" +TCF "                     # Drop the "L".
295
296  ### Sidebar customization
297  set sidebar_visible=yes
298  set sidebar_width=30
299  set sidebar_delim='  '
300  set sidebar_sort=yes
301  set sidebar_indentstr="-> "
302  set sidebar_folderindent=yes
303  set sidebar_format='%! %B'
304  set sidebar_shortpath=yes
305
306  ### Imap settings that apply to all accounts
307  set imap_delim_chars="."
308  set imap_idle=yes
309  set imap_check_subscribed=yes
310  set imap_list_subscribed=yes
311  set imap_keepalive=60
312  set imap_passive=no
313
314  ### SSL Hardening
315  set ssl_force_tls=yes
316  set ssl_starttls=yes
317  set ssl_use_sslv2=no
318  set ssl_use_sslv3=no
319  set ssl_use_tlsv1=no
320  set ssl_use_tlsv1_1=no
321  set ssl_use_tlsv1_2=yes
322  set ssl_verify_dates=yes
323  set ssl_verify_host=yes
324  unset ssl_usesystemcerts
325  set certificate_file=~/.mutt/muttcerts
326
327#######################################################
328###  Hooks
329#######################################################
330### Hooks
331send-hook . "set signature=~/.signature"
332send-hook . 'unset pgp_autoencrypt pgp_autosign'
333
334### Mark mail as read
335#folder-hook archive push '<tag-pattern>.*\r<tag-prefix><clear-flag>N<untag-pattern>.*\r'
336
337### Delete old mail after a set number of days
338#folder-hook archive push 'D~r>32d!~F\n'
339#folder-hook SPAM push 'D~r>60d!~F\n'
340
341### Include Colors
342#####################################################################
343# colors
344###
345### color pager
346# Rados' colors
347#source colors_rado
348
349source `case $TERM in\
350		*256color) echo '~/.mutt/colors256-dark'; break ;;\
351		*rxvt-unicode) echo '~/.mutt/colors256-dark'; break ;;\
352	esac`
353
354#source ~/.mutt/mutt-colors.muttrc
355#source ~/.mutt/mutt-colors-solarized-light-16.muttrc
356
357### Include mailboxes we want to check for new mail
358source ~/.mutt/mailboxes
359
360### Include headers we want to see
361source ~/.mutt/headers
362
363#######################################################
364###  Calomel.org .muttrc  END
365#######################################################

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

 1# Include the profile name in the status line
 2set 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)---"
 3
 4my_hdr From: louisk@ cryptomonkeys.org (Louis Kowolowski)
 5my_hdr Reply-To: louisk@ cryptomonkeys.org (Louis Kowolowski)
 6my_hdr Errors-To: louisk@ cryptomonkeys.org
 7my_hdr Organization: Open Source Software Supporter (OSSs)
 8
 9set hostname="cryptomonkeys.org"
10set folder='imaps://mail.cryptomonkeys.org/'
11set imap_authenticators="login"
12source "gpg2 -dq $HOME/.mutt/cryptomonkeys.org/cm.org.gpg |"
13set imap_pass=$my_cm_org_password
14set imap_user='louisk@ cryptomonkeys.org'
15set postponed='imaps://mail.cryptomonkeys.org/Drafts'
16set record='imaps://mail.cryptomonkeys.org/Sent'
17set spoolfile='imaps://mail.cryptomonkeys.org/INBOX'
18set sendmail="/usr/local/bin/msmtp -a cryptomonkeys.org"
19
20#######################################################
21###  GPG Hooks
22#######################################################
23my_hdr X-GPG-Key-Server: http://keyserver.pgp.com
24my_hdr X-GPG-Key-FingerPrint: DCED 3E1E 6AAF DDB1 C40F A379 9C88 F73C 2602 A9FC
25
26send-hook louisk@ cryptomonkeys.org 'set pgp_autosign; set pgp_autoencrypt'
27pgp-hook louisk@ cryptomonkeys.org 2602A9FC
28
29set pgp_decode_command="gpg %?p?--passphrase-fd 0? --no-verbose --batch --output - %f"
30set pgp_verify_command="gpg --no-verbose --batch --output - --verify %s %f"
31set pgp_decrypt_command="gpg --passphrase-fd 0 --no-verbose --batch --output - %f"
32set pgp_sign_command="gpg --no-verbose --batch --output - --passphrase-fd 0 --armor --detach-sign --textmode %?a?-u %a? %f"
33set pgp_clearsign_command="gpg --no-verbose --batch --output - --passphrase-fd 0 --armor --textmode --clearsign %?a?-u %a? %f"
34set 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"
35set 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"
36set pgp_import_command="gpg --no-verbose --import -v %f"
37set pgp_export_command="gpg --no-verbose --export --armor %r"
38set pgp_verify_key_command="gpg --no-verbose --batch --fingerprint --check-sigs %r"
39set pgp_list_pubring_command="gpg --no-verbose --batch --with-colons --list-keys %r"
40set pgp_list_secring_command="gpg --no-verbose --batch --with-colons --list-secret-keys %r"
41unset pgp_retainable_sigs
42set pgp_ignore_subkeys
43set pgp_verify_sig=yes
44set pgp_create_traditional=no
45set pgp_autosign=no
46set pgp_autoencrypt=no
47set pgp_sign_as=2602A9FC
48set pgp_replysignencrypted
49set pgp_replyencrypt=yes
50set pgp_replysign=yes
51set pgp_timeout=3600
52set pgp_good_sign="^gpg: Good signature from"
53
54# GPG/PGP colors
55color body brightblack cyan "^gpg: Signature made.*"
56color body brightblack green "^gpg: Good signature from.*"
57color body brightblack yellow "^gpg: Can't check signature.*"
58color body brightblack yellow "^gpg: WARNING: .*"
59color 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:

1set 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:

1$ 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:

1set 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.

1# If enter-command is available from the UI, it is possible to see the
2# password unencrypted, which my be undesired if anybody else than you has
3# access to your session while Mutt is running. You may want to disable it for
4# this reason. As a consequence, every command that the user intends to use
5# must be bound to a key in advance, otherwise it will never be accessible.
6bind 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.

 1# -*- muttrc -*-
 2#
 3# Configure header displays.
 4#
 5
 6# Ignore all headers
 7ignore *
 8
 9# Then un-ignore the ones I want to see
10unignore From:
11unignore To:
12unignore Reply-To:
13unignore Mail-Followup-To:
14unignore Subject:
15unignore date =
16unignore Organization:
17unignore Newsgroups:
18unignore CC:
19unignore BCC:
20unignore X-Mailer:
21unignore User-Agent:
22unignore X-Virus-Status:
23unignore X-Spam-Status:
24unignore X-Spam-Flag:
25
26# Now order the visable header lines
27hdr_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).

 1#!/bin/sh
 2pfile="${1}"
 3pdir="${HOME}/.mutt/mutt_print"
 4
 5if [ ! -d ${pdir} ]; then
 6    mkdir -p ${pdir}
 7fi
 8
 9# delete any old temporary files first
10rm -f ${pdir}/mutt_*.pdf
11
12tmpfile="`mktemp ${pdir}/mutt_$$`"
13mv -f ${tmpfile} ${tmpfile}.pdf
14enscript --font=Times-Roman10 --pretty-print ${1} -o - 2>/dev/null | pstopdf -i -o ${tmpfile}.pdf
15open ${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:

1$ 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!

1$ 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:

1$ 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

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

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

 1defaults
 2auth on
 3port 587
 4tls on
 5tls_certcheck on
 6tls_starttls on
 7logfile        ~/.config/msmtp.log
 8proxy_host 127.0.0.1
 9proxy_port 9050
10tls_fingerprint D6:08:64:7C:AF:58:59:4B:C7:16:20:91:40:BC:09:B9:D8:4E:C0:20
11
12account cryptomonkeys.org
13host mail.cryptomonkeys.org
14from louisk@ cryptomonkeys.org
15user louisk@ cryptomonkeys.org
16passwordeval "gpg2 --no-tty -q -d ~/.config/msmtprc-cryptomonkeys.org.gpg"
17
18account 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.

 1#MS office documents
 2application/excel; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'
 3application/ms-exc; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'
 4application/msword; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Word.app'
 5application/vnd.ms-exc; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'
 6application/vnd.ms-excel; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'
 7application/x-msexcel; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/Microsoft Excel.app'
 8
 9# Images
10image/*; $HOME/.mutt/view_attachment.sh %s "-" 'qlmanage -p'
11
12# PDFs
13application/pdf; $HOME/.mutt/view_attachment.sh %s
14
15# HTML
16text/html; $HOME/.mutt/view_attachment.sh %s "-" '/Applications/TorBrowser.app'
17text/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.

  1#!/bin/bash
  2#
  3# author = "  Eric Gebhart
  4#
  5# Purpose:  To be called by Mutt as indicated by .mailcap to handle mail attachments.
  6#
  7# Function: Copy the given file to a temporary directory so mutt
  8#           Won't delete it before it is read by the application.
  9#
 10#           Along the way, discern the file type or use the type
 11#           That is given.
 12#
 13#           Finally use 'open' or 'open -a' if the third argument is
 14#           given.
 15#
 16#
 17# Arguments:
 18#
 19#     $1 is the file
 20#     $2 is the type - for those times when file magic isn't enough.
 21#                      I frequently get html mail that has no extension
 22#                      and file can't figure out what it is.
 23#
 24#                      Set to '-' if you don't want the type to be discerned.
 25#                      Many applications can sniff out the type on their own.
 26#                      And they do a better job of it too.
 27#
 28#                      Open Office and MS Office for example.
 29#
 30#     $3 is open with.  as in open -a 'open with this .app' foo.xls
 31#
 32# Examples:  These are typical .mailcap entries which use this program.
 33#
 34#     Image/JPEG; /Users/vdanen/.mutt/view_attachment %s
 35#     Image/PNG; /Users/vdanen/.mutt/view_attachment %s
 36#     Image/GIF; /Users/vdanen/.mutt/view_attachment %s
 37#
 38#     Application/PDF; /Users/vdanen/.mutt/view_attachment %s
 39#
 40#         #This HTML example passes the type because file doesn't always work and
 41#         #there aren't always extensions.
 42#
 43#     text/html; /Users/vdanen/.mutt/view_attachment %s html
 44#
 45#         # If your Start OpenOffice.org.app is spelled with a space like this one, <--
 46#         # then you'll need to precede the space with a \ .  I found that too painful
 47#         # and renamed it with an _.
 48#
 49#     Application/vnd.ms-excel; /Users/vdanen/.mutt/view_attachment %s "-" '/Applications/OpenOffice.org1.1.2/Start_OpenOffice.org.app'
 50#     Application/msword; /Users/vdanen/.mutt/view_attachment %s "-" '/Applications/OpenOffice.org1.1.2/Start_OpenOffice.org.app'
 51#
 52#
 53# Debugging:  If you have problems set debug to 'yes'.  That will cause a debug file
 54#             be written to /tmp/mutt_attach/debug so you can see what is going on.
 55#
 56# See Also:  The man pages for open, file, basename
 57#
 58
 59# the tmp directory to use.
 60tmpdir="$HOME/.mutt/mutt_attach"
 61
 62# the name of the debug file if debugging is turned on.
 63debug_file=$tmpdir/debug
 64
 65# debug.  yes or no.
 66#debug="no"
 67debug="yes"
 68
 69type=$2
 70open_with=$3
 71
 72# make sure the tmpdir exists.
 73mkdir -p $tmpdir
 74
 75# clean it out.  Remove this if you want the directory
 76# to accumulate attachment files.
 77rm -f $tmpdir/*
 78
 79# Mutt puts everything in /tmp by default.
 80# This gets the basic filename from the full pathname.
 81filename=`basename $1`
 82
 83# get rid of the extenson and save the name for later.
 84file=`echo $filename | cut -d"." -f1`
 85
 86if [ $debug = "yes" ] ; then
 87    echo "1:" $1 " 2:" $2 " 3:" $3 > $debug_file
 88    echo "Filename:"$filename >> $debug_file
 89    echo "File:"$file >> $debug_file
 90    echo "===========================" >> $debug_file
 91fi
 92
 93# if the type is empty then try to figure it out.
 94if [ -z $type ] ; then
 95    type=`file -bi $1 | cut -d"/" -f2`
 96fi
 97
 98# if the type is '-' then we don't want to mess with type.
 99# Otherwise we are rebuilding the name.  Either from the
100# type that was passed in or from the type we discerned.
101if [ $type = "-" ] ; then
102    newfile=$filename
103else
104    newfile=$file.$type
105fi
106
107newfile=$tmpdir/$newfile
108
109# Copy the file to our new spot so Mutt can't delete it
110# before the app has a chance to view it.
111cp $1 $newfile
112
113if [ $debug = "yes" ] ; then
114    echo "File:" $file "TYPE:" $type >> $debug_file
115    echo "Newfile:" $newfile >> $debug_file
116    echo "Open With:" $open_with >> $debug_file
117fi
118
119# If there's no 'open with' then we can let preview do it's thing.
120# Otherwise we've been told what to use.  So do an open -a.
121
122if [ -z $open_with ] ; then
123    open $newfile
124else
125    open -a "$open_with" $newfile
126fi

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.

1$ brew install w3m

Configuring w3m

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

1ssl_forbid_method SSLv2, SSLv3
2ftp_proxy 127.0.0.1:8118
3https_proxy 127.0.0.1:8118
4http_proxy 127.0.0.1:8118
5use_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.

1$ brew install lbdb

Configuring Little brother database

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

This

1# METHODS="m_inmail m_passwd m_finger"

Becomes this:

1METHODS="m_muttalias m_osx_addressbook"

Uncomment these 2 lines:

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

Ensure this is in your muttrc

1set 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.

 1
 2keyserver-options http-proxy=http://127.0.0.1:8118,auto-key-retrieve
 3no-mangle-dos-filenames
 4auto-key-locate keyserver
 5charset utf-8
 6keyserver hkp://keyserver.pgp.com
 7keyserver hkp://pgp.mit.edu
 8default-key DCED3E1E6AAFDDB1C40FA3799C88F73C2602A9FC
 9no-emit-version
10no-greeting
11default-recipient-self
12require-cross-certification
13utf8-strings
14no-comments
15
16# IMPORTANT! GPG still defaults to bad choices for digests and symmetric
17# ciphers. This doesn't totally eliminate the risk of a peer deliberately
18# downgrading to weaker algorithms, but it makes the defaults strong when
19# you communicate with good faith actors with up-to-date software.
20
21personal-cipher-preferences AES256 AES192 AES
22personal-digest-preferences SHA512 SHA384 SHA256 SHA224
23
24# Don't include key-id metadata! The makes it a bit harder to link
25# the parties that are communicating.
26throw-keyids
27
28# More like "Web of Mistrust", amirite??
29trust-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

Copyright

Comments