mirror of
https://github.com/vale981/outlook-oauth-hack
synced 2025-03-04 08:31:38 -05:00
update readme to reflect new state
This commit is contained in:
parent
f5a0af281f
commit
a5558a7a52
2 changed files with 41 additions and 67 deletions
106
README.md
106
README.md
|
@ -1,73 +1,45 @@
|
||||||
# Using OfflineIMAP with M365
|
# Hiro's Home-Manager Outlook Oauth Hack
|
||||||
|
|
||||||
This instruction describes how [OfflineIMAP](https://www.offlineimap.org/) can be used with an IMAP-enabled Exchange Online (M365) environment using OAuth2, see the [OfflineIMAP config documentation](https://github.com/OfflineIMAP/offlineimap/blob/master/offlineimap.conf#L897). Note that the Microsoft 365 instance (the [tenant](https://learn.microsoft.com/en-us/microsoft-365/solutions/tenant-management-overview?view=o365-worldwide)) must be configured to support IMAP over 'modern authentication' and that it requires app consent to be granted for a mail app for which you have the client ID and secret.
|
This is a generalization and adaptation of the fork of
|
||||||
|
[UvA-FNWI](https://github.com/UvA-FNWI/M365-IMAP) to get oauth imap
|
||||||
|
working on my machine with the McGill email server. I've added
|
||||||
|
multi-configuration and encryption support. Furthermore token
|
||||||
|
expiration is now being taken into account. *This has been hacked
|
||||||
|
together in an afternoon and works for me. No guarantees provided :).*
|
||||||
|
|
||||||
A variation of the below should work with any OAuth-enabled mail client or script.
|
The tool is configured by `~/.o365-auth-config.toml` (see
|
||||||
|
`config.toml`) in this repo. The `[security]` section has only one
|
||||||
|
setting, namely the `PasswordPath` which can point to an optional
|
||||||
|
password file which is then used to decrypt the stored `refresh` and
|
||||||
|
`access` tokens. The expectation is, that a tool like
|
||||||
|
[agenix](https://github.com/ryantm/agenix) provides this file while
|
||||||
|
the computer is running.
|
||||||
|
|
||||||
## Step 1: get a client ID/secret
|
The `[default]` section contains the OAuth `ClientId`, the
|
||||||
In order to connect to Azure AD for authentication, you need a client ID and secret (an "app registration" in AAD). Confusingly, the client secret doesn't actually need to be a secret (a client app like a mail client can't keep secrets, after all). You can your own app registration, or use an existing one such as Thunderbird's, which is [publicly available](https://hg.mozilla.org/comm-central/file/tip/mailnews/base/src/OAuth2Providers.jsm) (see the `login.microsoft.com` section). Whatever client ID you use, it will need to have been granted the `IMAP.AccessAsUser.All` permission in your M365 tenant.
|
`ClientSecret` and the `Scopes`. I really don't have a clear idea what
|
||||||
|
those mean, but the values provided by default are taken from
|
||||||
|
Thunderbird. For a better explanation see [the work this is based
|
||||||
|
on](https://github.com/UvA-FNWI/M365-IMAP).
|
||||||
|
|
||||||
## Step 2: get a token
|
For each account one wishes to set up on can optionally add a section
|
||||||
Since OfflineIMAP doesn't support an interactive flow for getting a token, you need to do this step yourself. You can use `get_token.py` for this purpose, which uses Microsoft's [MSAL](https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-overview) wrapper library to perform the OAuth2 flow:
|
`[<account name>]` which can override the above values.
|
||||||
|
|
||||||
```sh
|
The script `get_token.py` (accessible as `o365-get-token` if the
|
||||||
git clone https://github.com/UvA-FNWI/M365-IMAP
|
home-manager module is enabled) takes an argument `<account name>` and
|
||||||
cd M365-IMAP
|
launches the authentication flow. Once this has been done, the script
|
||||||
pip install msal
|
`refresh_token.py` (accessible as `o365-refresh-token`) can be called
|
||||||
# add the client ID and secret from step 1 to config.py
|
with the same argument to obtain the currently valid `access key`. It
|
||||||
python3 get_token.py
|
automatically refreshes said key upon its expiration. The `access key`
|
||||||
|
is printed to `stdout` and may be fed into `mbsync` or `msmtp`.
|
||||||
|
|
||||||
|
The flake provides a package which makes the above commands
|
||||||
|
available. It also provides a very basic and ugly home-manager module
|
||||||
|
that allows you to configure those scripts using, who'd have thought
|
||||||
|
it, home-manager.
|
||||||
|
|
||||||
|
Simply a add the `o365-auth.homeManagerModules.default` to your home-manager modules an
|
||||||
|
```nix
|
||||||
|
programs.o365-auth.enable = true;
|
||||||
|
programs.o365-auth.passwordPath = config.age.secrets.mail_token_storage_pw.path;
|
||||||
```
|
```
|
||||||
|
should get you started.
|
||||||
Follow the instructions to obtain a `refresh_token` file containing an AAD refresh token. Note that the token allows access to your full mailbox (in combination with the client 'secret') and hence should be stored securely.
|
|
||||||
|
|
||||||
## Step 3: configure OfflineIMAP
|
|
||||||
Edit your `.offlineimaprc` file so that your remote repository section looks like this:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[Repository Remote]
|
|
||||||
type = IMAP
|
|
||||||
sslcacertfile = <path to CA certificates>
|
|
||||||
remotehost = outlook.office365.com
|
|
||||||
remoteuser = <your M365 email address>
|
|
||||||
auth_mechanisms = XOAUTH2
|
|
||||||
oauth2_request_url = https://login.microsoftonline.com/common/oauth2/v2.0/token
|
|
||||||
oauth2_client_id = <the client ID from step 1>
|
|
||||||
oauth2_client_secret = <the client secret from step 1>
|
|
||||||
oauth2_refresh_token = <the contents of the refresh_token file from step 2>
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: in practice you should store your token in some type of secure key store.
|
|
||||||
|
|
||||||
Optionally you may want to include
|
|
||||||
```ini
|
|
||||||
folderfilter = lambda folder: not folder.startswith('Calendar') and not folder.startswith('Contacts')
|
|
||||||
```
|
|
||||||
to filter out folders containing non-mail items.
|
|
||||||
|
|
||||||
# Sending Mail
|
|
||||||
|
|
||||||
Sending mail with a program like msmtp using SMTP requires an access token. The
|
|
||||||
access token has a short life and has to be refreshed periodically using the
|
|
||||||
refresh token.
|
|
||||||
|
|
||||||
`refresh_token.py` takes the refresh token stored in the file named in
|
|
||||||
config.RefreshTokenFileName and uses the MSAL library to request a new access
|
|
||||||
token. The new access token comes with a new refresh token and this is stored
|
|
||||||
in config.RefreshTokenFileName as well.
|
|
||||||
|
|
||||||
Optionally, `refresh_token.py` also prints the access token, so it can easily
|
|
||||||
be used in password scripts that work with your sendmail program. For example,
|
|
||||||
the sendmail configuration in msmtprc would read:
|
|
||||||
|
|
||||||
```
|
|
||||||
account myaccount
|
|
||||||
host smtp.office365.com
|
|
||||||
port 587
|
|
||||||
auth xoauth2
|
|
||||||
tls on
|
|
||||||
tls_starttls on
|
|
||||||
from <user@domain>
|
|
||||||
user <user@domain>
|
|
||||||
passwordeval "cd /usr/local/src/M365-IMAP/; python3 refresh_token.py"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,6 @@ ClientId = "08162f7c-0fd2-4200-a84a-f25a4db0b584"
|
||||||
ClientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82"
|
ClientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82"
|
||||||
Scopes = ['https://outlook.office.com/IMAP.AccessAsUser.All','https://outlook.office.com/SMTP.Send']
|
Scopes = ['https://outlook.office.com/IMAP.AccessAsUser.All','https://outlook.office.com/SMTP.Send']
|
||||||
Authority = false
|
Authority = false
|
||||||
|
|
||||||
|
[security]
|
||||||
PasswordPath = false
|
PasswordPath = false
|
||||||
|
|
Loading…
Add table
Reference in a new issue