Spaces:
Sleeping
Sleeping
| # src/payslip/googleservice.py | |
| import base64 | |
| import json | |
| import requests | |
| from fastapi import HTTPException | |
| from src.core.config import settings | |
| # TEMPORARY in-memory store | |
| GOOGLE_TOKENS = {} # user_id -> refresh_token | |
| def exchange_code_for_tokens(code: str): | |
| """Exchange authorization code for access + refresh tokens.""" | |
| data = { | |
| "client_id": settings.GOOGLE_CLIENT_ID, | |
| "client_secret": settings.GOOGLE_CLIENT_SECRET, | |
| "code": code, | |
| "grant_type": "authorization_code", | |
| "redirect_uri": settings.GOOGLE_REDIRECT_URI, | |
| } | |
| response = requests.post(settings.TOKEN_URL, data=data) | |
| return response.json() | |
| def extract_email_from_id_token(id_token: str) -> str: | |
| """Decode ID token to extract the email Google selected.""" | |
| try: | |
| payload_part = id_token.split(".")[1] + "===" | |
| decoded = json.loads(base64.urlsafe_b64decode(payload_part)) | |
| return decoded.get("email") | |
| except Exception: | |
| raise HTTPException(400, "Invalid ID token format") | |
| def refresh_google_access_token(refresh_token: str): | |
| """Refresh access token using refresh_token.""" | |
| data = { | |
| "client_id": settings.GOOGLE_CLIENT_ID, | |
| "client_secret": settings.GOOGLE_CLIENT_SECRET, | |
| "refresh_token": refresh_token, | |
| "grant_type": "refresh_token", | |
| } | |
| response = requests.post(settings.TOKEN_URL, data=data) | |
| token_data = response.json() | |
| if "access_token" not in token_data: | |
| raise HTTPException(400, f"Google refresh failed: {token_data}") | |
| return token_data["access_token"] | |
| def build_email(from_email: str, to_email: str, subject: str, body: str): | |
| """Build raw Gmail MIME email.""" | |
| message = ( | |
| f"From: {from_email}\r\n" | |
| f"To: {to_email}\r\n" | |
| f"Subject: {subject}\r\n\r\n" | |
| f"{body}" | |
| ) | |
| return base64.urlsafe_b64encode(message.encode("utf-8")).decode("utf-8") | |
| def send_gmail(access_token: str, raw_message: str): | |
| """Send email through Gmail API.""" | |
| url = "https://gmail.googleapis.com/gmail/v1/users/me/messages/send" | |
| headers = { | |
| "Authorization": f"Bearer {access_token}", | |
| "Content-Type": "application/json", | |
| } | |
| data = {"raw": raw_message} | |
| res = requests.post(url, headers=headers, json=data) | |
| data = res.json() | |
| if "id" not in data: | |
| raise HTTPException(400, f"Gmail send error: {data}") | |
| return data["id"] | |