241: def verify_connection(self) -> dict: 242- try: 243- prof = self.get_profile() 244- return {"ok": True, "email_address": prof.get("email_address"), "detail": "Gmail API connection verified."} 245- except Exception as e: 246- return {"ok": False, "detail": str(e)[:400]} 247- 248- 249:def build_gmail_client_from_account(account, oauth_token, client_config=None) -> GmailClient: 250- """Build a GmailClient from DB rows (sync session context - worker uses sync ORM).""" 251- cfg = client_config or resolve_client_config_for_account(account) 252- return GmailClient( 253- account_email=account.email, 254- access_token=oauth_token.access_token, # decrypted 255- refresh_token=oauth_token.refresh_token, # decrypted 256- client_config=cfg, 257- sending_method=account.sending_method, 258- token_expiry=oauth_token.expires_at, 259- ) 260- 261- 262-def resolve_client_config_for_account(account) -> dict: 263- """Resolve client config for an account: its imported config row or server default.""" 264- # Called from sync or async context; imports DB lazily. 265- from app.db.session import SyncSession 266- from app.models import OAuthClientConfig 267- if account.oauth_config_id: 268- with SyncSession() as s: 269- cfg = s.get(OAuthClientConfig, account.oauth_config_id) 270- if cfg and cfg.is_active: 271- return {"client_id": cfg.client_id, "client_secret": cfg.client_secret, 272- "redirect_uri": cfg.redirect_uri or f"{settings.BASE_URL}/auth/google/callback"} 273- return resolve_client_config(None)