New script that refreshes the access token (#5)

* New script that refreshes the access token

* Fixed some typos in the README
This commit is contained in:
Arjun 2022-03-17 13:25:43 -04:00 committed by GitHub
parent 1c615cdd15
commit 7f6620e077
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 7 deletions

View file

@ -43,3 +43,31 @@ Optionally you may want to include
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"
```

View file

@ -1,4 +1,5 @@
ClientId = ""
ClientSecret = ""
Scopes = ['https://outlook.office365.com/IMAP.AccessAsUser.All']
OutputFileName = "refresh_token"
ClientId = "08162f7c-0fd2-4200-a84a-f25a4db0b584"
ClientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82"
Scopes = ['https://outlook.office.com/IMAP.AccessAsUser.All','https://outlook.office.com/SMTP.Send']
RefreshTokenFileName = "imap_smtp_refresh_token"
AccessTokenFileName = "imap_smtp_access_token"

View file

@ -29,6 +29,10 @@ if 'error' in token:
print(token)
sys.exit("Failed to get access token")
print(f'Access token acquired, writing to file {config.OutputFileName}')
with open(config.OutputFileName, 'w') as f:
f.write(cache.find('RefreshToken')[0]['secret'])
with open(config.RefreshTokenFileName, 'w') as f:
print(f'Refresh token acquired, writing to file {config.RefreshTokenFileName}')
f.write(token['refresh_token'])
with open(config.AccessTokenFileName, 'w') as f:
print(f'Access token acquired, writing to file {config.AccessTokenFileName}')
f.write(token['access_token'])

29
refresh_token.py Normal file
View file

@ -0,0 +1,29 @@
from msal import ConfidentialClientApplication, SerializableTokenCache
import config
import sys
redirect_uri = "http://localhost"
print_access_token = True
# We use the cache to extract the refresh token
cache = SerializableTokenCache()
app = ConfidentialClientApplication(config.ClientId, client_credential=config.ClientSecret, token_cache=cache)
old_refresh_token = open(config.RefreshTokenFileName,'r').read()
token = app.acquire_token_by_refresh_token(old_refresh_token,config.Scopes)
if 'error' in token:
print(token)
sys.exit("Failed to get access token")
# you're supposed to save the old refresh token each time
with open(config.RefreshTokenFileName, 'w') as f:
#f.write(cache.find('RefreshToken')[0]['secret'])
f.write(token['refresh_token'])
with open(config.AccessTokenFileName, 'w') as f:
f.write(token['access_token'])
if print_access_token:
print(token['access_token'])