mutt integration with Gmail using OAuth

As I mentioned before, I am a heavy terminal user, including viewing and replying emails with it. Mutt is my email client. Once you have setup your 2 factor authentication with Google, you won’t be able to access your Gmail using IMAP with your password, you’ll have to generate a specific password for the so called “Less Secure Apps”. There is a problem with that, if you use IMAP with less-secure-app password on your company account where “less secure app” is not allowed, you are probably stuck.

In this tutorial, I am going to show you how to setup the Google recommended OAuth 2.0 way with Mutt.

Remember, the OAuth client setup should be an one-time step, it should be usable for your different email addresses on Gmail, that includes your work email if your employer choose Gmail as their email service provider, as long as you authorize permission during the OAuth App.

  1. Login to your google account, navigate to https://console.cloud.google.com/apis/credentials and if this page says anything API not enabled, enable it.
  2. In the credentials page, create a project.
  3. After creating the project, you should be able to go to the OAuth consent screen tab, put something recognizable in the application name, click save.
  4. Go back to “Credentials” page and click on “Create credentials” button and select OAuth client ID.
  5. Select other and click create. You’ll be given an OAuth client ID and secret. You can view the id and secret anytime.

Now you’ve setup an OAuth client, it is time for mutt configuration.

Download oauth2.py from GitHub: https://github.com/google/gmail-oauth2-tools/blob/master/python/oauth2.py and make it executable. You’ll need to run the command to generate an OAuth token.

./oauth2.py [email protected] \
--client_id=2345...0123.apps.googleusercontent.com \
--client_secret=s_ec_ret --generate_oauth2_token

Open the web browser with the link given and authenticate yourself, login and grant permission. Paste the response code back to terminal. You’ll be given the access token and refresh token, you’ll need the information next.

The way I manage my files under ~/.mutt:

.
|-- accounts
|   |-- gmail.asc
|   |-- account2.asc
|   |-- account3.asc
|-- mailcap
|-- muttrc
|-- oauth2.py
...

The muttrc master config file only manage generic stuff such as header and format stuff, it also has some macro to map function keys to switch accounts. The actual accounts are under ~/.mutt/accounts folder with GPG encryption in ASCII.

The original gmail file should only contain account related stuff, such as IMAP and SMTP configuration. At the core the login lines should be:

set imap_user = "[email protected]" 
set imap_authenticators="oauthbearer"
set imap_oauth_refresh_command="~/.mutt/oauth2.py --quiet [email protected] --client_id=2345...0123.apps.googleusercontent.com --client_secret=s_ec_ret --refresh_token=ReF/reShToken"
set smtp_authenticators="oauthbearer"
set smtp_oauth_refresh_command="~/.mutt/oauth2.py --quiet [email protected] --client_id=2345...0123.apps.googleusercontent.com --client_secret=s_ec_ret --refresh_token=ReF/reShToken"
set smtp_url = "smtp://[email protected]@smtp.gmail.com:587/"
set from = "[email protected]" 
set realname = "Your Name"
set signature = "~/.mutt/signatures/mysig"

# Basic config, you can leave this as is 
set folder = "imaps://imap.gmail.com"
set spoolfile = "+INBOX"
set imap_check_subscribed 
set postponed = "+[Gmail]/Draft"
set record = ""
set header_cache=~/.mutt/cache/headers

You should be able to use mutt to view/send emails via Gmail using OAuth 2.0!

Join the conversation

5 Comments

  1. Hi

    Thanks for the article but what about those GPG “asc” files? Can you elaborate a little bit on that or provide some resource? thanks.

  2. Hi, thanks for this neat guide you wrote. The access token I received is only valid for 3599 seconds; how do I get a permanent access token, so I could write it in the mutt config file without having to manually change the access token every time it expires?

    1. Sorry, I just noticed that you put the refresh token in the config file, not the access token itself. I take it, this is all that’s needed? If the access token expires, the same command will retrieve a new access token automatically?

Leave a comment

Leave a Reply to Luxing Huang Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.