imapfilter icon indicating copy to clipboard operation
imapfilter copied to clipboard

oauth with Office365 IMAP

Open tex443 opened this issue 3 years ago • 5 comments

Hi. Is there an example / guide how to access Office365 with IMAP an oauth? In the last version the oauth example is removed from extend.lua, so I think the workflow has changed?

Regards, Tex

tex443 avatar Aug 15 '22 08:08 tex443

Well, the support is still there in the config file, so in theory if you can get the correct string and supply it to imapfilter you should be able to authenticate.

But the example was out of date as the too oauth2.py script would not work with the latest versions of Python that most systems have nowadays, and this is the reason it was removed.

lefcha avatar Aug 17 '22 15:08 lefcha

With colleagues here (we use Exchange on campus) I also had these issues. We found that mutt's oauth tool in https://gitlab.com/muttmua/mutt/-/blob/master/contrib/mutt_oauth2.py can be used more easily by adding the clientid and clientsecret and user name (email) as needed. In particular you can also use eg Thunderbird's client secret if you do not want to go through the hassle of registering an app with Azure. See eg what the University of Glasgow documents: http://www.dcs.gla.ac.uk/~jacobd/posts/2022/03/configure-mutt-to-work-with-oauth-20/

A bit a lua /shell coding is required to put the returned string into something imapfitler can handle. Shell (known to work):

#!/bin/bash

( echo -ne 'user=your-email-address\01auth=Bearer '
 mutt_oauth2.py ~/.ssh/your-token-storage.token | tr -d '\n'
 echo -ne '\01\01'
) | base64 -w0

and lua (not tested yet...)


function FullGetMSImapToken(user)
 local status, ms_oauth_token = pipe_from('mutt_oauth2.py $HOME/.ssh/' .. user .. '.token')
 if (status ~= 0) then
   return nil
 end
 local sep = string.char(1)
 local data = 'user=' .. user .. sep .. 'auth=Bearer ' .. ms_oauth_token:gsub("\n$", "") .. string.rep(sep,2)
 local data64 = enc64(data)
 return data64
end

Mostly due to @andylytical (many thanks).

Note that this will all fail when the token expires since refreshing the token does not work in imapfilter right now.

There's a couple of C use-after-free bugs (I'll get to file a bug report and pull request soon I hope), but more fundamentally no way for the C code to call back to lua code to refresh the token.

rhaas80 avatar Aug 17 '22 19:08 rhaas80

and lua (not tested yet...)

function FullGetMSImapToken(user)
 local status, ms_oauth_token = pipe_from('mutt_oauth2.py $HOME/.ssh/' .. user .. '.token')
 if (status ~= 0) then
   return nil
 end
 local sep = string.char(1)
 local data = 'user=' .. user .. sep .. 'auth=Bearer ' .. ms_oauth_token:gsub("\n$", "") .. string.rep(sep,2)
 local data64 = enc64(data)
 return data64
end

The lua code works, if enc64 function is added:

local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -- You will need this for encoding/decoding
-- encoding
function enc64(data)
    return ((data:gsub('.', function(x)
        local r,b='',x:byte()
        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
        return r;
    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
        if (#x < 6) then return '' end
        local c=0
        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
        return b:sub(c+1,c+1)
    end)..({ '', '==', '=' })[#data%3+1])
end

And the path in local status, ms_oauth_token = pipe_from('mutt_oauth2.py $HOME/.ssh/' .. user .. '.token') has to match your local setup. for me it is './mutt_oauth2.py ./' .. user .. '.tokens'. For details about the mutt_oauth2.py usage see samples/mutt_oauth2.py.README.bz2.

lmoellendorf avatar Oct 01 '22 10:10 lmoellendorf

Thanks for verifying! Yup, I forgot the enc64 function. Looking at my own files I used the one in the mime Lua module (part of Debian's lua-socket package):

local mime = require("mime")
local dec64 = mime.decode("base64")
local enc64 = mime.encode("base64")

which may (no need to write code) or may not (more external dependencies) be more convenient.

rhaas80 avatar Oct 04 '22 01:10 rhaas80

Hi all,

Another option to use imapfilter with outlook/oauth2 is the email-ouath2-proxy (https://github.com/simonrob/email-oauth2-proxy.git). One nice side effect of it, is that you can put whatever you like in password configuration since the "real" auth will be done in the proxy.

clyra avatar May 01 '23 19:05 clyra