Microsoft you are the worst
This commit is contained in:
parent
1610bab0d8
commit
1c58e15783
@ -13,7 +13,8 @@
|
|||||||
<button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editMailAccount()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.MailAccount }">
|
<button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editMailAccount()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.MailAccount }">
|
||||||
<i-bs name="plus-circle"></i-bs> <ng-container i18n>Add Account</ng-container>
|
<i-bs name="plus-circle"></i-bs> <ng-container i18n>Add Account</ng-container>
|
||||||
</button>
|
</button>
|
||||||
<a class="btn btn-sm btn-outline-primary ms-2" [href]="googleOAuthUrl" i18n>Connect with Google</a>
|
<a class="btn btn-sm btn-outline-primary ms-2" [href]="gmailOAuthUrl" i18n>Connect with Gmail</a>
|
||||||
|
<a class="btn btn-sm btn-outline-primary ms-2" [href]="outlookOAuthUrl" i18n>Connect with Outlook</a>
|
||||||
</h4>
|
</h4>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
|
@ -37,10 +37,14 @@ export class MailComponent
|
|||||||
unsubscribeNotifier: Subject<any> = new Subject()
|
unsubscribeNotifier: Subject<any> = new Subject()
|
||||||
oAuthAccoundId: number
|
oAuthAccoundId: number
|
||||||
|
|
||||||
public get googleOAuthUrl(): string {
|
public get gmailOAuthUrl(): string {
|
||||||
return this.settingsService.get(SETTINGS_KEYS.GOOGLE_OAUTH_URL)
|
return this.settingsService.get(SETTINGS_KEYS.GOOGLE_OAUTH_URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get outlookOAuthUrl(): string {
|
||||||
|
return this.settingsService.get(SETTINGS_KEYS.OUTLOOK_OAUTH_URL)
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public mailAccountService: MailAccountService,
|
public mailAccountService: MailAccountService,
|
||||||
public mailRuleService: MailRuleService,
|
public mailRuleService: MailRuleService,
|
||||||
|
@ -65,6 +65,7 @@ export const SETTINGS_KEYS = {
|
|||||||
SEARCH_FULL_TYPE: 'general-settings:search:more-link',
|
SEARCH_FULL_TYPE: 'general-settings:search:more-link',
|
||||||
EMPTY_TRASH_DELAY: 'trash_delay',
|
EMPTY_TRASH_DELAY: 'trash_delay',
|
||||||
GOOGLE_OAUTH_URL: 'google_oauth_url',
|
GOOGLE_OAUTH_URL: 'google_oauth_url',
|
||||||
|
OUTLOOK_OAUTH_URL: 'outlook_oauth_url',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SETTINGS: UiSetting[] = [
|
export const SETTINGS: UiSetting[] = [
|
||||||
@ -248,4 +249,9 @@ export const SETTINGS: UiSetting[] = [
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: SETTINGS_KEYS.OUTLOOK_OAUTH_URL,
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
@ -1555,7 +1555,7 @@ class UiSettingsView(GenericAPIView):
|
|||||||
permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
|
permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
|
||||||
serializer_class = UiSettingsViewSerializer
|
serializer_class = UiSettingsViewSerializer
|
||||||
|
|
||||||
def generate_google_oauth_url(self) -> str:
|
def generate_gmail_oauth_url(self) -> str:
|
||||||
token_request_uri = "https://accounts.google.com/o/oauth2/auth"
|
token_request_uri = "https://accounts.google.com/o/oauth2/auth"
|
||||||
response_type = "code"
|
response_type = "code"
|
||||||
client_id = settings.GMAIL_OAUTH_CLIENT_ID
|
client_id = settings.GMAIL_OAUTH_CLIENT_ID
|
||||||
@ -1565,6 +1565,16 @@ class UiSettingsView(GenericAPIView):
|
|||||||
url = f"{token_request_uri}?response_type={response_type}&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&access_type={access_type}"
|
url = f"{token_request_uri}?response_type={response_type}&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&access_type={access_type}"
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
def generate_outlook_oauth_url(self) -> str:
|
||||||
|
# https://login.microsoftonline.com/common/oauth2/v2.0/authorize ?
|
||||||
|
token_request_uri = f"https://login.microsoftonline.com/{settings.OUTLOOK_OAUTH_TENANT_ID}/oauth2/v2.0/authorize"
|
||||||
|
response_type = "code"
|
||||||
|
client_id = settings.OUTLOOK_OAUTH_CLIENT_ID
|
||||||
|
redirect_uri = "http://localhost:8000/api/oauth/callback/"
|
||||||
|
scope = "offline_access%20Mail.ReadWrite"
|
||||||
|
url = f"{token_request_uri}?response_type={response_type}&response_mode=query&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}"
|
||||||
|
return url
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
serializer = self.get_serializer(data=request.data)
|
serializer = self.get_serializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
@ -1596,7 +1606,10 @@ class UiSettingsView(GenericAPIView):
|
|||||||
ui_settings["auditlog_enabled"] = settings.AUDIT_LOG_ENABLED
|
ui_settings["auditlog_enabled"] = settings.AUDIT_LOG_ENABLED
|
||||||
|
|
||||||
if settings.GMAIL_OAUTH_ENABLED:
|
if settings.GMAIL_OAUTH_ENABLED:
|
||||||
ui_settings["google_oauth_url"] = self.generate_google_oauth_url()
|
ui_settings["google_oauth_url"] = self.generate_gmail_oauth_url()
|
||||||
|
|
||||||
|
if settings.OUTLOOK_OAUTH_ENABLED:
|
||||||
|
ui_settings["outlook_oauth_url"] = self.generate_outlook_oauth_url()
|
||||||
|
|
||||||
user_resp = {
|
user_resp = {
|
||||||
"id": user.id,
|
"id": user.id,
|
||||||
@ -2150,18 +2163,27 @@ class OauthCallbackView(GenericAPIView):
|
|||||||
# permission_classes = (AllowAny,)
|
# permission_classes = (AllowAny,)
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
# Gmail setup guide: https://postmansmtp.com/how-to-configure-post-smtp-with-gmailgsuite-using-oauth/
|
# https://login.microsoftonline.com/<tenant-id>/adminconsent?client_id=<client-id> needed?
|
||||||
# Outlok setup guide: https://medium.com/@manojkumardhakad/python-read-and-send-outlook-mail-using-oauth2-token-and-graph-api-53de606ecfa1
|
admin_consent = request.query_params.get("admin_consent")
|
||||||
|
if admin_consent is not None:
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
"http://localhost:4200/mail",
|
||||||
|
)
|
||||||
code = request.query_params.get("code")
|
code = request.query_params.get("code")
|
||||||
|
# Gmail passes scope as a query param
|
||||||
scope = request.query_params.get("scope")
|
scope = request.query_params.get("scope")
|
||||||
if code is None or scope is None:
|
# Outlook passes session_state as a query param
|
||||||
|
session_state = request.query_params.get("session_state")
|
||||||
|
|
||||||
|
if code is None and scope is None and session_state is None:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"Invalid oauth callback request, code: {code}, scope: {scope}",
|
f"Invalid oauth callback request, code: {code}, scope: {scope}, session_state: {session_state}",
|
||||||
)
|
)
|
||||||
return HttpResponseBadRequest("Invalid request, see logs for more detail")
|
return HttpResponseBadRequest("Invalid request, see logs for more detail")
|
||||||
|
|
||||||
if "google" in scope:
|
if scope is not None and "google" in scope:
|
||||||
# Google
|
# Google
|
||||||
|
# Gmail setup guide: https://postmansmtp.com/how-to-configure-post-smtp-with-gmailgsuite-using-oauth/
|
||||||
imap_server = "imap.gmail.com"
|
imap_server = "imap.gmail.com"
|
||||||
defaults = {
|
defaults = {
|
||||||
"name": f"Gmail {datetime.now()}",
|
"name": f"Gmail {datetime.now()}",
|
||||||
@ -2173,26 +2195,40 @@ class OauthCallbackView(GenericAPIView):
|
|||||||
token_request_uri = "https://accounts.google.com/o/oauth2/token"
|
token_request_uri = "https://accounts.google.com/o/oauth2/token"
|
||||||
client_id = settings.GMAIL_OAUTH_CLIENT_ID
|
client_id = settings.GMAIL_OAUTH_CLIENT_ID
|
||||||
client_secret = settings.GMAIL_OAUTH_CLIENT_SECRET
|
client_secret = settings.GMAIL_OAUTH_CLIENT_SECRET
|
||||||
redirect_uri = "http://localhost:8000/api/oauth/callback/"
|
|
||||||
grant_type = "authorization_code"
|
|
||||||
scope = "https://mail.google.com/"
|
scope = "https://mail.google.com/"
|
||||||
|
elif session_state is not None:
|
||||||
|
# Outlook
|
||||||
|
# Outlok setup guide: https://medium.com/@manojkumardhakad/python-read-and-send-outlook-mail-using-oauth2-token-and-graph-api-53de606ecfa1
|
||||||
|
imap_server = "outlook.office365.com"
|
||||||
|
defaults = {
|
||||||
|
"name": f"Outlook {datetime.now()}",
|
||||||
|
"username": "",
|
||||||
|
"imap_security": MailAccount.ImapSecurity.SSL,
|
||||||
|
"imap_port": 993,
|
||||||
|
}
|
||||||
|
|
||||||
|
token_request_uri = f"https://login.microsoftonline.com/{settings.OUTLOOK_OAUTH_TENANT_ID}/oauth2/v2.0/token"
|
||||||
|
client_id = settings.OUTLOOK_OAUTH_CLIENT_ID
|
||||||
|
client_secret = settings.OUTLOOK_OAUTH_CLIENT_SECRET
|
||||||
|
scope = "offline_access%20Mail.ReadWrite"
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"code": code,
|
"code": code,
|
||||||
"client_id": client_id,
|
"client_id": client_id,
|
||||||
"client_secret": client_secret,
|
"client_secret": client_secret,
|
||||||
"redirect_uri": redirect_uri,
|
|
||||||
"grant_type": grant_type,
|
|
||||||
"scope": scope,
|
"scope": scope,
|
||||||
|
"redirect_uri": "http://localhost:8000/api/oauth/callback/",
|
||||||
|
"grant_type": "authorization_code",
|
||||||
}
|
}
|
||||||
headers = {
|
headers = {
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
}
|
}
|
||||||
response = httpx.post(token_request_uri, data=data, headers=headers)
|
response = httpx.post(token_request_uri, data=data, headers=headers)
|
||||||
data = response.json()
|
data = response.json()
|
||||||
elif "outlook" in scope:
|
logger.debug(data)
|
||||||
data = {}
|
|
||||||
|
|
||||||
if "error" in data:
|
if "error" in data:
|
||||||
|
logger.error(f"Error {response.status_code} getting access token: {data}")
|
||||||
return HttpResponseBadRequest(data["error"])
|
return HttpResponseBadRequest(data["error"])
|
||||||
elif "access_token" in data:
|
elif "access_token" in data:
|
||||||
access_token = data["access_token"]
|
access_token = data["access_token"]
|
||||||
|
@ -1203,3 +1203,9 @@ EMPTY_TRASH_DELAY = max(__get_int("PAPERLESS_EMPTY_TRASH_DELAY", 30), 1)
|
|||||||
GMAIL_OAUTH_CLIENT_ID = os.getenv("PAPERLESS_GMAIL_OAUTH_CLIENT_ID")
|
GMAIL_OAUTH_CLIENT_ID = os.getenv("PAPERLESS_GMAIL_OAUTH_CLIENT_ID")
|
||||||
GMAIL_OAUTH_CLIENT_SECRET = os.getenv("PAPERLESS_GMAIL_OAUTH_CLIENT_SECRET")
|
GMAIL_OAUTH_CLIENT_SECRET = os.getenv("PAPERLESS_GMAIL_OAUTH_CLIENT_SECRET")
|
||||||
GMAIL_OAUTH_ENABLED = bool(GMAIL_OAUTH_CLIENT_ID and GMAIL_OAUTH_CLIENT_SECRET)
|
GMAIL_OAUTH_ENABLED = bool(GMAIL_OAUTH_CLIENT_ID and GMAIL_OAUTH_CLIENT_SECRET)
|
||||||
|
OUTLOOK_OAUTH_TENANT_ID = os.getenv("PAPERLESS_OUTLOOK_OAUTH_TENANT_ID")
|
||||||
|
OUTLOOK_OAUTH_CLIENT_ID = os.getenv("PAPERLESS_OUTLOOK_OAUTH_CLIENT_ID")
|
||||||
|
OUTLOOK_OAUTH_CLIENT_SECRET = os.getenv("PAPERLESS_OUTLOOK_OAUTH_CLIENT_SECRET")
|
||||||
|
OUTLOOK_OAUTH_ENABLED = bool(
|
||||||
|
OUTLOOK_OAUTH_TENANT_ID and OUTLOOK_OAUTH_CLIENT_ID and OUTLOOK_OAUTH_CLIENT_SECRET,
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user