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)
