首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >附件不起作用的Node.js Gmail API草稿

我正在尝试使用Gmail API在Node.js中创建一个简单的带有PDF附件的草稿。草稿被创建并在Gmail中显示,但它没有附件。此外,当在Gmail中点击草稿时,它会打开一个没有标题或内容的空草稿。当我尝试使用几乎相同的代码发送电子邮件时,它工作得很好。

这是我的代码:

代码语言:javascript
运行
AI代码解释
复制
const createMailEncodedMessage = async (params) => {
    const msg = await buildMailBody(params)

    // The body needs to be base64url encoded.
    const encodedMessage = Buffer.from(msg)
        .toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=+$/, '')

    return encodedMessage
}

const sendEmail = async (params) => {
    if (!auth) {
        await init()
    }

    const encodedMessage = await createMailEncodedMessage(params)
    return await gmail.users.messages.send({
        userId: 'me',
        requestBody: {
            raw: encodedMessage,
        },
    })
}

const createDraft = async (params) => {
    if (!auth) {
        await init()
    }

    const encodedMessage = await createMailEncodedMessage(params)

    return await gmail.users.drafts.create({
        userId: 'me',
        requestBody: {
            message: {
                raw: encodedMessage,
            }
        }
    })
}

const buildMailBody = ({ from, to, subject, body, attachments }) => {
    return new Promise((resolve, reject) => {
        let mail = new MailComposer({
            from,
            to,
            //text: 'I hope this works',
            html: body,
            subject,
            textEncoding: 'base64',
            attachments: attachments?.map(a => ({
                filename: a.fileName,
                content: fs.createReadStream(a.filePath),
            })),
        })

        mail.compile().build((error, msg) => {
            if (error) {
                reject(error)
            }

            resolve(msg)
        })
    })
}
EN

回答 1

Stack Overflow用户

发布于 2021-08-11 01:09:41

在回顾了这个问题之后,我开发了一个代码,您可以使用它来实现您的目标。此脚本将发送一封带有两个示例附件的users.messages.send电子邮件。我使用quickstart中描述的凭据流来管理令牌和作用域。请记住,您将需要一个方法来处理电子邮件MIME类型和base64转换。为了制作一个工作示例,我使用了MailComposer库来控制MIME类型。以下脚本应按原样工作,您只需设置凭据以使其运行(您可以使用快速入门中描述的步骤):

代码语言:javascript
运行
AI代码解释
复制
const fs = require('fs');
const readline = require('readline');
const {
  google
} = require('googleapis');
const MailComposer = require('nodemailer/lib/mail-composer');
const SCOPES = ['https://mail.google.com/'];
const TOKEN_PATH = 'token.json';

fs.readFile('credentials.json', (err, content) => {
  if (err) return console.log('Error loading client secret file:', err);
  authorize(JSON.parse(content), sendEmailWithAttachments);
});

function authorize(credentials, callback) {
  const {
    client_secret,
    client_id,
    redirect_uris
  } = credentials.installed;
  const oAuth2Client = new google.auth.OAuth2(
    client_id, client_secret, redirect_uris[0]);

  fs.readFile(TOKEN_PATH, (err, token) => {
    if (err) return getNewToken(oAuth2Client, callback);
    oAuth2Client.setCredentials(JSON.parse(token));
    callback(oAuth2Client);
  });
}

function getNewToken(oAuth2Client, callback) {
  const authUrl = oAuth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: SCOPES,
  });
  console.log('Authorize this app by visiting this url:', authUrl);
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  rl.question('Enter the code from that page here: ', (code) => {
    rl.close();
    oAuth2Client.getToken(code, (err, token) => {
      if (err) return console.error('Error retrieving access token',
        err);
      oAuth2Client.setCredentials(token);
      fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
        if (err) return console.error(err);
        console.log('Token stored to', TOKEN_PATH);
      });
      callback(oAuth2Client);
    });
  });
}

function sendEmailWithAttachments(auth) {
  let mail = new MailComposer({
    to: "{ RECIPIENT EMAIL }",
    text: "Morbi imperdiet gravida leo in commodo.",
    html: "Morbi <i>imperdiet</i> gravida <b>leo</b> in commodo.",
    subject: "Donec et porttitor erat",
    textEncoding: "base64",
    attachments: [{
        filename: 'attachment1.txt',
        content: 'UHJhZXNlbnQgc2VtcGVyIGF1Z3VlIHV0IGJpYmVuZHVtIHVsbGFtY29ycGVyLiBOdW5jIGluIG1hdXJpcyB1dCBxdWFtIHRyaXN0aXF1ZSBwcmV0aXVtIHF1aXMgZXQgbWkuIER1aXMgZW5pbSBsZW8sIGltcGVyZGlldCBxdWlzIHVybmEgZXUsIHBsYWNlcmF0IGZpbmlidXMgcXVhbS4gRXRpYW0gbWFzc2EgbG9yZW0sIHJ1dHJ1bSB2ZWwgc29kYWxlcyBhYywgYWNjdW1zYW4gZXQgcHVydXMuIFV0IG5lYyBsb3JlbSBpbnRlcmR1bSwgYWxpcXVhbSBuaXNpIGVnZXN0YXMsIGVnZXN0YXMgZWxpdC4gSW50ZWdlciB2ZWwgb3JuYXJlIGVyb3MsIGVnZXQgbGFjaW5pYSB2ZWxpdC4gRXRpYW0gZGlhbSBzZW0sIGFsaXF1YW0gYSBzb2xsaWNpdHVkaW4gdml0YWUsIHBvcnRhIGFjIGVsaXQuIEludGVyZHVtIGV0IG1hbGVzdWFkYSBmYW1lcyBhYyBhbnRlIGlwc3VtIHByaW1pcyBpbiBmYXVjaWJ1cy4gU3VzcGVuZGlzc2UgbmVjIGltcGVyZGlldCB1cm5hLiBTdXNwZW5kaXNzZSBhIGVzdCB1bHRyaWNpZXMsIHZlbmVuYXRpcyB1cm5hIGlkLCBzY2VsZXJpc3F1ZSBwdXJ1cy4gQWVuZWFuIHN1c2NpcGl0IGxhY3VzIHNlbSwgYXQgZWdlc3RhcyBhbnRlIGFsaXF1YW0gYXQu',
        encoding: 'base64'
      },
      {
        filename: 'attachment2.txt',
        content: 'VmVzdGlidWx1bSBwdWx2aW5hciBzZW1wZXIgY29udmFsbGlzLiBPcmNpIHZhcml1cyBuYXRvcXVlIHBlbmF0aWJ1cyBldCBtYWduaXMgZGlzIHBhcnR1cmllbnQgbW9udGVzLCBuYXNjZXR1ciByaWRpY3VsdXMgbXVzLiBNYWVjZW5hcyBvcm5hcmUganVzdG8gc2VkIGFyY3UgaWFjdWxpcyBlZmZpY2l0dXIuIEZ1c2NlIHJob25jdXMsIGVzdCBmaW5pYnVzIGRpZ25pc3NpbSB2YXJpdXMsIHNhcGllbiB0dXJwaXMgcGxhY2VyYXQgcmlzdXMsIHNpdCBhbWV0IGZpbmlidXMgbmliaCBmZWxpcyBldSBsYWN1cy4gUHJvaW4gZWxlbWVudHVtLCBlcmF0IGEgYXVjdG9yIGx1Y3R1cywgcmlzdXMgb2RpbyBmcmluZ2lsbGEgcmlzdXMsIGlkIGNvbW1vZG8gbG9yZW0gdmVsaXQgaWQgbnVuYy4gRnVzY2Ugc2VkIHB1bHZpbmFyIG5pc2wsIGlkIGx1Y3R1cyBlcmF0LiBNYWVjZW5hcyBuZWMgY29uZGltZW50dW0gZmVsaXMuIE51bmMgZWxlbWVudHVtLCBqdXN0byBhIHZvbHV0cGF0IGJsYW5kaXQsIG1hZ25hIGlwc3VtIHBvcnRhIGFudGUsIHF1aXMgYmliZW5kdW0gbGVjdHVzIG9yY2kgdXQgbWF1cmlzLiBGdXNjZSBwdWx2aW5hciBmZWxpcyBhdCBudW5jIGNvbnNlY3RldHVyIGRpY3R1bS4gRXRpYW0gdmFyaXVzLCB0dXJwaXMgdGluY2lkdW50IHByZXRpdW0gcnV0cnVtLCBtZXR1cyBtYXVyaXMgbW9sZXN0aWUgZXgsIG5lYyBldWlzbW9kIGVuaW0ganVzdG8gYXQgZXN0Lg',
        encoding: 'base64'
      },
    ]
  });
  
  mail.compile().build((error, msg) => {
    if (error) return console.log('ERROR - ' + error);
    const encodedMessage = Buffer.from(msg).toString('base64').replace(
      /\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
    const gmail = google.gmail({
      version: 'v1',
      auth
    });
    gmail.users.messages.send({
      userId: 'me',
      resource: {
        raw: encodedMessage,
      }
    }, (err, result) => {
      if (err) return console.log('ERROR: ' + err);
      console.log("Email sent: ", result.data);
    });
  })
}

该脚本分两个步骤工作。首先,它使用该库构建与标准MIME类型兼容的电子邮件。其次,它使用先前构建的电子邮件调用Gmail API。如果邮件发送成功,接口会返回邮件的ID和标签。如有疑问,请留言澄清。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68426653

复制
相关文章
C++ GPU && CPU
1 #include <amp.h> 2 3 #include <iostream> 4 5 #include <winbase.h> //操作系统的底层文件 6 7 8 9 using namespace concurrency; 10 11 using namespace std; 12 13 14 15 void main () { 16 17 18 19 20 21 int a [] = {1 ,2, 3,4 ,5, 6
Gxjun
2018/03/26
7390
PyTorch 1.7 发布! 支持CUDA 11,Windows 分布式训练,以及FFT新API
今天,我们正式发布 PyTorch 1.7,以及升级的域库。PyTorch 1.7版本包括了一些新的 API,比如对兼容 numpy 的 FFT 操作的支持、性能分析工具以及对分布式数据并行(DDP)和基于远程过程调用(RPC)的分布式训练的重要更新。此外,还有一些特性移到了 stable 状态,包括自定义 C++ 类、内存分析器、通过自定义类张量对象实现的扩展、 RPC 中的用户异步函数以及 torch.distributed 中的其他一些特性,如 Per-RPC 超时、 DDP dynamic bucketing 和 RRef helper。
McGL
2020/10/30
1.1K0
[开发技巧]·PyTorch如何使用GPU加速(CPU与GPU数据的相互转换)
在进行深度学习开发时,GPU加速可以提升我们开发的效率,速度的对比可以参照笔者这篇博文:[深度应用]·主流深度学习硬件速度对比(CPU,GPU,TPU)结论:通过对比看出相较于普通比较笔记本的(i5 8250u)CPU,一个入门级显卡(GPU MX150)可以提升8倍左右的速度,而高性能的显卡(GPU GTX1080ti)可以提升80倍的速度,如果采用多个GPU将会获得更快速度,所以经常用于训练的话还是建议使用GPU。
小宋是呢
2019/06/27
35.5K1
PyTorch 1.5上线:加入稳定C++前端,高级自动梯度API
今天,PyTorch 1.5 宣布上线,此版本主要包括几个新的 API 的添加和改进。新版 PyTorch 包括对 C++前端的重大更新,用于计算机视觉模型的「channels last」存储格式,以及用于模型并行训练的分布式 RPC 框架的稳定版本。该版本还提供了针对自动求导机制中黑塞和雅可比的新 API,以及受 pybind 启发,允许用户创建自定义 C++类的一个 API。另外,torch_xla 已可在 PyTorch 1.5 版中使用,并在 1.5 版本中进行了测试,可提供成熟的 Cloud TPU 体验。
机器之心
2020/04/23
5660
PyTorch 1.7来了:支持Windows上的分布式训练,还有大波API袭来
据Facebook 官方博客公告,PyTorch1.7版本已经于昨日正式发布,相比于以往的 PyTorch 版本,此次更新除了增加了更多的API,还能够支持 NumPy兼容下的傅里叶变换、性能分析工具,以及对基于分布式数据并行(DDP)和远程过程调用(RPC)的分布式训练。
AI科技评论
2020/11/06
1.3K0
PyTorch 1.7来了:支持Windows上的分布式训练,还有大波API袭来
PyTorch 1.7来了:支持Windows上的分布式训练,还有大波API袭来
据Facebook 官方博客公告,PyTorch1.7版本已经于昨日正式发布,相比于以往的 PyTorch 版本,此次更新除了增加了更多的API,还能够支持 NumPy兼容下的傅里叶变换、性能分析工具,以及对基于分布式数据并行(DDP)和远程过程调用(RPC)的分布式训练。
AI算法与图像处理
2020/11/06
1.2K0
PyTorch 1.7来了:支持Windows上的分布式训练,还有大波API袭来
[源码解析] PyTorch 如何使用GPU
在 PyTorch DataParallel 训练过程中,其会在多个GPU之上复制模型副本,然后才开始训练。笔者在分析过程中,发现如果不把一些GPU相关基础知识整理出来,很难理解DataParallel的这个复制模型的过程,遂有此文。
罗西的思考
2021/11/10
3.4K0
GPU VS CPU
安装TensorFlow GPU版本 !pip install tensorflow-gpu Collecting tensorflow-gpu [?25l Downloading https://
用户3577892
2020/06/11
5560
PyTorch 2.0 重磅发布:编译、编译、还是编译!
内容一览:昨晚召开的 PyTorch Conference 2022 中,官方正式发布了 PyTorch 2.0。本文将梳理 PyTorch 2.0 与 1.x 相比的最大差异。
HyperAI超神经
2023/02/27
1.5K0
PyTorch 2.0 重磅发布:编译、编译、还是编译!
PyTorch 1.12发布,正式支持苹果M1芯片GPU加速,修复众多Bug
点击上方↑↑↑“OpenCV学堂”关注我来源:公众号 机器之心  授权 PyTorch 1.12 正式发布,还没有更新的小伙伴可以更新了。 距离 PyTorch 1.11 推出没几个月,PyTorch 1.12 就来了!此版本由 1.11 版本以来的 3124 多次 commits 组成,由 433 位贡献者完成。1.12 版本进行了重大改进,并修复了很多 Bug。 随着新版本的发布,大家讨论最多的可能就是 PyTorch 1.12 支持苹果 M1 芯片。 其实早在今年 5 月,PyTorch 官方就已经
OpenCV学堂
2022/07/04
9150
PyTorch 1.12发布,正式支持苹果M1芯片GPU加速,修复众多Bug
开发 | 用PyTorch还是TensorFlow?斯坦福大学CS博士生带来全面解答
AI 科技评论按:关于深度学习的框架之争一直没有停止过。PyTorch,TensorFlow,Caffe还是Keras ?近日, 斯坦福大学计算机科学博士生Awni Hannun就发表了一篇文章,对比当前两个主流框架PyTorch和TensorFlow。 AI 科技评论编译如下: 这篇指南是我目前发现的PyTorch和TensorFlow之间的主要差异。写这篇文章的目的是想帮助那些想要开始新项目或者转换深度学习框架的人进行选择。文中重点考虑训练和部署深度学习堆栈组件时框架的可编程性和灵活性。我不会权衡速度、
AI科技评论
2018/03/13
1.8K0
PyTorch 1.0 中文官方教程:使用 PyTorch C++ 前端
PyTorch C++ 前端 是PyTorch机器学习框架的一个纯C++接口。PyTorch的主接口是Python,Python API位于一个基础的C++代码库之上,提供了基本的数据结构和功能,例如张量和自动求导。C++前端暴露了一个纯的C++11的API,在C++底层代码库之上扩展了机器学习训练和推理所需的工具扩展。这包括用于神经网络建模的内置组件集合;扩展此集合的自定义模块API;流行的优化算法库(如随机梯度下降);使用API定义和加载数据集的并行数据加载程序;序列化例行程序等等。
ApacheCN_飞龙
2022/05/07
6750
PyTorch如何加速数据并行训练?分布式秘籍大揭秘
在芯片性能提升有限的今天,分布式训练成为了应对超大规模数据集和模型的主要方法。本文将向你介绍流行深度学习框架 PyTorch 最新版本( v1.5)的分布式数据并行包的设计、实现和评估。
机器之心
2020/07/14
1.1K0
PyTorch如何加速数据并行训练?分布式秘籍大揭秘
清华自研深度学习框架「计图」开源!多项任务性能超过PyTorch
刚刚,清华自研的深度学习框架,正式对外开源。“贵系”计算机系的图形实验室出品,取名Jittor,中文名计图。
量子位
2020/03/31
4870
清华自研深度学习框架「计图」开源!多项任务性能超过PyTorch
PyTorch如何加速数据并行训练?分布式秘籍大揭秘
在芯片性能提升有限的今天,分布式训练成为了应对超大规模数据集和模型的主要方法。本文将向你介绍流行深度学习框架 PyTorch 最新版本( v1.5)的分布式数据并行包的设计、实现和评估。
CV君
2020/07/17
9340
PyTorch如何加速数据并行训练?分布式秘籍大揭秘
PyTorch如何加速数据并行训练?分布式秘籍大揭秘
在芯片性能提升有限的今天,分布式训练成为了应对超大规模数据集和模型的主要方法。本文将向你介绍流行深度学习框架 PyTorch 最新版本( v1.5)的分布式数据并行包的设计、实现和评估。
代码医生工作室
2020/07/17
9030
PyTorch如何加速数据并行训练?分布式秘籍大揭秘
Pytorch 最全入门介绍,Pytorch入门看这一篇就够了
本文通过详细且实践性的方式介绍了 PyTorch 的使用,包括环境安装、基础知识、张量操作、自动求导机制、神经网络创建、数据处理、模型训练、测试以及模型的保存和加载。
TechLead
2023/10/21
6.5K0
Pytorch 最全入门介绍,Pytorch入门看这一篇就够了
在 Python 中将数值变量转换为分类变量
这篇文章是今天发布的CTGAN的补充,我们可以使用pandas的cut函数将数据进行离散化、将连续变量进行分段汇总,这比写自定义函数要简单的多。
deephub
2021/11/16
2.2K0
Python中将字典转为成员变量
当我们在Python中写一个class时,如果有一部分的成员变量需要用一个字典来命名和赋值,此时应该如何操作呢?这个场景最常见于从一个文件(比如json、npz之类的文件)中读取字典变量到内存当中,再赋值给一个类的成员变量,或者已经生成的实例变量。
DechinPhy
2022/05/10
1.4K0
点击加载更多

相似问题

如何在pytorch中从gpu返回cpu?

340

PyTorch (GPU)比CPU慢

13

在Pytorch中从GPU/CPU中删除模型

10

Pytorch CPU和GPU并行运行

115

Pytorch-GPU我忘了把什么移到GPU上?

294
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文