Agentic_flow / gmail_tools.py
disLodge's picture
Bug fixes
dd57d13
Raw History Blame Contribute Delete
3.42 kB
import base64
from email.mime.text import MIMEText
from langchain_core.tools import tool
from langgraph.types import interrupt
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google.auth.exceptions import RefreshError
from google_auth_helpers import (
build_auth_required,
get_google_credentials,
is_auth_failure,
)
def _gmail_service(
user_id: str,
thread_id: str | None = None,
):
creds, auth_info = get_google_credentials(
user_id=user_id,
service="Gmail",
thread_id=thread_id,
)
if auth_info:
interrupt(auth_info)
if creds is None:
interrupt(
build_auth_required(
user_id=user_id,
service="Gmail",
thread_id=thread_id,
)
)
return build(
"gmail",
"v1",
credentials=creds,
)
def _create_message(
to_email: str,
subject: str,
body: str,
):
message = MIMEText(body)
message["To"] = to_email
message["Subject"] = subject
encoded_message = base64.urlsafe_b64encode(
message.as_bytes()
).decode()
return {
"raw": encoded_message
}
def _send_email(
user_id: str,
to_email: str,
subject: str,
body: str,
thread_id: str | None = None,
) -> str:
"""
Sends an email using the user's connected Gmail account.
Args:
user_id: The authenticated application user ID.
to_email: Recipient email address.
subject: Email subject.
body: Email body.
"""
service = _gmail_service(
user_id=user_id,
thread_id=thread_id,
)
try:
message = _create_message(
to_email=to_email,
subject=subject,
body=body,
)
result = (
service
.users()
.messages()
.send(
userId="me",
body=message,
)
.execute()
)
return (
f"Email successfully sent to "
f"{to_email}."
)
except RefreshError as e:
print(
f"[GMAIL AUTH] RefreshError "
f"for {user_id}: {repr(e)}"
)
interrupt(
build_auth_required(
user_id=user_id,
service="Gmail",
thread_id=thread_id,
revoke=True,
)
)
except HttpError as e:
print(
f"[GMAIL] HttpError "
f"for {user_id}: {repr(e)}"
)
if is_auth_failure(e):
interrupt(
build_auth_required(
user_id=user_id,
service="Gmail",
thread_id=thread_id,
revoke=True,
)
)
return f"Gmail send failed: {e}"
except Exception as e:
print(
f"[GMAIL] Unexpected error: "
f"{repr(e)}"
)
return f"Failed to send email: {e}"
@tool
def send_email_tool(
to_email: str,
subject: str,
body: str,
) -> str:
"""
Sends an email using the authenticated user's Gmail account.
The backend supplies the authenticated user.
"""
raise RuntimeError(
"send_email_tool must be executed through the backend."
)