如何使用Gmail API在Node.js中发送带附件的邮件?新手求助
嘿,作为Node.js新手碰到这种找不到对应文档的情况真的挺闹心的!别慌,Gmail API其实有专门适配Node.js的附件上传方案,我给你一步步捋清楚:
核心思路:Gmail API的Node.js附件上传逻辑
Gmail API发送带附件的邮件核心是要把邮件内容构造成MIME格式,Node.js里有两种主流实现方式:用工具库简化操作,或者手动构造MIME内容。不管哪种方式,都需要把本地文件读取成二进制后转成base64编码——这是Gmail API对附件内容的硬性要求。
具体实现步骤(附代码示例)
先假设你已经通过googleapis库获取了授权的gmail客户端实例(比如完成了OAuth2授权流程)。
方式1:用Nodemailer + Gmail API(推荐,更简洁)
Nodemailer有专门适配Gmail API的传输器,处理附件超级省心,不用自己折腾MIME格式:
- 先安装依赖:
npm install nodemailer googleapis
- 完整代码示例:
const nodemailer = require('nodemailer'); const { google } = require('googleapis'); // 创建Gmail API传输器 const createTransporter = async () => { return nodemailer.createTransport({ service: 'gmail', auth: { type: 'OAuth2', user: '你的邮箱@gmail.com', clientId: '你的OAuth2客户端ID', clientSecret: '你的OAuth2客户端密钥', refreshToken: '你的刷新令牌', // accessToken可以不用手动传,transporter会自动刷新获取 } }); }; // 发送带附件的邮件 const sendEmailWithAttachment = async () => { const transporter = await createTransporter(); const mailOptions = { from: '你的名字 <你的邮箱@gmail.com>', to: '收件人邮箱@example.com', subject: '测试带附件的邮件', text: '这是一封带附件的测试邮件', attachments: [ // 方式1:直接指定本地文件路径 { filename: 'test.txt', path: './test.txt' }, // 方式2:读取文件内容后传入 { filename: '头像.jpg', content: fs.readFileSync('./avatar.jpg'), encoding: 'base64' } ] }; try { await transporter.sendMail(mailOptions); console.log('带附件的邮件发送成功啦!'); } catch (error) { console.error('发送失败:', error); } }; // 调用发送函数 sendEmailWithAttachment();
方式2:直接调用Gmail API的users.messages.send接口(手动构造MIME)
如果不想依赖Nodemailer,也可以手动构造MIME消息后发送:
- 安装辅助依赖:
npm install mime-types
- 完整代码示例:
const fs = require('fs'); const mime = require('mime-types'); const { google } = require('googleapis'); // 假设你已经有授权好的gmail客户端 const gmail = google.gmail({ version: 'v1', auth: 你的授权客户端实例 }); // 构造MIME格式的邮件内容 const createMimeMessage = (to, from, subject, text, attachments) => { const boundary = `----=_Part_${Date.now()}`; let mimeParts = [ `From: ${from}`, `To: ${to}`, `Subject: ${subject}`, 'MIME-Version: 1.0', `Content-Type: multipart/mixed; boundary="${boundary}"`, '', `--${boundary}`, 'Content-Type: text/plain; charset="UTF-8"', 'Content-Transfer-Encoding: 7bit', '', text, '' ]; // 逐个添加附件 attachments.forEach(attachment => { const fileContent = fs.readFileSync(attachment.path); const base64Content = fileContent.toString('base64'); const contentType = mime.lookup(attachment.path) || 'application/octet-stream'; mimeParts.push( `--${boundary}`, `Content-Type: ${contentType}; name="${attachment.filename}"`, `Content-Disposition: attachment; filename="${attachment.filename}"`, 'Content-Transfer-Encoding: base64', '', base64Content, '' ); }); mimeParts.push(`--${boundary}--`); return mimeParts.join('\n'); }; // 发送邮件 const sendEmail = async () => { const to = '收件人邮箱@example.com'; const from = '你的名字 <你的邮箱@gmail.com>'; const subject = '手动构造MIME带附件测试'; const text = '这是手动构造MIME格式的带附件邮件'; const attachments = [ { path: './report.pdf', filename: '月度报告.pdf' }, { path: './screenshot.png', filename: '界面截图.png' } ]; // 生成MIME消息并转成Gmail要求的base64编码(需要替换特殊字符) const mimeMessage = createMimeMessage(to, from, subject, text, attachments); const encodedMessage = Buffer.from(mimeMessage) .toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); try { await gmail.users.messages.send({ userId: 'me', // 'me'代表当前授权用户的邮箱 requestBody: { raw: encodedMessage } }); console.log('邮件发送成功!'); } catch (error) { console.error('发送失败:', error); } }; sendEmail();
常见问题排查
- 确认你的OAuth2授权范围包含
https://www.googleapis.com/auth/gmail.send(发送邮件)或者https://www.googleapis.com/auth/gmail.compose(创建草稿),没有足够权限会导致上传失败 - 检查本地文件路径是否正确,确保Node.js进程有读取该文件的权限
- Gmail普通邮件最大支持25MB附件,如果你的文件超过这个大小,需要使用**可恢复上传(resumable upload)**方案,不过一般中小附件用上面的方法就足够了
内容的提问来源于stack exchange,提问作者moxched
相关产品推荐
相关产品推荐

