Setting up neomutt with offlineimap and msmtp

25 Jul 2020


Recently I tried setting up my own email server with the help of Luke Smith's emailwiz script. And it went well. Run echo "YUBha3RzYm90LmluCg==" | base64 --decode in your terminal, to hit me up on the new email adress :)

Now I needed to use an email client with which I can connect to the mail server. I tried thunderbird, but it felt a bit too sluggish for my taste. Then I came across one of Luke Smith's other gems called mutt-wizard. Instead of running the tool he provided, I thought it'd be fun to set things up by hand. Hence this write-up.

Please watch this and this to get a feel for what we're going to be setting up.

Our goal

offlineimap

Offlineimap when configured, will go to our email server and download all of our email to a folder of our choosing, on our computer.

Run the following to install it, if you're running voidlinux.

$ sudo xbps-install offlineimap

All the packages in this post are available in most distros. So consult your package manager docs on how to search for them.

To configure it, create a file called .offlineimaprc in our $HOME folder.

$ cat ~/.offlineimaprc

[general]
ui = ttyui
accounts = mydomain.com,disroot.org

#### account 1 ------------------------------------
[Account mydomain.com]
localrepository = mydomain.com-local
remoterepository = mydomain.com-remote

[Repository mydomain.com-local]
type = Maildir
localfolders = ~/Mail/mydomain.com
restoreatime = no

[Repository mydomain.com-remote]
type = IMAP
remoteuser = yoshi
remotepass = mySuperS3cr3tPassword
remotehost = mail.mydomain.com
ssl = yes
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

#### account 2 ------------------------------------
[Account disroot.org]
localrepository = disroot.org-local
remoterepository = disroot.org-remote

[Repository disroot.org-local]
type = Maildir
localfolders = ~/Mail/disroot.org
restoreatime = no

[Repository disroot.org-remote]
type = IMAP
remoteuser = [email protected]
remotepass = mySuperS3cr3tPassword
remotehost = disroot.org
remoteport = 993

As we can see, we have 2 email accounts configured in the above config file.

Now when we run $ offlineimap, it'll start downloading emails from both our accounts to ~/Mail/mydomain.com and ~/Mail/disroot.org. It might take a while to finish as it depends on the amount of mail we have.

If we just run $ offlineimap -a mydomain.com or $ offlineimap -a disroot.org, it'll download email for just that account. The name should be the same as what we mentioned in the [Account xxxxx] section.

The next time we run $ offlineimap, only new emails would get downloaded. And that's it for configuring offlineimap.

Go ahead and check your ~/Mail folder and sub-folders. It should contain our email.

msmtp

msmtp, simply put is a tool for sending emails from the command-line.

Run the following to install it.

$ sudo xbps-install msmtp

When configured, we could do

$ echo "Subject: Oye from msmtp" | msmtp -a disroot.org [email protected]

and [email protected] would get a mail from the account we configured with the name of disroot.org. If this seems too weird, don't worry. It'll become a lot clearer after we configure it.

Go ahead and create a file called .msmtprc in our $HOME folder.

$ cat ~/.msmtprc

defaults
protocol smtp
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
syslog LOG_USER
logfile ~/.msmtp.log
timeout 60

#### account 1 ------------------------------------
account mydomain.com
host mail.mydomain.com
port 587
domain mydomain.com
from [email protected]
user yoshi
password mySuperS3cr3tPassword

#### account 2 ------------------------------------
account disroot.org
host disroot.org
port 587
domain disroot.org
from [email protected]
user [email protected]
password mySuperS3cr3tPassword

account default : mydomain.com

Like offlineimap's config, we have sectioned the config based on the accounts we'll be using. Pay attention to the user line in both account entries. For an email service like disroot, the username would be the full email address. But for our email server, it'd be just a name.

With this in place, if we do

$ echo "Subject: Hello from msmtp" | msmtp -a mydomain.com [email protected]

[email protected] would receive a mail from our account in mydomain.com. Switch mydomain.com with disroot.org in the command above and we can send emails using our account on disroot.

The last line in the config, just makes mydomain.com as the default account, we'd like to use, if none is provided as an argument. For example,

$ echo "Subject: Ola from msmtp" | msmtp [email protected]

would send a mail using the mydomain.com account. And with that msmtp is configured.

neomutt

neomutt/mutt is our mail client. It can do both fetching and sending emails, but configuring it for doing that for multiple accounts is notoriously painful. Hence this approach.

Install it with

$ sudo xbps-install neomutt

In this writeup, we'll focus on making neomutt

To make things a bit more manageable, we'll be splitting up the config into multiple files.

The configs live in ~/.config/neomutt. So make sure that folder is present. Let's start by setting up our different accounts first.

We need to be in neomutt's config folder, so $ cd ~/.config/neomutt.

$ mkdir accounts
$ touch accounts/mydomain.com
$ touch accounts/disroot.org

Now lets add content to those files.

$ cat accounts/mydomain.com

unmailboxes *

set from = "[email protected]"
set sendmail = "/usr/bin/msmtp -a mydomain.com"
set folder = "~/Mail/mydomain.com/"
set spoolfile = "+INBOX"
set postponed = "+Drafts"
set record = "+Sent"
set trash = "+Junk"

alias me "Yoshi Nakamura" "[email protected]"

set mbox_type = Maildir
set ssl_starttls = yes
set ssl_force_tls = yes

mailboxes =INBOX =Sent =Drafts =Junk

neomutt comes with a sidebar to display the folders we have available in a particular account. Later on in the config, we'd setup a keybind to toggle between accounts. unmailboxes * would just update the sidebar with the particular account's folders, as we change between them. The rest of the config is pretty much self explanatory.

$ cat accounts/disroot.org 

unmailboxes *

set from      = "[email protected]"
set sendmail  = "/usr/bin/msmtp -a disroot.org"
set folder = "~/Mail/disroot.org/"
set spoolfile = "+INBOX"
set postponed = "+Drafts"
set record = "+Sent"
set trash = "+Junk"

alias me "Ou Rname" "[email protected]"

set mbox_type = Maildir
set ssl_starttls = yes
set ssl_force_tls = yes

mailboxes =INBOX =Sent =Drafts =Junk =Trash =Archive

To know, what are all the possible folder names we can set for mailboxes, look inside ~/Mail/disroot.org/ or ~/Mail/mydomain.com/

Now that we have both accounts setup, lets setup a way to toggle between them.

Create a file in neomutt's config folder called mailboxes.muttrc.

$ cat mailboxes.muttrc 

macro index,pager <f2> '<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/mydomain.com<enter><change-folder>!<enter>;<check-stats>'
macro index,pager <f3> '<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/disroot.org<enter><change-folder>!<enter>;<check-stats>'

source ~/.config/neomutt/accounts/mydomain.com

All this file does is, when in neomutt, if we press F2 or F3 we can switch between our accounts. And by default the mail from mydomain.com will be shown, when neomutt opens up.

By default, neomutt looks a bit plain, so lets add some colors to it. Create a file called colors.muttrc

$ cat colors.muttrc

# Default index colors:
color index yellow default '.*'
color index_author red default '.*'
color index_number blue default
color index_subject cyan default '.*'

# New mail is boldened:
color index brightyellow black "~N"
color index_author brightred black "~N"
color index_subject brightcyan black "~N"

# Tagged mail is highlighted:
color index brightyellow blue "~T"
color index_author brightred blue "~T"
color index_subject brightcyan blue "~T"

# Other colors and aesthetic settings:
mono bold bold
mono underline underline
mono indicator reverse
mono error bold
color normal default default
color indicator brightblack white
color sidebar_highlight red default
color sidebar_divider brightblack black
color sidebar_flagged red black
color sidebar_new green black
color normal brightyellow default
color error red default
color tilde black default
color message cyan default
color markers red white
color attachment white default
color search brightmagenta default
color status brightyellow black
color hdrdefault brightgreen default
color quoted green default
color quoted1 blue default
color quoted2 cyan default
color quoted3 yellow default
color quoted4 red default
color quoted5 brightred default
color signature brightgreen default
color bold black default
color underline black default
color normal default default

# Regex highlighting:
color header blue default ".*"
color header brightmagenta default "^(From)"
color header brightcyan default "^(Subject)"
color header brightwhite default "^(CC|BCC)"
color body brightred default "[\-\.+_a-zA-Z0-9][email protected][\-\.a-zA-Z0-9]+" # Email addresses
color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL
color body green default "\`[^\`]*\`" # Green text between ` and `
color body brightblue default "^# \.*" # Headings as bold blue
color body brightcyan default "^## \.*" # Subheadings as bold cyan
color body brightgreen default "^### \.*" # Subsubheadings as bold green
color body yellow default "^(	| )*(-|\*) \.*" # List items as yellow
color body brightcyan default "[;:][-o][)/(|]" # emoticons
color body brightcyan default "[;:][)(|]" # emoticons
color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
color body red default "(BAD signature)"
color body cyan default "(Good signature)"
color body brightblack default "^gpg: Good signature .*"
color body brightyellow default "^gpg: "
color body brightyellow red "^gpg: BAD signature from.*"
mono body bold "^gpg: Good signature"
mono body bold "^gpg: BAD signature from.*"
color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\.?|[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? 	
<>\"]"

Now to bring everything together. Create a file called neomuttrc. This file would link the files that we have created thus far.

$ cat neomuttrc

source mailboxes.muttrc

set realname="Ou Rname"
set sort='reverse-date'

set use_from=yes                                                                
set ssl_starttls=yes                                                            
set ssl_force_tls=yes  

set editor="vim"
set rfc2047_parameters = yes                                                    
set sleep_time = 0    # Pause 0 seconds for informational messages              
set markers = no    # Disables the `+` displayed at line wraps                  
set mark_old = no   # Unread mail stay unread until read                        
set mime_forward = yes    # attachments are forwarded with mail                 
set wait_key = no   # mutt won't ask "press key to continue"                    
set fast_reply      # skip to compose when replying                             
set fcc_attach      # save attachments with the body                            
set forward_format = "Fwd: %s"  # format of subject when forwarding             
set forward_quote   # include message in forwards                               
set reverse_name    # reply as whomever it was to                               
set include     # include message in replies  

set sidebar_visible = yes                                                       
set sidebar_width = 20                                                          
set sidebar_short_path = yes                                                    
set sidebar_next_new_wrap = yes                                                 
set mail_check_stats                                                            
set sidebar_format = '%B%?F? [%F]?%* %?N?%N/? %?S?%S?'

source colors.muttrc                                                              
                                                                                
macro index O "<shell-escape>offlineimap <enter>" "run offlineimap to sync all mail"

Phew! With that our neomutt should be configured and ready to go. Just run

$ neomutt

And you'd be greeted by something that looks like this

neomutt

If you're a neomutt beginner like me, do bookmark the getting started guide.

Keybinds not working?

Make sure your terminal's $TERM variable is properly set. Otherwise, the keybinds may not work. In my case urxvt didn't register the F2 and F3 keypresses, as I had manually set URxvt.termName: xterm-256color in ~/.Xresources. Remove that, and you should be good.

$ echo $TERM
rxvt-unicode-256color

Credits

Fin

The config files in this post are butchered and in some cases like the color definitions, are outright "borrowed" from the above mentioned links. I cannot thank them enough for their efforts.

Hope you gained something worth while from this post.

Happy Hacking & have a great day!