Michael Shriver Senior Computer Specialist - College of the Environment

Configuring mutt (neomutt) for IMAP/SMTP access to O365 Exchange

Office 365 Exchange requires XOauth2 tokens to authenticate via IMAP and SMTP. Mutt/Neomutt can use this form of authentication with the mutt_oauth2.py script

Pre-requisites:

Steps:

The instructions in the mutt_oauth2.py.README have a pretty complete listing of steps, but they do need to be tweaked a little for access to UW’s Exchange system.

Create an Entra ID Application

  1. Log into Microsoft Entra ID (Sometimes called Azure AD in tutorials)
  2. Click ‘App Registrations’ from the left menu
  3. Click ‘New Registration’ and give your app a descriptibe name like ’neomutt.’ Leave the ‘Supported account types’ at it’s default. Under Redirect URI, select ‘Public client/native (mobile & desktop)’ and enter “http://localhost/” for the URI path.
  4. Click ‘Register’
  5. On your new App’s overview page, take note down the ‘Application (client) ID’
  6. Click ‘API Permissions’
  7. Click ‘Add a permission,’ Select the large ‘Microsoft Graph’ option, the click ‘Delegated permissions.’ Search and add the following permissions:

Modify the mutt_oauth2.py script

The script by default uses the /common/ Microsoft Entra endpoint. It will need to be edited slightly to point the UW endpoints

Change the following lines:

    'microsoft': {
        'authorize_endpoint': 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
        'devicecode_endpoint': 'https://login.microsoftonline.com/common/oauth2/v2.0/devicecode',
        'token_endpoint': 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
        'redirect_uri': 'https://login.microsoftonline.com/common/oauth2/nativeclient',
        'tenant': 'common',

To read as follows:

    'microsoft': {
        'authorize_endpoint': 'https://login.microsoftonline.com/uw.edu/oauth2/v2.0/authorize',
        'devicecode_endpoint': 'https://login.microsoftonline.com/uw.edu/oauth2/v2.0/devicecode',
        'token_endpoint': 'https://login.microsoftonline.com/uw.edu/oauth2/v2.0/token',
        'redirect_uri': 'http://localhost/',
        'tenant': 'uw.edu',

Note: for each of the first three URLs and the ’tenant’ entry, ‘common’ was replaced with ‘uw.edu’ Additionally, the ‘redirect_uri’ was changed to match the URI we entered when we created our Entra App: https://localhost/

Registering your auth tokens with the mutt_oauth2.py script

Manually run the following command:

    ./mutt_oauth2.py --authorize --provider microsoft --authflow authcode --email <your@uw.email> --client-id <your-application-client-id> <your@uw.email>.tokens

The script should spit out a long URL, click the link, or open that URL in your web browser. At this point you will be prompted to log in with your UW Microsoft account. Additionally you will recieve a prompt to allow this app to view your account and send/recieve email. Click Approve.

If this step is successful, your browser will redirect to a http://localhost/ URL that will give you an error. This is ok, the information you need is included in that URL. From the browser address bar copy everything between ‘code=’ and ‘$state…’ Paste that string into the script window where it should be waiting patiently for a code. You should also be able to use one of the other auth flows, there is more information in the README.

The script will authenticate and spit out a long string. You can ignore that. To validate that everything went smoothly, run:

    ./mutt_oauth2.py --verbose --test <your@uw.email>.tokens

You should see messages that authentication succeeded for each mail protocol

Updating muttrc

Update your muttrc/neomuttrc with the following information:

set imap_user="<your@uw.email>"
set folder="imap://outlook.office365.com/"
set smtp_url="smtp://${imap_user}@smtp.office365.com:587/"
set imap_authenticators="oauthbearer:xoauth2"
set imap_oauth_refresh_command="/path/to/mutt_oauth2.py <your@uw.email>.tokens"
set smtp_authenticators=${imap_authenticators}
set smtp_oauth_refresh_command=${imap_oauth_refresh_command}

References