diff --git a/src-ui/src/app/components/manage/mail/mail.component.html b/src-ui/src/app/components/manage/mail/mail.component.html
index a83b87355..bea79ae3c 100644
--- a/src-ui/src/app/components/manage/mail/mail.component.html
+++ b/src-ui/src/app/components/manage/mail/mail.component.html
@@ -13,7 +13,7 @@
Add Account
- Connect with Google
+ Connect with Google
diff --git a/src/documents/views.py b/src/documents/views.py
index a049d3bfd..02af9d5c3 100644
--- a/src/documents/views.py
+++ b/src/documents/views.py
@@ -1558,8 +1558,8 @@ class UiSettingsView(GenericAPIView):
def generate_google_oauth_url(self) -> str:
token_request_uri = "https://accounts.google.com/o/oauth2/auth"
response_type = "code"
- client_id = settings.GOOGLE_OAUTH_CLIENT_ID
- redirect_uri = "http://localhost:8000/api/oauth/google/callback/"
+ client_id = settings.GMAIL_OAUTH_CLIENT_ID
+ redirect_uri = "http://localhost:8000/api/oauth/callback/"
scope = "https://mail.google.com/"
access_type = "offline"
url = f"{token_request_uri}?response_type={response_type}&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&access_type={access_type}"
@@ -1595,7 +1595,7 @@ class UiSettingsView(GenericAPIView):
ui_settings["auditlog_enabled"] = settings.AUDIT_LOG_ENABLED
- if settings.GOOGLE_OAUTH_ENABLED:
+ if settings.GMAIL_OAUTH_ENABLED:
ui_settings["google_oauth_url"] = self.generate_google_oauth_url()
user_resp = {
@@ -2146,36 +2146,52 @@ class TrashView(ListModelMixin, PassUserMixin):
# Outlook https://stackoverflow.com/questions/73902642/office-365-imap-authentication-via-oauth2-and-python-msal-library
-class GoogleOauthCallbackView(GenericAPIView):
+class OauthCallbackView(GenericAPIView):
# permission_classes = (AllowAny,)
def get(self, request, format=None):
- # Guide: https://postmansmtp.com/how-to-configure-post-smtp-with-gmailgsuite-using-oauth/
- # http://localhost:4200/api/oauth/google/callback?code=4%2F0AQlEd8yxIwqjz95p82tWMq4ogn4KxRdprtjjGqjEHW4x7X1roEgswzn9EfiAit1cOLfSog&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&hd=michaelshamoon.com&prompt=consent
+ # Gmail setup guide: https://postmansmtp.com/how-to-configure-post-smtp-with-gmailgsuite-using-oauth/
+ # Outlok setup guide: https://medium.com/@manojkumardhakad/python-read-and-send-outlook-mail-using-oauth2-token-and-graph-api-53de606ecfa1
code = request.query_params.get("code")
- if code is None:
- return HttpResponseBadRequest("Code required")
+ scope = request.query_params.get("scope")
+ if code is None or scope is None:
+ logger.error(
+ f"Invalid oauth callback request, code: {code}, scope: {scope}",
+ )
+ return HttpResponseBadRequest("Invalid request, see logs for more detail")
+
+ if "google" in scope:
+ # Google
+ imap_server = "imap.gmail.com"
+ defaults = {
+ "name": f"Gmail {datetime.now()}",
+ "username": "",
+ "imap_security": MailAccount.ImapSecurity.SSL,
+ "imap_port": 993,
+ }
+
+ token_request_uri = "https://accounts.google.com/o/oauth2/token"
+ client_id = settings.GMAIL_OAUTH_CLIENT_ID
+ client_secret = settings.GMAIL_OAUTH_CLIENT_SECRET
+ redirect_uri = "http://localhost:8000/api/oauth/callback/"
+ grant_type = "authorization_code"
+ scope = "https://mail.google.com/"
+ data = {
+ "code": code,
+ "client_id": client_id,
+ "client_secret": client_secret,
+ "redirect_uri": redirect_uri,
+ "grant_type": grant_type,
+ "scope": scope,
+ }
+ headers = {
+ "Content-Type": "application/x-www-form-urlencoded",
+ }
+ response = httpx.post(token_request_uri, data=data, headers=headers)
+ data = response.json()
+ elif "outlook" in scope:
+ data = {}
- token_request_uri = "https://accounts.google.com/o/oauth2/token"
- client_id = settings.GOOGLE_OAUTH_CLIENT_ID
- client_secret = settings.GOOGLE_OAUTH_CLIENT_SECRET
- redirect_uri = "http://localhost:8000/api/oauth/google/callback/"
- grant_type = "authorization_code"
- scope = "https://mail.google.com/"
- url = f"{token_request_uri}"
- data = {
- "code": code,
- "client_id": client_id,
- "client_secret": client_secret,
- "redirect_uri": redirect_uri,
- "grant_type": grant_type,
- "scope": scope,
- }
- headers = {
- "Content-Type": "application/x-www-form-urlencoded",
- }
- response = httpx.post(url, data=data, headers=headers)
- data = response.json()
if "error" in data:
return HttpResponseBadRequest(data["error"])
elif "access_token" in data:
@@ -2186,13 +2202,8 @@ class GoogleOauthCallbackView(GenericAPIView):
account, _ = MailAccount.objects.update_or_create(
password=access_token,
is_token=True,
- imap_server="imap.gmail.com",
- defaults={
- "name": f"Gmail {datetime.now()}",
- "username": "",
- "imap_security": MailAccount.ImapSecurity.SSL,
- "imap_port": 993,
- },
+ imap_server=imap_server,
+ defaults=defaults,
)
return HttpResponseRedirect(
diff --git a/src/paperless/settings.py b/src/paperless/settings.py
index e5dd7ce8e..d190af335 100644
--- a/src/paperless/settings.py
+++ b/src/paperless/settings.py
@@ -1200,6 +1200,6 @@ EMPTY_TRASH_DELAY = max(__get_int("PAPERLESS_EMPTY_TRASH_DELAY", 30), 1)
###############################################################################
# Oauth Email Providers #
###############################################################################
-GOOGLE_OAUTH_CLIENT_ID = os.getenv("PAPERLESS_GOOGLE_OAUTH_CLIENT_ID")
-GOOGLE_OAUTH_CLIENT_SECRET = os.getenv("PAPERLESS_GOOGLE_OAUTH_CLIENT_SECRET")
-GOOGLE_OAUTH_ENABLED = bool(GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET)
+GMAIL_OAUTH_CLIENT_ID = os.getenv("PAPERLESS_GMAIL_OAUTH_CLIENT_ID")
+GMAIL_OAUTH_CLIENT_SECRET = os.getenv("PAPERLESS_GMAIL_OAUTH_CLIENT_SECRET")
+GMAIL_OAUTH_ENABLED = bool(GMAIL_OAUTH_CLIENT_ID and GMAIL_OAUTH_CLIENT_SECRET)
diff --git a/src/paperless/urls.py b/src/paperless/urls.py
index 13b5c0136..98f7fa983 100644
--- a/src/paperless/urls.py
+++ b/src/paperless/urls.py
@@ -22,9 +22,9 @@ from documents.views import CorrespondentViewSet
from documents.views import CustomFieldViewSet
from documents.views import DocumentTypeViewSet
from documents.views import GlobalSearchView
-from documents.views import GoogleOauthCallbackView
from documents.views import IndexView
from documents.views import LogViewSet
+from documents.views import OauthCallbackView
from documents.views import PostDocumentView
from documents.views import RemoteVersionView
from documents.views import SavedViewViewSet
@@ -167,9 +167,9 @@ urlpatterns = [
name="trash",
),
re_path(
- r"^oauth/google/callback/",
- GoogleOauthCallbackView.as_view(),
- name="google_oauth_callback",
+ r"^oauth/callback/",
+ OauthCallbackView.as_view(),
+ name="oauth_callback",
),
*api_router.urls,
],