Skip to main content
Glama

gmail_send_email

Send emails programmatically via Gmail API using OAuth2 tokens, enabling automated email dispatch from remote server environments without browser access.

Instructions

Send an email via Gmail

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
google_access_tokenYesGoogle OAuth2 access token
toYesRecipient email address
subjectYesEmail subject
bodyYesEmail body content (plain text)
html_bodyNoEmail body content in HTML format (optional)

Implementation Reference

  • Core implementation of gmail_send_email tool logic in GmailClient.send_email method. Constructs MIME multipart message with plain and optional HTML body, base64url encodes it, and sends via Gmail API v1 users.messages.send.
    def send_email(self, to: str, subject: str, body: str, html_body: Optional[str] = None) -> str: """Send an email via Gmail Args: to: Recipient email address subject: Email subject body: Plain text email body html_body: Optional HTML email body """ try: # Check if service is initialized if not hasattr(self, 'service'): return json.dumps({ "error": "No valid access token provided. Please refresh your token first.", "status": "error" }) # Define the operation def _operation(): # Create message container message = MIMEMultipart('alternative') message['to'] = to message['subject'] = subject # Attach plain text and HTML parts message.attach(MIMEText(body, 'plain')) if html_body: message.attach(MIMEText(html_body, 'html')) # Encode the message encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode() # Create the message body create_message = { 'raw': encoded_message } # Send the message send_response = self.service.users().messages().send( userId='me', body=create_message ).execute() return json.dumps({ "messageId": send_response['id'], "threadId": send_response.get('threadId', ''), "labelIds": send_response.get('labelIds', []) }) # Execute the operation with token refresh handling return self._handle_token_refresh(_operation) except HttpError as e: logger.error(f"API Exception: {str(e)}") return json.dumps({"error": str(e)}) except Exception as e: logger.error(f"Exception: {str(e)}") return json.dumps({"error": str(e)})
  • MCP dispatch handler in handle_call_tool for gmail_send_email: extracts arguments, initializes GmailClient, validates params, calls send_email method.
    elif name == "gmail_send_email": # Initialize Gmail client with just access token gmail = GmailClient( access_token=access_token ) to = arguments.get("to") subject = arguments.get("subject") body = arguments.get("body") html_body = arguments.get("html_body") if not to or not subject or not body: raise ValueError("Missing required parameters: to, subject, and body are required") results = gmail.send_email(to=to, subject=subject, body=body, html_body=html_body) return [types.TextContent(type="text", text=results)]
  • Tool registration in server.list_tools(): defines name, description, input schema with required parameters for gmail_send_email.
    types.Tool( name="gmail_send_email", description="Send an email via Gmail", inputSchema={ "type": "object", "properties": { "google_access_token": {"type": "string", "description": "Google OAuth2 access token"}, "to": {"type": "string", "description": "Recipient email address"}, "subject": {"type": "string", "description": "Email subject"}, "body": {"type": "string", "description": "Email body content (plain text)"}, "html_body": {"type": "string", "description": "Email body content in HTML format (optional)"} }, "required": ["google_access_token", "to", "subject", "body"] }, ),
  • JavaScript GmailClient.sendEmail method - core implementation that builds multipart raw email message manually, base64 encodes, sends via Gmail API.
    async sendEmail({ to, subject, body, html_body }) { const operation = async () => { if (!this.gmail) { throw new Error('Gmail service not initialized. No valid access token provided.'); } const messageParts = [ `To: ${to}`, `Subject: ${subject}`, 'Content-Type: multipart/alternative; boundary="boundary"', '', '--boundary', 'Content-Type: text/plain; charset="UTF-8"', '', body, '--boundary', 'Content-Type: text/html; charset="UTF-8"', '', html_body || '', '--boundary--' ]; const rawMessage = Buffer.from(messageParts.join('\r\n')).toString('base64').replace(/\+/g, '-').replace(/\//g, '_'); const res = await this.gmail.users.messages.send({ userId: 'me', requestBody: { raw: rawMessage } }); return JSON.stringify({ messageId: res.data.id, threadId: res.data.threadId, labelIds: res.data.labelIds }); }; return await this._handleTokenRefresh(operation); }
  • JavaScript MCP server.tool registration and handler for gmail_send_email: Zod schema, creates GmailClient, calls sendEmail, returns result.
    server.tool( 'gmail_send_email', 'Send an email via Gmail', { google_access_token: z.string().describe('Google OAuth2 access token'), to: z.string().describe('Recipient email address'), subject: z.string().describe('Email subject'), body: z.string().describe('Email body content (plain text)'), html_body: z.string().optional().describe('Email body content in HTML format (optional)') }, async ({ google_access_token, to, subject, body, html_body }) => { try { const gmail = new GmailClient({ accessToken: google_access_token }); const result = await gmail.sendEmail({ to, subject, body, html_body }); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: `Error: ${error.message}` }] }; } } );

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/baryhuang/mcp-headless-gmail'

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