Skip to main content
Glama
taylorwilsdon

Google Workspace MCP Server - Control Gmail, Calendar, Docs, Sheets, Slides, Chat, Forms & Drive

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
NameRequiredDescriptionDefault
bodyYesEmail body (plain text).
serviceYes
subjectYesEmail subject.
toYesRecipient email address.
user_google_emailYes

Implementation Reference

  • 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}"
  • 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
  • Decorators on the handler function that register it as an MCP tool via @server.tool(), handle errors, and require Gmail send scope.
    @server.tool()
  • 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:

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/taylorwilsdon/google_workspace_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server