@aot-tech/gmail-mcp-server
Version:
Gmail MCP Server with Bearer Token Authentication - A Model Context Protocol server for Gmail access
169 lines (166 loc) • 5.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseEmailAddress = parseEmailAddress;
exports.formatEmailAddress = formatEmailAddress;
exports.getDisplayName = getDisplayName;
exports.createEmailMessage = createEmailMessage;
exports.decodeEmailContent = decodeEmailContent;
exports.extractEmailBody = extractEmailBody;
exports.extractHeaderValue = extractHeaderValue;
exports.extractEmailDetails = extractEmailDetails;
exports.formatEmailDetails = formatEmailDetails;
exports.formatSearchResult = formatSearchResult;
exports.formatSearchResultWithName = formatSearchResultWithName;
function parseEmailAddress(emailString) {
if (!emailString)
return { name: '', email: '' };
const nameEmailMatch = emailString.match(/^"?([^"]*?)"?\s*<([^>]+)>$/);
if (nameEmailMatch) {
return {
name: nameEmailMatch[1].trim(),
email: nameEmailMatch[2].trim()
};
}
const simpleNameEmailMatch = emailString.match(/^([^<]+?)\s*<([^>]+)>$/);
if (simpleNameEmailMatch) {
return {
name: simpleNameEmailMatch[1].trim(),
email: simpleNameEmailMatch[2].trim()
};
}
const emailOnlyMatch = emailString.match(/^([^<>\s]+@[^<>\s]+)$/);
if (emailOnlyMatch) {
return {
name: '',
email: emailOnlyMatch[1].trim()
};
}
return {
name: '',
email: emailString.trim()
};
}
function formatEmailAddress(emailString) {
const { name, email } = parseEmailAddress(emailString);
if (name && name.length > 0) {
return `${name} <${email}>`;
}
return email;
}
function getDisplayName(emailString) {
const { name, email } = parseEmailAddress(emailString);
if (name && name.length > 0) {
return name;
}
const localPart = email.split('@')[0];
if (localPart) {
return localPart
.replace(/[._]/g, ' ')
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(' ');
}
return email;
}
function encodeSubject(subject) {
if (!/^[\x00-\x7F]*$/.test(subject)) {
const encodedSubject = Buffer.from(subject, 'utf-8').toString('base64');
return `=?UTF-8?B?${encodedSubject}?=`;
}
return subject;
}
function createEmailMessage(emailData) {
const { to, subject, body, cc, bcc } = emailData;
let message = '';
message += `To: ${to.join(', ')}\r\n`;
if (cc && cc.length > 0) {
message += `Cc: ${cc.join(', ')}\r\n`;
}
if (bcc && bcc.length > 0) {
message += `Bcc: ${bcc.join(', ')}\r\n`;
}
message += `Subject: ${encodeSubject(subject)}\r\n`;
message += `Content-Type: text/plain; charset="UTF-8"\r\n`;
message += `MIME-Version: 1.0\r\n`;
message += `\r\n${body}`;
return Buffer.from(message).toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
function decodeEmailContent(data) {
if (!data)
return '';
const base64 = data.replace(/-/g, '+').replace(/_/g, '/');
const padding = base64.length % 4;
const paddedBase64 = padding ? base64 + '='.repeat(4 - padding) : base64;
try {
return Buffer.from(paddedBase64, 'base64').toString('utf-8');
}
catch (error) {
return data;
}
}
function extractEmailBody(payload) {
if (!payload)
return '';
if (payload.body && payload.body.data) {
return decodeEmailContent(payload.body.data);
}
if (payload.parts && Array.isArray(payload.parts)) {
for (const part of payload.parts) {
if (part.mimeType === 'text/plain' && part.body && part.body.data) {
return decodeEmailContent(part.body.data);
}
}
for (const part of payload.parts) {
if (part.mimeType === 'text/html' && part.body && part.body.data) {
return decodeEmailContent(part.body.data);
}
}
}
return 'Could not extract email content';
}
function extractHeaderValue(headers, headerName) {
const header = headers.find(h => h.name.toLowerCase() === headerName.toLowerCase());
return header?.value || '';
}
function extractEmailDetails(message) {
const headers = message.payload?.headers || [];
const fromHeader = extractHeaderValue(headers, 'From');
const { name: fromName, email: fromEmail } = parseEmailAddress(fromHeader);
return {
id: message.id,
from: formatEmailAddress(fromHeader) || 'Unknown',
fromName: fromName || getDisplayName(fromHeader),
fromEmail: fromEmail || 'Unknown',
to: extractHeaderValue(headers, 'To') || 'Unknown',
subject: extractHeaderValue(headers, 'Subject') || 'No Subject',
date: extractHeaderValue(headers, 'Date') || 'Unknown Date',
body: extractEmailBody(message.payload),
};
}
function formatEmailDetails(details) {
return `Email Details:
From: ${details.from}
To: ${details.to}
Subject: ${details.subject}
Date: ${details.date}
--- Email Body ---
${details.body}`;
}
function formatSearchResult(messageId, from, subject, date) {
const displayFrom = formatEmailAddress(from);
return `• ID: ${messageId}
From: ${displayFrom}
Subject: ${subject}
Date: ${date}`;
}
function formatSearchResultWithName(messageId, from, subject, date) {
const { name: fromName, email: fromEmail } = parseEmailAddress(from);
const displayName = fromName || getDisplayName(from);
return `• ID: ${messageId}
From: ${displayName} (${fromEmail})
Subject: ${subject}
Date: ${date}`;
}