send-email
Compose and deliver emails to specified recipients with a subject line and text body, enabling automated notifications or AI-driven communication.
Instructions
发送邮件
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | 邮件收件人 | |
| subject | Yes | 邮件主题 | |
| text | Yes | 邮件内容 |
Implementation Reference
- src/index.ts:81-211 (registration)Registration of the 'send_email' tool in the ListTools handler, defining its name, description, and JSON input schema.
this.server.setRequestHandler(ListToolsRequestSchema, async () => { const tools: Tool[] = [ { name: "send_email", description: "Send an email to specified recipients", inputSchema: { type: "object", properties: { to: { type: "string", description: "Recipient email address", }, subject: { type: "string", description: "Email subject", }, body: { type: "string", description: "Email body content", }, from: { type: "string", description: "Sender email address (optional)", }, html: { type: "boolean", description: "Whether the body is HTML format", }, attachments: { type: "array", description: "Email attachments", items: { type: "object", properties: { filename: { type: "string" }, path: { type: "string" }, content: { type: "string" }, }, }, }, }, required: ["to", "subject", "body"], }, }, { name: "read_emails", description: "Read emails from inbox or specified folder", inputSchema: { type: "object", properties: { limit: { type: "number", description: "Number of emails to retrieve (default: 10)", }, folder: { type: "string", description: "Email folder to read from (default: INBOX)", }, unreadOnly: { type: "boolean", description: "Only retrieve unread emails", }, }, }, }, { name: "search_emails", description: "Search emails by query", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query", }, limit: { type: "number", description: "Number of results to return (default: 10)", }, folder: { type: "string", description: "Folder to search in (default: INBOX)", }, }, required: ["query"], }, }, { name: "delete_email", description: "Delete an email by message ID", inputSchema: { type: "object", properties: { messageId: { type: "string", description: "Email message ID to delete", }, }, required: ["messageId"], }, }, { name: "reply_email", description: "Reply to an email", inputSchema: { type: "object", properties: { messageId: { type: "string", description: "Original message ID to reply to", }, body: { type: "string", description: "Reply body content", }, replyAll: { type: "boolean", description: "Reply to all recipients", }, html: { type: "boolean", description: "Whether the body is HTML format", }, }, required: ["messageId", "body"], }, }, ]; return { tools }; }); - src/index.ts:24-35 (schema)Zod validation schema for the 'send_email' tool inputs, defining required and optional fields with type constraints.
const SendEmailSchema = z.object({ to: z.string().email(), subject: z.string(), body: z.string(), from: z.string().email().optional(), html: z.boolean().optional(), attachments: z.array(z.object({ filename: z.string(), path: z.string().optional(), content: z.string().optional(), })).optional(), }); - src/index.ts:217-220 (handler)CallTool handler dispatch for 'send_email' — parses args with Zod schema, creates the tool via createSendEmailTool(), and invokes it.
case "send_email": { const args = SendEmailSchema.parse(request.params.arguments); const sendEmailTool = createSendEmailTool(); return await sendEmailTool(args); - src/tools/sendEmail.ts:159-206 (handler)Core handler function createSendEmailTool() that reads config, validates environment variables, and dispatches to sendViaGmail or sendViaSMTP based on provider setting.
export function createSendEmailTool() { return async (args: SendEmailArgs) => { try { const config = getEmailConfig(); // 验证必需的环境变量 if (config.provider === "gmail") { if (!config.gmail?.clientId || !config.gmail?.clientSecret || !config.gmail?.refreshToken) { throw new Error("Gmail配置缺失。请设置 GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, 和 GMAIL_REFRESH_TOKEN"); } } else { if (!config.smtp?.auth.user || !config.smtp?.auth.pass) { throw new Error("SMTP配置缺失。请设置 SMTP_USER 和 SMTP_PASS"); } } if (!config.defaultFrom) { throw new Error("DEFAULT_FROM_EMAIL 环境变量是必需的"); } let result; if (config.provider === "gmail") { result = await sendViaGmail(args, config); } else { result = await sendViaSMTP(args, config); } return { content: [ { type: "text", text: `✅ 邮件发送成功!\n\n详情:\n- 收件人: ${args.to}\n- 主题: ${args.subject}\n- 提供商: ${result.provider}\n- 消息ID: ${result.messageId}\n- 格式: ${args.html ? "HTML" : "纯文本"}${args.attachments ? `\n- 附件数量: ${args.attachments.length}` : ""}`, }, ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : "发生未知错误"; return { content: [ { type: "text", text: `❌ 邮件发送失败: ${errorMessage}`, }, ], }; } }; } - src/tools/sendEmail.ts:73-111 (helper)Helper function sendViaGmail() that sends an email using the Gmail API (OAuth2 authentication, base64-encoded raw message).
async function sendViaGmail(args: SendEmailArgs, config: EmailConfig) { const oauth2Client = new google.auth.OAuth2( config.gmail!.clientId, config.gmail!.clientSecret ); oauth2Client.setCredentials({ refresh_token: config.gmail!.refreshToken, access_token: config.gmail!.accessToken, }); const gmail = google.gmail({ version: "v1", auth: oauth2Client }); // 创建邮件内容 const emailLines = [ `To: ${args.to}`, `From: ${args.from || config.defaultFrom}`, `Subject: ${args.subject}`, `Content-Type: ${args.html ? "text/html" : "text/plain"}; charset=utf-8`, "", args.body, ]; const email = emailLines.join("\n"); const encodedEmail = Buffer.from(email).toString("base64").replace(/\+/g, "-").replace(/\//g, "_"); const result = await gmail.users.messages.send({ userId: "me", requestBody: { raw: encodedEmail, }, }); return { success: true, messageId: result.data.id, provider: "gmail", }; } - src/tools/sendEmail.ts:114-156 (helper)Helper function sendViaSMTP() that sends an email via SMTP using nodemailer, supporting attachments and HTML content.
async function sendViaSMTP(args: SendEmailArgs, config: EmailConfig) { const transporter = nodemailer.createTransport({ host: config.smtp!.host, port: config.smtp!.port, secure: config.smtp!.secure, auth: config.smtp!.auth, }); // 处理附件 const attachments = []; if (args.attachments) { for (const attachment of args.attachments) { if (attachment.path) { // 文件附件 attachments.push({ filename: attachment.filename, path: attachment.path, }); } else if (attachment.content) { // 内容附件 attachments.push({ filename: attachment.filename, content: attachment.content, }); } } } const mailOptions = { from: args.from || config.defaultFrom, to: args.to, subject: args.subject, [args.html ? "html" : "text"]: args.body, attachments: attachments.length > 0 ? attachments : undefined, }; const result = await transporter.sendMail(mailOptions); return { success: true, messageId: result.messageId, provider: "smtp", }; }