如何通过Google Drive文件ID在Node.js中创建带附件的Gmail草稿
使用Gmail API和Drive API在Node.js中通过fileId创建带附件的邮件草稿(无需下载文件)
核心思路
Gmail API创建草稿需要Base64编码的原始MIME消息,要直接引用Drive文件作为附件且不落地本地文件,关键是通过Drive API获取文件的二进制流,实时进行Base64编码后嵌入MIME结构,跳过本地文件下载步骤。
代码实现
假设你已完成Google OAuth2客户端初始化(需包含https://www.googleapis.com/auth/gmail.compose和https://www.googleapis.com/auth/drive.readonly权限),以下是完整实现:
1. 依赖准备
先安装Google官方客户端库:
npm install googleapis
2. 初始化客户端与Drive文件流获取
const { google } = require('googleapis'); // 替换为你的OAuth2配置 const oauth2Client = new google.auth.OAuth2( 'YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET', 'YOUR_REDIRECT_URI' ); // 配置已获取的有效access_token(从认证流程或缓存中获取) oauth2Client.setCredentials({ access_token: 'YOUR_ACCESS_TOKEN' }); const drive = google.drive({ version: 'v3', auth: oauth2Client }); const gmail = google.gmail({ version: 'v1', auth: oauth2Client }); /** * 获取Drive文件的元数据与二进制流 * @param {string} fileId Drive文件ID * @returns {Promise<{name: string, mimeType: string, stream: Readable}>} */ async function getDriveFileStream(fileId) { // 获取文件名、MIME类型等元数据 const fileMeta = await drive.files.get({ fileId, fields: 'name, mimeType' }); // 获取文件二进制流 const fileStream = await drive.files.get({ fileId, alt: 'media' }, { responseType: 'stream' }); return { name: fileMeta.data.name, mimeType: fileMeta.data.mimeType, stream: fileStream.data }; }
3. 扩展createRawMessage函数,添加Drive附件
const { Transform } = require('stream'); const { Buffer } = require('buffer'); /** * 将二进制流直接转换为Base64字符串 * @param {Readable} stream 文件流 * @returns {Promise<string>} */ async function streamToBase64(stream) { return new Promise((resolve, reject) => { let base64Str = ''; const transform = new Transform({ transform(chunk, encoding, callback) { base64Str += chunk.toString('base64'); callback(); } }); stream.pipe(transform); transform.on('end', () => resolve(base64Str)); transform.on('error', reject); }); } /** * 创建包含Drive附件的原始MIME消息 * @param {string} to 收件人 * @param {string} subject 邮件主题 * @param {string} body 纯文本正文 * @param {Array<string>} driveFileIds Drive文件ID列表 * @returns {Promise<string>} URL安全的Base64编码消息 */ async function createRawMessageWithDriveAttachments(to, subject, body, driveFileIds) { const boundary = `----GMAIL_BOUNDARY_${Date.now()}`; // 构建邮件基础部分 let rawMessage = [ `To: ${to}`, `Subject: ${subject}`, `MIME-Version: 1.0`, `Content-Type: multipart/mixed; boundary="${boundary}"`, '', `--${boundary}`, `Content-Type: text/plain; charset="UTF-8"`, '', body, '' ].join('\r\n'); // 逐个处理Drive附件 for (const fileId of driveFileIds) { const { name, mimeType, stream } = await getDriveFileStream(fileId); const base64Content = await streamToBase64(stream); rawMessage += [ `--${boundary}`, `Content-Type: ${mimeType}`, `Content-Disposition: attachment; filename="${name}"`, `Content-Transfer-Encoding: base64`, '', base64Content, '' ].join('\r\n'); } // 结束MIME边界 rawMessage += `--${boundary}--`; // 转换为Gmail API要求的URL安全Base64编码 return Buffer.from(rawMessage).toString('base64url'); }
4. 创建带附件的邮件草稿
/** * 创建包含Drive附件的邮件草稿 * @param {string} userId 固定为'me'代表当前用户 * @param {string} to 收件人邮箱 * @param {string} subject 邮件主题 * @param {string} body 邮件正文 * @param {Array<string>} driveFileIds Drive文件ID列表 */ async function createDraftWithDriveAttachments(userId, to, subject, body, driveFileIds) { const raw = await createRawMessageWithDriveAttachments(to, subject, body, driveFileIds); const response = await gmail.users.drafts.create({ userId, requestBody: { message: { raw } } }); console.log('草稿创建成功,ID:', response.data.id); return response.data; } // 调用示例 createDraftWithDriveAttachments( 'me', 'recipient@example.com', '带Drive附件的测试邮件', '这是一封包含Drive文件附件的邮件草稿', ['YOUR_DRIVE_FILE_ID'] ).catch(err => console.error('创建草稿失败:', err));
关键说明
- 无本地文件落地:通过Drive API流式获取文件内容,直接转换为Base64嵌入MIME消息,完全跳过本地文件存储步骤。
- 权限要求:必须确保OAuth2客户端已申请
gmail.compose(创建草稿权限)和drive.readonly(读取Drive文件权限),否则会触发权限错误。 - MIME格式合规:严格按照RFC标准构建多部分MIME消息,兼容Gmail API的解析要求。
与Google Apps Script的差异
Apps Script中GmailApp.createDraft可以直接传入Drive文件对象,是因为Google内部封装了MIME消息构建和文件流处理逻辑。Node.js中需要手动构建MIME结构,但通过流式处理可以实现完全一致的“无需下载文件”效果。
内容的提问来源于stack exchange,提问作者Deep Trikannad
相关产品推荐
相关产品推荐

