You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Gmail的multipart/related内容转为HTML或PDF?附API调用示例

处理Gmail Multipart/Related内容转HTML/PDF,及简化获取方案

嘿,我来帮你搞定这个Gmail API的邮件内容处理问题!结合你用gmail.users.threads.get({ format: 'full' })获取线程的代码,我分步骤给你拆解解决方案:

一、把Multipart/Related格式转成可用的HTML

Multipart/Related类型的邮件结构其实是把HTML内容和内嵌资源(比如图片、内嵌样式)打包在一起的,资源通过cid:前缀的链接引用。你可以按下面的步骤提取并处理:

  1. 定位并解码HTML主体部分
    首先得从线程的消息里找到text/html类型的内容块,因为邮件可能嵌套多层parts,所以用递归查找更靠谱:

    // 从返回的线程数据里取第一条消息(一般就是主邮件)
    const targetMessage = full.data.messages[0];
    const payload = targetMessage.payload;
    
    // 递归查找text/html类型的part
    function getHtmlPart(part) {
      if (part.mimeType === 'text/html') return part;
      if (part.parts) {
        for (const subPart of part.parts) {
          const found = getHtmlPart(subPart);
          if (found) return found;
        }
      }
      return null;
    }
    
    const htmlPart = getHtmlPart(payload);
    if (!htmlPart) {
      // fallback:如果没有HTML,把纯文本转成简单HTML
      const textPart = payload.parts.find(p => p.mimeType === 'text/plain');
      if (textPart) {
        const plainText = Buffer.from(textPart.body.data, 'base64').toString('utf-8');
        const html = plainText.replace(/\n/g, '<br>').replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;');
        // 这里拿到的html可以直接用或者转PDF
      }
      return;
    }
    
    // 解码base64的HTML内容
    let finalHtml = Buffer.from(htmlPart.body.data, 'base64').toString('utf-8');
    
  2. 替换内嵌资源的CID引用
    邮件里的图片都是用cid:xxx引用的,浏览器没法直接识别,所以我们把这些资源转成base64内嵌到HTML里:

    // 收集所有带content-id的内嵌资源(比如图片)
    const inlineAssets = [];
    function collectInlineParts(part) {
      if (part.mimeType.startsWith('image/') && part.headers) {
        const contentId = part.headers.find(h => h.name.toLowerCase() === 'content-id');
        if (contentId) {
          // 去掉CID前后的<>符号
          const cid = contentId.value.replace(/[<>]/g, '');
          inlineAssets.push({
            cid,
            base64Data: part.body.data,
            mimeType: part.mimeType
          });
        }
      }
      if (part.parts) part.parts.forEach(collectInlineParts);
    }
    
    collectInlineParts(payload);
    
    // 把HTML里的cid:xxx替换成base64数据URL
    inlineAssets.forEach(asset => {
      const dataUrl = `data:${asset.mimeType};base64,${asset.base64Data}`;
      finalHtml = finalHtml.replace(new RegExp(`cid:${asset.cid}`, 'g'), dataUrl);
    });
    
    // 现在finalHtml就是可以直接在浏览器打开的完整HTML了
    

二、把HTML转成PDF

要把HTML转成PDF,首推puppeteer——它基于Chrome无头浏览器,能完美渲染复杂的HTML和CSS,比轻量库靠谱得多:

  1. 先装依赖:

    npm install puppeteer
    
  2. 然后写转换代码:

    const puppeteer = require('puppeteer');
    const fs = require('fs').promises;
    
    async function convertHtmlToPdf(htmlContent) {
      const browser = await puppeteer.launch({ headless: 'new' });
      const page = await browser.newPage();
      await page.setContent(htmlContent, { waitUntil: 'networkidle0' }); // 等资源加载完
      const pdfBuffer = await page.pdf({
        format: 'A4',
        printBackground: true // 要渲染背景色的话开这个
      });
      await browser.close();
      return pdfBuffer;
    }
    
    // 调用示例:把刚才的finalHtml转成PDF并保存
    const pdf = await convertHtmlToPdf(finalHtml);
    await fs.writeFile('email_output.pdf', pdf);
    

如果你的邮件HTML很简单,也可以用html-pdf库,它更轻量,但复杂样式可能渲染崩,按需选择就行。

三、更简便的Gmail内容获取方式

你现在用format: 'full'需要手动解析multipart结构,其实有更省心的办法:

  • 用第三方解析库自动处理:比如gmail-api-parse-message或者mailparser,这些库能帮你跳过手动遍历parts的步骤,直接拿到处理好的HTML:
    举个mailparser的例子,配合format: 'raw'使用:

    const { simpleParser } = require('mailparser');
    
    // 用raw格式获取完整邮件内容
    const rawThread = await gmail.users.threads.get({
      userId,
      id: firstThread.id,
      format: 'raw'
    });
    
    // 解码base64的原始邮件并解析
    const decodedRaw = Buffer.from(rawThread.data.raw, 'base64').toString('utf-8');
    const parsedEmail = await simpleParser(decodedRaw);
    
    // 直接拿到处理好的HTML(已经替换了内嵌资源)
    const readyHtml = parsedEmail.html;
    

    这种方式完全不用自己处理multipart结构,库会帮你搞定所有细节,非常适合快速开发。

  • 如果只需要纯文本:可以用format: 'minimal'或者format: 'metadata',但你要HTML/PDF的话,上面的raw+mailparser方案最省事。


内容的提问来源于stack exchange,提问作者Sibelius Seraphini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:23:44