entry = _pending_oauth_states.pop(state, None) if not entry: raise HTTPException(400, "Invalid or expired OAuth state") user_id = entry["user_id"] # 2) resolve client config (latest imported by this user, else server default) cfg_row = (await db.execute( select(OAuthClientConfig) .where(OAuthClientConfig.user_id == user_id, OAuthClientConfig.is_active == True) # noqa .order_by(OAuthClientConfig.id.desc()))).scalars().first() client = gmail_service.resolve_client_config(cfg_row) # 3) exchange code for tokens (real HTTP call to Google) try: tokens = gmail_service.exchange_code_for_tokens(client, code) except gmail_service.GmailOauthError as e: return HTMLResponse(f"
{str(e)[:500]}")
# 4) identify the Gmail address that authorized
try:
userinfo = gmail_service.get_userinfo(tokens["access_token"])
gmail_email = userinfo.get("email", "").lower()
except Exception as e:
raise HTTPException(502, f"Could not fetch userinfo: {e}")
if not gmail_email:
raise HTTPException(502, "Google did not return an email address")
# 5) persist account + encrypted tokens
account = (await db.execute(select(GmailAccount)
.where(GmailAccount.user_id == user_id,
GmailAccount.email == gmail_email))).scalar_one_or_none()
from datetime import timedelta as _td
expires_at = datetime.now(timezone.utc) + _td(seconds=int(tokens.get("expires_in", 3600)))
if account:
account.status = "authorized"
account.sending_method = account.sending_method or "api"
account.token_expiry = expires_at
if account.oauth_token:
account.oauth_token.access_token = tokens["access_token"]
account.oauth_token.refresh_token = tokens.get("refresh_token") or account.oauth_token.refresh_token
account.oauth_token.expires_at = expires_at
account.oauth_token.granted_scopes = tokens.get("scope", "")
else:
account.oauth_token = OAuthToken(
access_token=tokens["access_token"],
refresh_token=tokens.get("refresh_token", ""),
scope=tokens.get("scope", ""),
expires_at=expires_at,
granted_scopes=tokens.get("scope", ""),
)
else:
account = GmailAccount(
user_id=user_id, email=gmail_email, display_name=userinfo.get("name", ""),
status="authorized", sending_method="api",
google_user_id=userinfo.get("sub", ""), token_expiry=expires_at,
oauth_config_id=cfg_row.id if cfg_row else None,
)
account.oauth_token = OAuthToken(
access_token=tokens["access_token"],
refresh_token=tokens.get("refresh_token", ""),
scope=tokens.get("scope", ""),
expires_at=expires_at,
granted_scopes=tokens.get("scope", ""),
)
db.add(account)
await db.commit()
await log_audit(db, user_id, "gmail.authorized", "gmail_account", account.id,
{"email": gmail_email}, request.client.host)
redirect = f"{settings.FRONTEND_BASE_URL}/gmail-accounts?connected={gmail_email}"
return RedirectResponse(redirect, status_code=303)