from typing import Iterator, Dict, Any from googleapiclient.discovery import build from googleapiclient.errors import HttpError from mail_intake.adapters.base import MailIntakeAdapter from mail_intake.exceptions import MailIntakeAdapterError from mail_intake.auth.base import MailIntakeAuthProvider class MailIntakeGmailAdapter(MailIntakeAdapter): """ Gmail read-only adapter. This class is the ONLY place where: - googleapiclient is imported - Gmail REST semantics are known - .execute() is called It must remain thin and dumb by design. """ def __init__( self, auth_provider: MailIntakeAuthProvider, user_id: str = "me", ): self._auth_provider = auth_provider self._user_id = user_id self._service = None @property def service(self): if self._service is None: try: creds = self._auth_provider.get_credentials() self._service = build("gmail", "v1", credentials=creds) except Exception as exc: raise MailIntakeAdapterError( "Failed to initialize Gmail service" ) from exc return self._service def iter_message_refs(self, query: str) -> Iterator[Dict[str, str]]: """ Iterate over message references matching the query. Yields: { "message_id": "...", "thread_id": "..." } """ try: request = ( self.service.users() .messages() .list(userId=self._user_id, q=query) ) while request is not None: response = request.execute() for msg in response.get("messages", []): yield { "message_id": msg["id"], "thread_id": msg["threadId"], } request = ( self.service.users() .messages() .list_next(request, response) ) except HttpError as exc: raise MailIntakeAdapterError( "Gmail API error while listing messages" ) from exc def fetch_message(self, message_id: str) -> Dict[str, Any]: try: return ( self.service.users() .messages() .get(userId=self._user_id, id=message_id) .execute() ) except HttpError as exc: raise MailIntakeAdapterError( f"Gmail API error while fetching message {message_id}" ) from exc def fetch_thread(self, thread_id: str) -> Dict[str, Any]: try: return ( self.service.users() .threads() .get(userId=self._user_id, id=thread_id) .execute() ) except HttpError as exc: raise MailIntakeAdapterError( f"Gmail API error while fetching thread {thread_id}" ) from exc