Configure mu4e and msmtp

Tags: emacs mu4e technical

I am using mu4e for reading and sending emails wherever possible: mostly for the technical discussions or any quick emails where HTML isn’t required. I have multipl accounts, Gmail & Fastmail, the latter mostly because it provides an excellent service, has support for custom domain, and seemingly unlimited aliases.

Having said that, I had a few hiccups while setting up muliple providers with mu4e. Out of the box, it provides what are called as contexts which are dynamic placeholders for messages based on some predefined rules. Sending an email from given address is as quick as changing the context by pressing ; and writing & sending it off. But I wasn’t able to make it work really well for one reason or another and wasn’t able to send mails using Fastmail.

I spend quite some time today, read all over the internet, tried debugging the emacs configuration but finally decided to make the configuration a bit more sane after reading a reddit comment from IceDane. The gist is that email can be divided into three parts:

  • Getting it
  • Indexing & Reading it
  • Sending it

And using good applications where each can do one thing well makes sense:

  • Getting it: mbsync
  • Indexing & Reading it: mu + mu4e
  • Sending it: ??

Getting the emails and indexing them was working flawlessly. Initially I was rolling with the default sendmail that came with Debian. The problem of using it with mu4e was that the entire configuration had to come as part of contexts:

(setq mu4e-contexts
      `(
        ,(make-mu4e-context
          :name "fastmail"
          :enter-func
          (lambda ()
            (mu4e-message "Entering Fastmail contenxt"))
          :leave-func (lambda () (mu4e-message "Leaving fastmail context"))
          :vars
          '((; A lot of stuff removed from here
            (smtpmail-smtp-server "smtp.fastmail.com")
            (smtpmail-default-smtp-server . "smtp.fastmail.com")
            (smtpmail-smtp-server . "smtp.fastmail.com")
            (smtpmail-local-domain . "fastmail.com")
            (user-mail-address . "username@fastmail.com")))))

msmtp provides a good configuration file to setup each email differently. The benefit of using it was that I could move the configuration out to its own file, and just forward the send request from emacs to msmtp.

The changes on emacs side were actually minimal as well. I needed to configure msmtp as the sendmail program in Emacs, and provide the option --read-envelope-from as an extra argument. This causes msmtp to read the sending address from the header of the message and use that to get the configuration for sending the email. This also means that the individual contexts in mu4e are pretty slim as well as the configuration for ports, endpoints, etc. can be moved out.

Also, we need to set message-sendmail-f-is-evil to remove the username from the emacs message. This is anyhow read from the msmtp configuration.

(setq sendmail-program "/usr/bin/msmtp"
      send-mail-function 'smtpmail-send-it
      message-sendmail-f-is-evil t
      message-sendmail-extra-arguments '("--read-envelope-from")
      message-send-mail-function 'message-send-mail-with-sendmail)

Finally, ~/.msmtprc configuration is also pretty sleek:

# Set default values for all following accounts.
defaults
auth           on
tls            on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        ~/.msmtp.log

# Gmail
account        gmail
host           smtp.gmail.com
port           587
from           username@gmail.com
user           username
password       app-specific-password

# A freemail service
account        fastmail
host           smtp.fastmail.com
port           465
from           username@fastmail.com
user           username@fastmail.com
tls_starttls   off
password       app-specific-password

# Set a default account
account default : gmail

Adding new account is just adding it to the configuration file, adding the context to mu4e configuration and start sending the message.