In case there is someone else in my situation, needing to connect to an institutional outlook account with s-nail, here is a recipe that works for me on ubuntu 20.04 LTS:

On Sun, 4 Sep 2022, Steffen Nurpmeso steffen-at-sdaoden.eu |s-nail| wrote:

in the mutt(1) MUA repository there
is contrib/mutt_oauth2.py*, and it reads

 -- How to create a Microsoft registration --

 Go to portal.azure.com, log in with a Microsoft account (get a free
 one at outlook.com), then search for "app registration", and add a
 new registration. On the initial form that appears, put a name like
 "Mutt", allow any type of account, and put "http://localhost/"; as
 the redirect URI, then more carefully go through each
 screen:

 Branding
  - Leave fields blank or put in reasonable values
  - For official registration, verify your choice of publisher domain
 Authentication:
  - Platform "Mobile and desktop"
  - Redirect URI "http://localhost/";
  - Any kind of account
  - Enable public client (allow device code flow)
 API permissions:
  - Microsoft Graph, Delegated, "offline_access"
  - Microsoft Graph, Delegated, "IMAP.AccessAsUser.All"
  - Microsoft Graph, Delegated, "POP.AccessAsUser.All"
  - Microsoft Graph, Delegated, "SMTP.Send"
  - Microsoft Graph, Delegated, "User.Read"
 Overview:
  - Take note of the Application ID (a.k.a. Client ID), you'll need it shortly

 End users who aren't able to get to the app registration screen within
 portal.azure.com for their work/school account can temporarily use an
 incognito browser window to create a free outlook.com account and use that
 to create the app registration.

 Edit the client_id (and client_secret if there is one) into the
 mutt_oauth2.py script.

Do the above. When I did it, I got a client id, but no client secret. I put the client id between the '' quotes in the microsoft subsection of the registrations section of the mutt_oauth2.py script and left the client secret blank. I also filled in my own gpg id in the ENCRYPTION_PIPE line of the script.

[Note: mutt-oauth2.py requires a python installation sufficiently recent to accept the keyword argument "capture_output". Python3 3.8.2 on ubuntu 20.04 is ok. Python3 3.6.8-18 on Centos 7 is too old.

I have seen claims that you don't actually need get your own client id or secret and can just use the ones for Thunderbird that have been posted on the web, or, I suppose, the ones for Alpine that Steffen quoted in a recent message. I haven't tried though.]

Then a one-time run of

mutt_oauth2.py --authorize --verbose --test ~/.s-nail-tokenfile

invites you to log in to your organizational microsoft account and fill in various stuff, after which you have an encrypted refresh token in ~/.s-nail-tokenfile, as well as a lot of gibberish on your screen.

Put the lines below into your .mailrc. They are mostly copied from the s-nail man page or the sample fozzy-baer setup that Steffen posted in a message:

set tokenfile=~/.s-nail-tokenfile # or another location of your choice
set access_token_=0

define o-m-l-t {
    xcall update_access_token
}
define o-c-e {
    xcall update_access_token
}

set v15-compat=1

define update_access_token {
    local set x epoch_sec epoch_nsec
    vput vexpr x epoch
    eval set $x # set epoch_sec/_nsec of vexpr epoch
    vput vexpr i + $access_token_ 2100
    if $epoch_sec -ge $i
        eval "vput ! password mutt_oauth2.py --test $tokenfile 2>/dev/null"
        # need eval to get the value of "tokenfile" passed out to the shell
        vput csop password trim "$password"
        if -n "$verbose"
           echo password is <$password>
        endif
        set access_token_=$epoch_sec
    endif
}

account oauth {
    set inbox=imaps://yourname%[email protected]
    set folder=${inbox}
    set user=loginname@organization #the name you log in with on their website
    set from=emailname@organization # might be the same as user, or not
    set mta=submission://smtp.office365.com
    set smtp-use-starttls
    set smtp-auth=oauthbearer
    set imap-auth=oauthbearer
    set on-main-loop-tick=o-m-l-t on-compose-enter=o-c-e
}

[Note: This is minimal. You can add your own further preferences. Steffen's fozzi-baer script sets the boolean variables nosmtp-hostname and nonetrc-lookup and sets tls-config-pairs=MinProtocol=TLSv1.2, but I don't appear to need those. Setting user looks necessary for sending with smtp. Not setting it or setting it wrong gives an error message when you try to send, although you can read mail without it. Email can be different from login, e.g., user=joebloggs@organization, [email protected]. The @organization part probably has to be the same though.]

Now you can connect with

s-nail -X 'call update_access_token' -A oauth

The initial call to update_access_token uses the refresh token in your ~/.s-nail-tokenfile to get an access token that s-nail treats as a password for logging in. The settings of on-main-loop-tick and on-compose-enter are for fetching a new access token if the original one expires during your session, as explained in the man page.

Stephen Isard

Reply via email to