For me, any sort of general purpose note taking and/or keeping solution needs to meet only a few requirements:

  1. Noting something has to be quick and easy (in a terminal and scriptable)
  2. Notes should be available from anywhere… tothecloud!
  3. Notes should be searchable

Now, just to clarify – I’m not talking about classroom notes, those things go in note-books. I’m talking about short little blurbs of information I would like to keep and reference at a later time.

Though, I suppose this could work for classroom notes too…

I’m also not talking about reminders, those are the stuff of calendars, not note-keeping apps.

So what’s my solution? What else, Gmail!


Setting up gmail as a note keeper/searcher is simple. A note is an email from me with the prefix “Note -” in the subject line. Therefore, it’s easy to setup a label and a filter to funnel note-mails into a defined folder:

From:    me@whatever.com
Subject: ^Note - 

I also add “Skip inbox” and “Mark as read” as part of the rule.

I know the gmail filters support some level of regex and/or globbing, but I don’t know where it ends. I’m hoping that the ^ anchor is supported but I’m not positive.

Requirements 2 and 3 done.


So if taking a note is done by just sending an email of a particular consistent format, then it’s easy for me to achieve requirement 1 since I use that awesome terminal mail client mutt.

A short bash function gives us uber-simple note taking abilities by handling the boilerplate of a note-mail:

noteit() {
  _have mutt || return 1 # see my dotfiles re: _have

  local subject="$*" message

  [[ -z "$subject" ]] && { echo 'no subject.'; return 1; }

  echo -e "^D to save, ^C to cancel\nNote:\n"


  [[ -z "$message" ]] && { echo 'no message.'; return 1; }

  # send message
  echo "$message" | mutt -s "Note - $subject" -- pbrisbin@gmail.com

  echo -e "\nnoted.\n"

You could probably also streamline note taking by leveraging mutt’s -H option. I’ll leave reading that man page snippet as an exercise to the reader.

And here’s how that might work out in the day-to-day:

//blue/0/~/ noteit test note
^D to save, ^C to cancel

This is a test note.

< I pressed ^D here >


You could also use sendmail, mailx, msmtp or whatever other CLI mail solution you want for this.

And there it is, ready to be indexed by the almighty google:

Mutt notes shot 

With a few mutt macros, I think this could get pretty featureful without a lot of code.

Let me know in the comments if there are any other simple or out-of-the-box note-keeping solutions you know of.

Oh, and before anyone mentions it – no, you can’t take notes without internet when you’re using this approach. I’m ok with that, I understand if you’re not.

26 Mar 2011, tagged with bash, gmail, linux, mutt

Using Two IMAP Accounts in Mutt

Mutt can be really great with multiple accounts, but it’s not exactly intuitive to setup. Here I’ll document how I access two Gmail accounts together in one mutt instance.

If you haven’t yet seen my previous mutt post, please go read that now. I recommend using that post to get a single account setup first before coming back here. Even if you plan to jump right into a multi-account setup, this post assumes you’ve at least read the other one and will focus on the differences and required changes to get from there to here.


To get Offlineimap syncing multiple accounts, we simply need to add additional configuration blocks to sync the second account with another local Maildir.


ui = ttyui
accounts = Personal,Work

[Account Personal]
localrepository = Personal-Local
remoterepository = Personal-Remote

[Account Work]
localrepository = Work-Local
remoterepository = Work-Remote

[Repository Personal-Local]
type = Maildir
localfolders = ~/Mail/Personal

[Repository Work-Local]
type = Maildir
localfolders = ~/Mail/Work

[Repository Personal-Remote]
type = Gmail
remoteuser = username@gmail.com
remotepass = secret
realdelete = no
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

[Repository Work-Remote]
type = Gmail
remoteuser = work-username@gmail.com
remotepass = secret
realdelete = no
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

Obviously, if either of these accounts weren’t a Gmail server, the configuration blocks would be different.

You can test your setup by running offlineimap -o to sync things once. It could take a while, but once done, you should have a nice folder structure like this:

|-- Personal
|   |-- INBOX
|   `-- ...
`-- Work
    |-- INBOX
    `-- ...


Msmtp also handles multiple accounts very elegantly, we just add another account block for the second account.


# shared defaults since both are gmail accounts
host smtp.gmail.com
port 587
protocol smtp
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt

account personal
from username@gmail.com
user username@gmail.com
password secret

account work
from work-username@gmail.com
user work-username@gmail.com
password secret

account default : personal

Now we can simply call msmtp -a personal or msmtp -a work to use whichever account we want. Omitting the -a option will use the default account which we’ve set as personal.


The goal with mutt is to have certain settings change when we enter certain folders. For example, when we’re viewing +Personal/INBOX we want our from setting to be our personal From address and the sendmail setting should be msmtp -a personal. To provide this functionality, we’re going to do the following:

  1. Place any account-specific settings in separate files
  2. Use mutt’s folder-hook facility to source the proper file and set the proper settings upon entering a folder for a given account.

Here are the two account-specific files:


set from      = "username@gmail.com"
set sendmail  = "/usr/bin/msmtp -a personal"
set mbox      = "+Personal/archive"
set postponed = "+Personal/drafts"

color status green default

macro index D \
    "<save-message>+Personal/Trash<enter>" \
    "move message to the trash"

macro index S \
    "<save-message>+Personal/Spam<enter>"  \
        "mark message as spam"


set from      = "work-username@gmail.com"
set sendmail  = "/usr/bin/msmtp -a work"
set mbox      = "+Work/archive"
set postponed = "+Work/drafts"

color status cyan default

macro index D \
    "<save-message>+Work/Trash<enter>" \
    "move message to the trash"

macro index S \
    "<save-message>+Work/Spam<enter>"  \
        "mark message as spam"

Notice the color line which changes the status bar depending on what account I’m “in” at any given moment.

The following settings will tell mutt to source one of these files upon entering a folder matching the given pattern, this will setup all the correct settings when entering a folder for a given account:


set spoolfile = "+Personal/INBOX"

source ~/.mutt/personal

folder-hook Personal/* source ~/.mutt/accounts/personal
folder-hook Work/*     source ~/.mutt/accounts/work

The first two lines effectively set Personal as the default account when we open mutt.

Well, that should do it. Open up mutt, change folders, send some mails, and make sure everything’s working as you’d expect.

For reference, my complete and current setup can be found with my dotfiles.

05 Dec 2009, tagged with linux, gmail, mutt

Mutt + Gmail + Offlineimap

Most people use Gmail. Some people like CLI mail clients. This post describes how I use Gmail in the best CLI mail client, mutt. Many people will back me up when I say it’s a very good setup.

For reference, my complete and current setup can be found with my dotfiles.


Step one is to setup Offlineimap to keep ~/Mail in sync with Gmail. This is a two way sync so anything moved, deleted, or sent from any IMAP-connected device or our local mutt interface will act exactly the same. This also has the benefit of storing offline, local copies of all your mails.

First, install Offlineimap and fill in an ~/.offlineimaprc like so:

ui = ttyui
accounts = Gmail

[Account Gmail]
localrepository = Gmail-Local
remoterepository = Gmail-Remote

[Repository Gmail-Local]
type = Maildir
localfolders = ~/Mail/Gmail

[Repository Gmail-Remote]
type = Gmail
remoteuser = you@gmail.com
remotepass = secret
realdelete = no
maxconnections = 3
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

Test that this works by running offlineimap -o. Your first sync could take some time, but once done, you should see the folders under ~/Mail/Gmail with the proper structure.

Once you’re satisfied syncing is working, we’ll schedule a periodic sync via cron.

There are some tempting options offlineimap has for daemonizing itself to handle periodic syncing for you – in my experience these don’t work. Scheduling a full offlineimap run via cron is the only working setup I’ve been able to find.

To work around a thread-joining bug, I’ve landed on a wrapper script that spawns offlineimap to the background then babysits the process for up to 60 seconds. If it appears to be hung, it’s killed.

#!/usr/bin/env bash

# Check every ten seconds if the process identified as $1 is still 
# running. After 5 checks (~60 seconds), kill it. Return non-zero to 
# indicate something was killed.
monitor() {
  local pid=$1 i=0

  while ps $pid &>/dev/null; do
    if (( i++ > 5 )); then
      echo "Max checks reached. Sending SIGKILL to ${pid}..." >&2
      kill -9 $pid; return 1

    sleep 10

  return 0

read -r pid < ~/.offlineimap/pid

if ps $pid &>/dev/null; then
  echo "Process $pid already running. Exiting..." >&2
  exit 1

offlineimap -o -u quiet & monitor $!

Set this script to run as frequently as you want, by adding something like the following to your crontab – I chose to sync once every 3 minutes:

*/3 * * * * /path/to/mailrun.sh


Now we need a way to send mails. I like msmtp, you can also use other smtp clients. If you choose to install msmtp, the config file is at ~/.msmtprc and should look like this:

account default 
host smtp.gmail.com
port 587
protocol smtp
auth on
from user@gmail.com
user user@gmail.com
password secret
tls on

You can test this by executing echo "a test message" | msmtp you@gmail.com.


Now the fun part! I don’t know how many hours I’ve spent in the past year fine tuning my muttrc, but it’ll never be done. Here are the parts required to get this setup working.

set mbox_type   = Maildir
set sendmail    = /usr/bin/msmtp

set folder      = ~/Mail
set spoolfile   = "+INBOX"
set mbox        = "+[Gmail]/All Mail"
set postponed   = "+[Gmail]/Drafts"
unset record

mailboxes +INBOX

macro index D \
    "<save-message>+[Gmail]/Trash<enter>" \
    "move message to the trash"

macro index S \
    "<save-message>+[Gmail]/Spam<enter>" \
    "mark message as spam"

The above should be enough to get a connection and start sending/receiving mail, but here are some other must-have options that make it feel a bit more like gmail:

# main options
set realname   = "Real Name"
set from       = "user@gmail.com"
set mail_check = 0
set envelope_from

unset move           # gmail does that
set delete           # don't ask, just do
unset confirmappend  # don't ask, just do!
set quit             # don't ask, just do!!
unset mark_old       # read/new is good enough for me

# sort/threading
set sort     = threads
set sort_aux = reverse-last-date-received
set sort_re

# look and feel
set pager_index_lines = 8
set pager_context     = 5
set pager_stop
set menu_scroll
set smart_wrap
set tilde
unset markers

# composing 
set fcc_attach
unset mime_forward
set forward_format = "Fwd: %s"
set include
set forward_quote

ignore *                               # first, ignore all headers
unignore from: to: cc: date: subject:  # then, show only these
hdr_order from: to: cc: date: subject: # and in this order

I’ve left out quite a few tweaks in the above so that those who are happy with mutt’s very sane defaults aren’t overwhelmed. Keep in mind, man muttrc is a great command for when you’re bored.

That should do it. Hopefully this info will get you going in the right direction.

05 Dec 2009, tagged with linux, gmail, mutt