get_email_content
Fetch email content by providing the email ID using the JMAP MCP Server tool for efficient email data retrieval.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| inputSchema | Yes |
Implementation Reference
- index.js:237-307 (handler)The handler function for 'get_email_content' tool. It fetches the email details using JMAP Email.get, downloads the body content (prioritizing text over HTML), handles errors, and formats a readable output with subject, from, to, date, and body.async ({ emailId }) => { const session = await jam.session; const accountId = session.primaryAccounts["urn:ietf:params:jmap:mail"]; const [emails] = await jam.api.Email.get({ accountId, ids: [emailId], properties: ["id", "textBody", "htmlBody", "subject", "from", "to", "cc", "bcc", "sentAt", "receivedAt"] }); if (!emails || emails.list.length === 0) { return { content: [{ type: "text", text: `Error: Email with ID ${emailId} not found.` }], isError: true }; } const email = emails.list[0]; let bodyContent = 'No body content found.'; const downloadBodyPartContent = async (bodyPart) => { if (!bodyPart || !bodyPart.blobId) { return null; } try { const response = await jam.downloadBlob({ accountId, blobId: bodyPart.blobId, mimeType: bodyPart.type || 'application/octet-stream', // Use part type or a default fileName: bodyPart.name || 'body_part' // Use part name or a default }); if (response.ok) { return response.text(); // Read the response body as text } else { console.error(`Failed to download blob ${bodyPart.blobId}: ${response.status} ${response.statusText}`); return null; } } catch (error) { console.error(`Error downloading blob ${bodyPart.blobId}:`, error); return null; } }; // Prioritize text body, then HTML body if (email.textBody && email.textBody.length > 0) { // Assuming we only need the content of the first text part for simplicity const firstTextPart = email.textBody[0]; const downloadedText = await downloadBodyPartContent(firstTextPart); if (downloadedText !== null) { bodyContent = downloadedText; } } else if (email.htmlBody && email.htmlBody.length > 0) { // Assuming we only need the content of the first html part for simplicity const firstHtmlPart = email.htmlBody[0]; const downloadedHtml = await downloadBodyPartContent(firstHtmlPart); // Note: For HTML body, you might want to strip HTML tags for a text representation if (downloadedHtml !== null) { bodyContent = `[HTML Body - may contain tags]\n${downloadedHtml}`; // Indicate it's HTML } } return { content: [{ type: "text", text: `Subject: ${email.subject || '(No Subject)'}\nFrom: ${email.from ? email.from.map(f => f.name ? `${f.name} <${f.email}>` : f.email).join(', ') : '(Unknown Sender)'}\nTo: ${email.to ? email.to.map(t => t.name ? `${t.name} <${t.email}>` : t.email).join(', ') : '(Unknown Recipient)'}\nDate: ${email.receivedAt || email.sentAt || '(Unknown Date)'}\n\n---\n\n${bodyContent}` }] }; }
- index.js:233-235 (schema)Input schema for the 'get_email_content' tool, requiring an 'emailId' string.inputSchema: z.object({ emailId: z.string().describe("The ID of the email to fetch.") })
- index.js:229-308 (registration)Registration of the 'get_email_content' tool using server.tool, including name, description, input schema, and handler reference.server.tool( "get_email_content", { description: "Retrieves the full content of an email by its ID, including subject, sender, recipients, date, and body (text or HTML).", inputSchema: z.object({ emailId: z.string().describe("The ID of the email to fetch.") }) }, async ({ emailId }) => { const session = await jam.session; const accountId = session.primaryAccounts["urn:ietf:params:jmap:mail"]; const [emails] = await jam.api.Email.get({ accountId, ids: [emailId], properties: ["id", "textBody", "htmlBody", "subject", "from", "to", "cc", "bcc", "sentAt", "receivedAt"] }); if (!emails || emails.list.length === 0) { return { content: [{ type: "text", text: `Error: Email with ID ${emailId} not found.` }], isError: true }; } const email = emails.list[0]; let bodyContent = 'No body content found.'; const downloadBodyPartContent = async (bodyPart) => { if (!bodyPart || !bodyPart.blobId) { return null; } try { const response = await jam.downloadBlob({ accountId, blobId: bodyPart.blobId, mimeType: bodyPart.type || 'application/octet-stream', // Use part type or a default fileName: bodyPart.name || 'body_part' // Use part name or a default }); if (response.ok) { return response.text(); // Read the response body as text } else { console.error(`Failed to download blob ${bodyPart.blobId}: ${response.status} ${response.statusText}`); return null; } } catch (error) { console.error(`Error downloading blob ${bodyPart.blobId}:`, error); return null; } }; // Prioritize text body, then HTML body if (email.textBody && email.textBody.length > 0) { // Assuming we only need the content of the first text part for simplicity const firstTextPart = email.textBody[0]; const downloadedText = await downloadBodyPartContent(firstTextPart); if (downloadedText !== null) { bodyContent = downloadedText; } } else if (email.htmlBody && email.htmlBody.length > 0) { // Assuming we only need the content of the first html part for simplicity const firstHtmlPart = email.htmlBody[0]; const downloadedHtml = await downloadBodyPartContent(firstHtmlPart); // Note: For HTML body, you might want to strip HTML tags for a text representation if (downloadedHtml !== null) { bodyContent = `[HTML Body - may contain tags]\n${downloadedHtml}`; // Indicate it's HTML } } return { content: [{ type: "text", text: `Subject: ${email.subject || '(No Subject)'}\nFrom: ${email.from ? email.from.map(f => f.name ? `${f.name} <${f.email}>` : f.email).join(', ') : '(Unknown Sender)'}\nTo: ${email.to ? email.to.map(t => t.name ? `${t.name} <${t.email}>` : t.email).join(', ') : '(Unknown Recipient)'}\nDate: ${email.receivedAt || email.sentAt || '(Unknown Date)'}\n\n---\n\n${bodyContent}` }] }; } );
- index.js:260-281 (helper)Helper function inside the handler to download blob content for email body parts using jam.downloadBlob.const downloadBodyPartContent = async (bodyPart) => { if (!bodyPart || !bodyPart.blobId) { return null; } try { const response = await jam.downloadBlob({ accountId, blobId: bodyPart.blobId, mimeType: bodyPart.type || 'application/octet-stream', // Use part type or a default fileName: bodyPart.name || 'body_part' // Use part name or a default }); if (response.ok) { return response.text(); // Read the response body as text } else { console.error(`Failed to download blob ${bodyPart.blobId}: ${response.status} ${response.statusText}`); return null; } } catch (error) { console.error(`Error downloading blob ${bodyPart.blobId}:`, error); return null; } };