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
| Name | Required | Description | Default |
|---|---|---|---|
| google_access_token | Yes | Google OAuth2 access token | |
| to | Yes | Recipient email address | |
| subject | Yes | Email subject | |
| body | Yes | Email body content (plain text) | |
| html_body | No | Email 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)] - src/mcp_server_headless_gmail/server.py:517-531 (registration)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"] }, ), - server.js:202-234 (handler)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); } - server.js:358-379 (handler)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}` }] }; } } );