/** * Send email functionality */ const config = require('../config'); const { callGraphAPI } = require('../utils/graph-api'); const { ensureAuthenticated } = require('../auth'); const { normalizeMailbox, buildPath, withMailboxHeaders } = require('../utils/mailbox'); /** * Send email handler * @param {object} args - Tool arguments * @returns {object} - MCP response */ async function handleSendEmail(args) { const { to, cc, bcc, subject, body, importance = 'normal', saveToSentItems = true, from: fromArg, onBehalfOf = false } = args; const mb = normalizeMailbox(args.mailbox); const onBehalf = onBehalfOf === true || onBehalfOf === 'true'; if (!to) { return { content: [{ type: "text", text: "Recipient (to) is required." }] }; } if (!subject) { return { content: [{ type: "text", text: "Subject is required." }] }; } if (!body) { return { content: [{ type: "text", text: "Body content is required." }] }; } try { const accessToken = await ensureAuthenticated(); const toRecipients = to.split(',').map(email => { email = email.trim(); return { emailAddress: { address: email } }; }); const ccRecipients = cc ? cc.split(',').map(email => { email = email.trim(); return { emailAddress: { address: email } }; }) : []; const bccRecipients = bcc ? bcc.split(',').map(email => { email = email.trim(); return { emailAddress: { address: email } }; }) : []; const fromAddr = (fromArg && String(fromArg).trim()) || (mb.kind === 'user' ? mb.smtpOrUpn : null); // Default: when mailbox is a shared UPN, send via users/{upn}/sendMail (Send As style). // onBehalfOf=true forces me/sendMail with from=shared (Send on Behalf style). let sendPath = 'me/sendMail'; let anchorMb = mb; if (mb.kind === 'user' && !onBehalf) { sendPath = buildPath(mb, 'sendMail'); } else if (fromAddr && onBehalf) { sendPath = 'me/sendMail'; anchorMb = normalizeMailbox(fromAddr); } else if (mb.kind === 'user') { sendPath = buildPath(mb, 'sendMail'); } const message = { subject, body: { // New Outlook + Graph: prefer HTML when the body looks like a document. // Match ]|<(?:table|div|h[1-6]|p)\b/i.test(body || '') ? 'HTML' : 'Text', content: body }, toRecipients, ccRecipients: ccRecipients.length > 0 ? ccRecipients : undefined, bccRecipients: bccRecipients.length > 0 ? bccRecipients : undefined, importance }; if (fromAddr) { message.from = { emailAddress: { address: fromAddr } }; } const emailObject = { message, saveToSentItems }; await callGraphAPI( accessToken, 'POST', sendPath, emailObject, null, { headers: withMailboxHeaders(anchorMb) } ); const fromNote = fromAddr ? `\nFrom: ${fromAddr}${onBehalf ? ' (on behalf)' : ''}` : ''; const mailboxNote = mb.kind === 'user' ? `\nMailbox: ${mb.smtpOrUpn}` : ''; return { content: [{ type: "text", text: `Email sent successfully!${mailboxNote}${fromNote}\n\nSubject: ${subject}\nRecipients: ${toRecipients.length}${ccRecipients.length > 0 ? ` + ${ccRecipients.length} CC` : ''}${bccRecipients.length > 0 ? ` + ${bccRecipients.length} BCC` : ''}\nMessage Length: ${body.length} characters` }] }; } catch (error) { if (error.message === 'Authentication required') { return { content: [{ type: "text", text: "Authentication required. Please use the 'authenticate' tool first." }] }; } return { content: [{ type: "text", text: `Error sending email: ${error.message}` }] }; } } module.exports = handleSendEmail;