45:class GmailOauthError(Exception): 52:def resolve_client_config(config=None) -> dict: 81:def parse_client_json(content: bytes) -> dict: 103:def generate_state() -> str: 107:def build_authorization_url(client: dict, state: str) -> str: 121:def exchange_code_for_tokens(client: dict, code: str) -> dict: 139:def refresh_access_token(client: dict, refresh_token: str) -> dict: 152:def revoke_token(token: str) -> bool: 163:def get_userinfo(access_token: str) -> dict: 173:class GmailClient: 176: def __init__(self, account_email: str, access_token: str, refresh_token: str, 177: client_config: dict, sending_method: str = "api", token_expiry=None): 180: self.method = sending_method if sending_method in ("api", "smtp") else "api" 193: def _ensure_valid(self): 199: def _api(self): 208: def send_mime_api(self, mime_message) -> dict: 218: def send_mime_smtp(self, mime_message) -> dict: 235: def get_profile(self) -> dict: 241: def verify_connection(self) -> dict: 249:def build_gmail_client_from_account(account, oauth_token, client_config=None) -> GmailClient: 257: sending_method=account.sending_method, 262:def resolve_client_config_for_account(account) -> dict: --- 9:import logging 10:import random 11:import re as _re 12:import time 13:from datetime import date, datetime, timedelta, timezone 15:import googleapiclient.errors 16:import redis as redis_lib 17:from celery import Task 18:from sqlalchemy import select 20:from app.core.config import settings 21:from app.db.session import SyncSession 22:from app.models import (Attachment, Campaign, CampaignRecipient, EmailEvent, 25:from app.services import attachments_service, message_builder 26:from app.services.gmail_service import build_gmail_client_from_account 27:from app.services.variable_engine import GeneratedValues, VariableEngine 28:from app.worker.celery_app import celery_app 33: rdb = redis_lib.from_url(settings.REDIS_URL, socket_timeout=2)