Imran's Blog
Stuff I feel like blogging about.


Microsoft, XOAUTH2, and mbsync

Posted on

I use neomutt (with mbsync) to access my email accounts. This involves setting up an app password which retrieves messages via IMAP. I have accounts across gmail, fastmail and microsoft email.

All was well until June 19th. Microsoft sent an email with the title "Action Needed – You may lose access to some of your third-party mail and calendar apps". The TL;DR of this email is that MS will remove app passwords in September and I will need to switch to an oauth sign in flow to keep using neomutt, but if I fail to do that I can still use outlook applications 🙄.

Getting the oauth flow was a bit of pain, so I'm documenting it here.

# Step 1 Get mutt_oauth2.py

(neo)mutt comes with this file. If your distribution does not include the file, you can grab it from the mutt git repository: https://gitlab.com/muttmua/mutt/-/blob/master/contrib/mutt_oauth2.py

I also modified this file to use pass instead of gpg.

# Step 2 Create an OAuth Application in Azure

Other blog posts on this subject (at least the ones that I could find with a search engine) recommended using Thunderbird's credentials. The current credentials in source control is missing a client_secret and the older credentials that are floating around on these posts do not work with my account type. They with school/work accounts (anything belonging to an organization) but not individual accounts.

During this process I changed the redirect_uri in the mutt script to http://localhost as that is what Thunderbird has.

The easiest way forward was to create my own oauth application in azure and use its credentials. Fair warning this involves giving microsoft your phone number, address, and credit card.

AFAICT there is no cost associated with this: https://learn.microsoft.com/en-us/answers/questions/1111512/application-registration-cost

I chose the "Pay as you go" on the azure sign up page. In the search bar, look for "App registration" and create a new application.

You will want to select the option that allows both organizational and personal accounts and because of the redirect_uri stuff I did, I set the app type to web with http://localhost as the redirect url.

You'll get your client_id as "Application (client) ID", "Certificates & secrets" will generate a client_secret. The next step will require both so make sure you note them down somewhere.

# Step 3 Run mutt_oauth2.py

Run the script with --authorize. In my case, it's ./mutt_oauth2.py <pass-name> --authorize

Follow the prompts, make sure you select localhostauthcode when asked (this is where the localhost redirect comes into play). It will print a url, visit in the browser and it will complete the token retrieval.

The script store the client_id, client_secret and access + refresh tokens in pass. ./mutt_oauth2.py <pass-name> will retrieve the access token, and also auto refresh if needed.

# Step 4 Update mbsync

First mbsync needs to know to use XOAUTH2. For arch install cyrus-sasl-xoauth2-git from AUR.

The important thing is the default value of AuthMechs is * which means mbsync will now attempt to use XOAUTH2 for every configured account. For the microsoft accounts set AuthMechs XOAUTH2 and for all others set it as AuthMechs PLAIN.

For the microsoft accounts change the PassCmd to /path/to/mutt_oauth2.py <pass-name>.

At this point you're done and can continue using mbsync like you were before. If you want to do this for gmail, the AuthMechs value will be OAUTHBEARER. For the OAuth application setup refer to the 1,000,001 tutorials online.