Skip to main content
Glama

gmail_get_email

Retrieve complete email content including subject, sender, recipients, date, labels, and body text using a Gmail message ID.

Instructions

Get the full content of a specific email by its Gmail message ID. Returns subject, sender, recipients, date, labels, and full body text.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
email_idYesThe Gmail message ID obtained from search or list results.

Implementation Reference

  • Input schema definition for the 'gmail_get_email' tool, specifying the required 'email_id' parameter.
    Tool(
        name="gmail_get_email",
        description="Get the full content of a specific email by its ID",
        inputSchema={
            "type": "object",
            "properties": {
                "email_id": {
                    "type": "string",
                    "description": "The Gmail message ID",
                },
            },
            "required": ["email_id"],
        },
    ),
  • The main handler in the MCP server's call_tool function that executes the 'gmail_get_email' tool by retrieving the email via GmailClient and formatting it for response.
    elif name == "gmail_get_email":
        email_id = arguments.get("email_id")
        if not email_id:
            return [TextContent(type="text", text="Error: email_id is required")]
        email = await client.get_email(email_id)
        return [
            TextContent(
                type="text",
                text=_format_full_email(email),
            )
        ]
  • Core implementation in GmailClient that fetches the full email from Gmail API using users.messages.get and parses it into an Email object.
    async def get_email(self, message_id: str) -> Email:
        """Get a single email by ID with full content."""
        try:
            msg = (
                self.service.users()
                .messages()
                .get(userId="me", id=message_id, format="full")
                .execute()
            )
            return self._parse_message(msg, include_body=True)
        except HttpError as e:
            logger.error(f"Failed to get email {message_id}: {e}")
            raise
  • Helper function used by the handler to format the retrieved email into a readable text response.
    def _format_full_email(email) -> str:
        """Format full email for display."""
        categories = f"Categories: {', '.join(email.categories)}" if email.categories else ""
    
        attachments = ""
        if email.attachments:
            att_list = ", ".join(a.filename for a in email.attachments)
            attachments = f"\nAttachments: {att_list}"
    
        body = email.body_text or "(No text content)"
        if len(body) > 2000:
            body = body[:2000] + "\n\n... [truncated]"
    
        return f"""
    **Subject:** {email.subject}
    **From:** {email.sender}
    **To:** {', '.join(str(t) for t in email.to)}
    **Date:** {email.date.strftime('%Y-%m-%d %H:%M:%S')}
    **Labels:** {', '.join(email.labels)}
    {categories}
    {attachments}
    
    ---
    
    {body}
    """
  • Helper function in GmailClient that parses the raw Gmail API message into a structured Email object, including body extraction, categorization, and metadata parsing.
    def _parse_message(self, msg: dict, include_body: bool = False) -> Email:
        """Parse Gmail API message into Email model."""
        payload = msg.get("payload", {})
        headers = payload.get("headers", [])
    
        # Parse date
        date_str = self._get_header(headers, "Date")
        try:
            date = parsedate_to_datetime(date_str)
        except Exception:
            # Fallback to internal date
            internal_date = int(msg.get("internalDate", 0)) / 1000
            date = datetime.fromtimestamp(internal_date, tz=timezone.utc)
    
        # Parse labels
        label_ids = msg.get("labelIds", [])
        is_read = "UNREAD" not in label_ids
        is_starred = "STARRED" in label_ids
        is_important = "IMPORTANT" in label_ids
    
        # Extract body if requested
        text_body, html_body = None, None
        if include_body:
            text_body, html_body = self._extract_body(payload)
    
        # Extract attachments
        attachments = self._extract_attachments(payload)
    
        email = Email(
            id=msg["id"],
            thread_id=msg["threadId"],
            subject=self._get_header(headers, "Subject") or "(No Subject)",
            snippet=msg.get("snippet", ""),
            body_text=text_body,
            body_html=html_body,
            sender=self._parse_email_address(self._get_header(headers, "From")),
            to=self._parse_email_addresses(self._get_header(headers, "To")),
            cc=self._parse_email_addresses(self._get_header(headers, "Cc")),
            reply_to=self._parse_email_address(self._get_header(headers, "Reply-To"))
            if self._get_header(headers, "Reply-To")
            else None,
            date=date,
            labels=label_ids,
            is_read=is_read,
            is_starred=is_starred,
            is_important=is_important,
            attachments=attachments,
            has_attachments=len(attachments) > 0,
        )
    
        # Categorize
        email.categories = self._categorize_email(email)
        email.priority = self._get_priority(email.categories)
    
        return email

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/murphy360/mcp_gmail'

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