send_gmail_message
Send emails directly from your Gmail account by specifying recipient, subject, and message body. Confirms delivery with the sent email's message ID.
Instructions
Sends an email using the user's Gmail account.
Args:
to (str): Recipient email address.
subject (str): Email subject.
body (str): Email body (plain text).
user_google_email (str): The user's Google email address. Required.
Returns:
str: Confirmation message with the sent email's message ID.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | Email body (plain text). | |
| service | Yes | ||
| subject | Yes | Email subject. | |
| to | Yes | Recipient email address. | |
| user_google_email | Yes |
Implementation Reference
- gmail/gmail_tools.py:707-804 (handler)The primary handler for the 'send_gmail_message' MCP tool. Decorated with @server.tool() for registration. Uses Gmail API to send emails, supports threading/replies, plain/HTML body, CC/BCC. Relies on helper _prepare_gmail_message for MIME message construction.@server.tool() @handle_http_errors("send_gmail_message", service_type="gmail") @require_google_service("gmail", GMAIL_SEND_SCOPE) async def send_gmail_message( service, user_google_email: str, to: str = Body(..., description="Recipient email address."), subject: str = Body(..., description="Email subject."), body: str = Body(..., description="Email body content (plain text or HTML)."), body_format: Literal["plain", "html"] = Body( "plain", description="Email body format. Use 'plain' for plaintext or 'html' for HTML content." ), cc: Optional[str] = Body(None, description="Optional CC email address."), bcc: Optional[str] = Body(None, description="Optional BCC email address."), thread_id: Optional[str] = Body(None, description="Optional Gmail thread ID to reply within."), in_reply_to: Optional[str] = Body(None, description="Optional Message-ID of the message being replied to."), references: Optional[str] = Body(None, description="Optional chain of Message-IDs for proper threading."), ) -> str: """ Sends an email using the user's Gmail account. Supports both new emails and replies. Args: to (str): Recipient email address. subject (str): Email subject. body (str): Email body content. body_format (Literal['plain', 'html']): Email body format. Defaults to 'plain'. cc (Optional[str]): Optional CC email address. bcc (Optional[str]): Optional BCC email address. user_google_email (str): The user's Google email address. Required. thread_id (Optional[str]): Optional Gmail thread ID to reply within. When provided, sends a reply. in_reply_to (Optional[str]): Optional Message-ID of the message being replied to. Used for proper threading. references (Optional[str]): Optional chain of Message-IDs for proper threading. Should include all previous Message-IDs. Returns: str: Confirmation message with the sent email's message ID. Examples: # Send a new email send_gmail_message(to="user@example.com", subject="Hello", body="Hi there!") # Send an HTML email send_gmail_message( to="user@example.com", subject="Hello", body="<strong>Hi there!</strong>", body_format="html" ) # Send an email with CC and BCC send_gmail_message( to="user@example.com", cc="manager@example.com", bcc="archive@example.com", subject="Project Update", body="Here's the latest update..." ) # Send a reply send_gmail_message( to="user@example.com", subject="Re: Meeting tomorrow", body="Thanks for the update!", thread_id="thread_123", in_reply_to="<message123@gmail.com>", references="<original@gmail.com> <message123@gmail.com>" ) """ logger.info( f"[send_gmail_message] Invoked. Email: '{user_google_email}', Subject: '{subject}'" ) # Prepare the email message raw_message, thread_id_final = _prepare_gmail_message( subject=subject, body=body, to=to, cc=cc, bcc=bcc, thread_id=thread_id, in_reply_to=in_reply_to, references=references, body_format=body_format, from_email=user_google_email, ) send_body = {"raw": raw_message} # Associate with thread if provided if thread_id_final: send_body["threadId"] = thread_id_final # Send the message sent_message = await asyncio.to_thread( service.users().messages().send(userId="me", body=send_body).execute ) message_id = sent_message.get("id") return f"Email sent! Message ID: {message_id}"
- gmail/gmail_tools.py:175-241 (helper)Helper function used by send_gmail_message to construct the MIME email message, handle threading headers (In-Reply-To, References), support plain/HTML body, and base64 encode the raw message for Gmail API.def _prepare_gmail_message( subject: str, body: str, to: Optional[str] = None, cc: Optional[str] = None, bcc: Optional[str] = None, thread_id: Optional[str] = None, in_reply_to: Optional[str] = None, references: Optional[str] = None, body_format: Literal["plain", "html"] = "plain", from_email: Optional[str] = None, ) -> tuple[str, Optional[str]]: """ Prepare a Gmail message with threading support. Args: subject: Email subject body: Email body content to: Optional recipient email address cc: Optional CC email address bcc: Optional BCC email address thread_id: Optional Gmail thread ID to reply within in_reply_to: Optional Message-ID of the message being replied to references: Optional chain of Message-IDs for proper threading body_format: Content type for the email body ('plain' or 'html') from_email: Optional sender email address Returns: Tuple of (raw_message, thread_id) where raw_message is base64 encoded """ # Handle reply subject formatting reply_subject = subject if in_reply_to and not subject.lower().startswith('re:'): reply_subject = f"Re: {subject}" # Prepare the email normalized_format = body_format.lower() if normalized_format not in {"plain", "html"}: raise ValueError("body_format must be either 'plain' or 'html'.") message = MIMEText(body, normalized_format) message["Subject"] = reply_subject # Add sender if provided if from_email: message["From"] = from_email # Add recipients if provided if to: message["To"] = to if cc: message["Cc"] = cc if bcc: message["Bcc"] = bcc # Add reply headers for threading if in_reply_to: message["In-Reply-To"] = in_reply_to if references: message["References"] = references # Encode message raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode() return raw_message, thread_id
- gmail/gmail_tools.py:707-707 (registration)Decorators on the handler function that register it as an MCP tool via @server.tool(), handle errors, and require Gmail send scope.@server.tool()
- gmail/gmail_tools.py:710-724 (schema)Input schema defined via FastAPI Body() parameters with descriptions, type hints (str, Optional[str], Literal), and comprehensive docstring with usage examples serving as schema documentation.async def send_gmail_message( service, user_google_email: str, to: str = Body(..., description="Recipient email address."), subject: str = Body(..., description="Email subject."), body: str = Body(..., description="Email body content (plain text or HTML)."), body_format: Literal["plain", "html"] = Body( "plain", description="Email body format. Use 'plain' for plaintext or 'html' for HTML content." ), cc: Optional[str] = Body(None, description="Optional CC email address."), bcc: Optional[str] = Body(None, description="Optional BCC email address."), thread_id: Optional[str] = Body(None, description="Optional Gmail thread ID to reply within."), in_reply_to: Optional[str] = Body(None, description="Optional Message-ID of the message being replied to."), references: Optional[str] = Body(None, description="Optional chain of Message-IDs for proper threading."), ) -> str: