使用 Google Cloud Functions 让您的 Gmail 收件箱更加强大

1. 简介

数十亿企业和个人都在使用 Gmail 和其他 G Suite 服务通信和处理数据。Google 提供的 G Suite API 可帮助您以编程方式访问这些服务中的信息,而您可以使用这些 API 轻松实现日常工作流程的自动化。在本实验中,您将构建一个功能强大的 Gmail 扩展程序,它能自动对收到的邮件中的电子邮件进行分类,并将这些类别保存到 Google 表格中。此扩展程序将使用 G Suite 的 RESTful API、Google Cloud Functions 和其他 Google Cloud Platform 服务。

构建内容

在本实验中,您将构建和部署一些关联到 G Suite API 和其他 Google Cloud Platform 服务的 Cloud Functions 函数。这些函数将:

  • 授权安全访问 Gmail 和 Google 表格数据
  • 提取收到的所有邮件中附加的图片
  • 使用 Cloud Vision API 对这些图片进行分类
  • 将这些类别、发件人地址和附件名称写入 Google 表格

学习内容

  • G Suite RESTful API 基础知识
  • Google Cloud Functions 和其他 Google Cloud Platform 服务的基础知识
  • 如何使用 Google Cloud Functions 以编程方式访问 Gmail

所需条件

  • 拥有 Gmail 和 Google 表格访问权限的 Google 账号。如果没有,请点击此处创建一个
  • 具备 JavaScript/Node.js 的基础知识。

2. 要事第一

启用 API

在本实验中,您将使用以下 Google 产品/服务:

  • Google Cloud Functions
  • Google Cloud Pub/Sub
  • Google Cloud Vision API
  • Google Cloud Datastore
  • Gmail API
  • Google Sheets API

Google Cloud Functions

Google Cloud Functions 是 Google 的无服务器函数即服务平台,可让您以简单、可扩缩的方式运行各个代码段(“函数”)。

如需启用 Google Cloud Functions,请点击屏幕左上角的汉堡形菜单,打开左侧导航边栏:

f457988e33594bb6.png

在导航菜单中找到 Cloud Functions 并点击它。点击启用 API,在项目中启用 Google Cloud Functions。

Google Cloud Pub/Sub

Google Cloud Pub/Sub 简单且可扩缩,可为数据流和事件传送奠定基础。在本实验中,它将充当 Gmail 和 Google Cloud Functions 之间的快递服务。

要启用 Google Cloud Pub/Sub,请打开左侧导航边栏,找到 Pub/Sub,然后点击它。点击启用 API,在项目中启用 Google Cloud Pub/Sub。

Google Cloud Datastore

Google Cloud Datastore 是一个可扩缩的分布式无服务器数据库。

要启用 Google Cloud Datastore,请在左侧导航边栏中找到 Datastore 并点击它。在新页面中,点击 Select Datastore Mode

98012c91fd4080d4

在本实验中,您可以使用任何数据库位置。点击创建数据库以启用 Google Cloud Datastore;可能需要几分钟才能完成。

Google Cloud Vision

Google Cloud Vision API 是一项强大的机器学习服务,使用预训练模型从图片中提取实用信息。

请参阅以下说明,了解如何启用 Google Cloud Vision API。

启用 Gmail API、Google Sheets API 和 Google Cloud Vision API

再次打开左侧的导航边栏,找到 APIs & &服务。点击。在搜索 API 和服务字段中,输入 Gmail。在搜索结果中,选择 Gmail API,然后点击启用

返回“API 库”页面。搜索 Google Sheets API 并启用它。

重复此过程。搜索并启用 Cloud Vision API

打开 Google Cloud Shell

在本实验中,您将使用 Google Cloud Shell 执行大多数操作。Cloud Shell 让您可以直接在浏览器中通过命令行访问 Google Cloud Platform 资源,无需使用本地机器即可管理这些资源。

如需打开 Google Cloud Shell,请点击顶部蓝色水平栏上的激活 Cloud Shell 按钮:

fd5c2925ca9cdfdd.png

屏幕底部会显示一个新面板:

34f498402e910802

点击启动代码编辑器按钮以启动 Cloud Shell 代码编辑器:

10f8631ef48bed22

Cloud Shell 代码编辑器将在新窗口中打开。

下载代码

在 Cloud Shell 中运行以下命令以克隆项目:

git clone https://github.com/googlecodelabs/gcf-gmail-codelab.git

cd gcf-gmail-codelab

您应该会看到一个新文件夹 gcf-gmail-codelab,它出现在 Cloud Shell 代码编辑器中。

3. 架构概览

本实验的工作流程如下:

79c5d3e43f674b33

  1. 用户设置 Gmail 推送通知:每当有新邮件到达收件箱时,Gmail 都会向 Cloud Pub/Sub 发送通知。
  2. Cloud Pub/Sub 向 Google Cloud Functions 传递新消息通知。
  3. 收到新邮件通知后,Cloud Functions 实例会连接到 Gmail 并检索新邮件。
  4. 如果邮件包含图片作为附件,Cloud Functions 实例会调用 Cloud Vision API 来分析附件。
  5. Cloud Functions 实例会更新您选择的 Google 表格,指定邮件的发件人以及附件的下载位置。

4. 授予对 Gmail 的访问权限

在设置 Cloud Functions 函数以自动阅读您的电子邮件之前,您必须先授予该函数访问 Gmail 的权限。您需要向 Google 注册一个 OAuth 客户端,并创建一个关联的客户端 ID。

注册 OAuth 客户端

在 Google Cloud 控制台的左侧导航菜单中,找到 API 和服务。点击 OAuth 同意屏幕

91b2a3bac30bb2c5

Application name 字段中输入一个名称,例如 GCF + Gmail Codelab。保持其他设置不变,向下滚动页面,然后点击保存

创建关联的客户端 ID

切换到凭据标签页。点击创建凭据,然后选择 OAuth 客户端 ID。选择 Web 应用类型,并为其命名(您可以在此处再次使用 GCF + Gmail Codelab),然后点击创建。暂时将“限制”字段留空。

记下弹出式窗口中返回的客户端 ID 和客户端密钥。您可以点击页面上客户的名称再次查看这些值:

1160d8027ea52d90

执行授权流程

在示例代码中,auth/index.js 指定了 auth_initauth_callback 这两个 Cloud Functions 函数,这两个函数使用您刚刚创建的客户端 ID 和客户端密钥协同执行授权流程。

如需检查代码,请在 Cloud Shell 代码编辑器中打开 auth/index.js

授权流程会返回两种类型的令牌:访问令牌和刷新令牌。

  • 访问令牌是短期的身份证明,可授权拥有令牌的任何人访问您的数据;auth_callback 将其保存在 Cloud Datastore 中。
  • 刷新令牌用于获取新的访问令牌,有效期显著更长。

通常,令牌会进行加密和/或与访问令牌分开存储。

在 Cloud Shell 代码编辑器中修改 auth/env_vars.yaml。将 YOUR-GOOGLE-CLIENT-IDYOUR-GOOGLE-CLIENT-SECRET 替换为您自己的值。如需了解详情,请参阅上一步。暂时保持 YOUR-GOOGLE-CLIENT-CALLBACK-URLYOUR-PUBSUB-TOPIC 的值不变。

a2b4853c39a78bc6.png

修改 auth/env_vars.yaml 后,在 Cloud Shell 中运行以下命令以部署 Cloud Functions:

cd ~
cd gcf-gmail-codelab/auth

# Deploy Cloud Function auth_init
gcloud functions deploy auth_init --runtime=nodejs8 --trigger-http --env-vars-file=env_vars.yaml

# Deploy Cloud Function auth_callback
gcloud functions deploy auth_callback --runtime=nodejs8 --trigger-http --env-vars-file=env_vars.yaml

部署 Cloud Functions 函数可能需要几分钟时间。如果出现提示,请授予 Cloud SDK 安装 Beta 版命令的权限。

接下来,转到 Google Cloud 控制台,然后点击左侧导航菜单中的 Cloud Functions。点击 Cloud Functions 列表中的 auth_callback,然后切换到触发器标签页。

cb094bd341f9b299.png

45678a327c80e0f1

复制该网页上的网址。返回 Cloud Functions 页面,点击 Cloud Functions 列表中的 auth_init。在常规标签页中,点击修改。点击环境变量、网络、超时等,然后将 GOOGLE_CALLBACK_URL 的值替换为您刚复制的网址。

939ca3bd38047282

点击部署以应用更改。重复此过程并更新 auth_callback

最后,打开左侧导航菜单,点击API 和服务 >域名验证。如需添加已获授权的网域,请点击添加网域。例如,如果您先前复制的网址类似于

https://us-central1-my-project.cloudfunctions.net/auth_callback

您应将以下内容添加为已获授权的网域:

us-central1-my-project.cloudfunctions.net

添加网域进行确认。

4348748f232ceb87

返回凭据页面。点击 OAuth 客户端的名称,然后将您复制的网址添加为已获授权的重定向 URI。按 Enter 键进行确认。

从网址中移除 /auth_callback 部分,然后将其余部分添加为已获授权的 JavaScript 来源。例如,如果您的网址如下所示

https://us-central1-my-project.cloudfunctions.net/auth_callback

您应将以下内容添加为来源:

https://us-central1-my-project.cloudfunctions.net/

159bad719432582c.png

Enter 键确认,然后点击保存以应用更改。

5. 设置 Gmail 推送通知

如果授权流程成功,auth_callback 会自动调用 Gmail API 来设置推送通知。

为了接收 Gmail 推送通知,您必须创建一个 Pub/Sub 主题。当 Gmail 收到消息通知时,该主题的所有订阅者都会自动收到这些通知。

如需创建 Pub/Sub 主题,请转到 Google Cloud Console,然后点击 Pub/Sub >主题。点击创建主题。输入主题名称,例如 gmail-watch,然后点击创建。此外,您必须授予 Gmail 向 Pub/Sub 主题发送消息的权限:点击您刚刚创建的主题的上下文菜单(三个垂直排列的点),然后选择权限;点击添加成员,将 gmail-api-push@system.gserviceaccount.com 指定为新成员,然后为其指定角色 Pub/Sub >Pub/Sub 发布者;最后,点击保存以应用更改。

更新 Cloud Functions 函数 auth_callback 以指定要使用的 Pub/Sub 主题。点击左侧导航菜单中的 Cloud Functions,然后在 Cloud Functions 列表中选择 auth_callback。在常规标签页中,点击修改。点击更多,然后将 PUBSUB_TOPIC 的值替换为您刚刚创建的 Pub/Sub 主题的名称。点击保存以应用更改。

现在,您可以授权和设置 Gmail 推送通知了。等待新更改完成,然后返回 Cloud Functions 页面,在 Cloud Functions 列表中选择 auth_init,然后切换到触发器标签页。点击该网址,系统会将您重定向至使用 Google 账号登录页面:

348ab0a7e0c9cd03

使用您拥有的 Gmail 账号登录。任何递送至账号收件箱的新邮件都会触发推送通知。登录后,您将看到以下页面:

cfdad62fd02de004.png

点击允许以授予访问权限。auth_callback 会完成授权流程、保存访问令牌,并为您设置 Gmail 推送通知。此过程完成后,您应该会在浏览器中看到 Successfully set up Gmail push notifications 消息。

此 Codelab 使用 @google-cloud/express-oauth2-handlers 软件包为您自动执行授权工作流。如需了解详情,请参阅 GitHub 上的代码库

6. 处理传入消息

如前所述,当您的收件箱收到新邮件时,您创建的 Pub/Sub 主题的任何订阅者都会收到通知。pubsub/index.js 会指定一个 Cloud Functions 函数 watchGmailMessages,在部署为主题的订阅者后,该函数会读取新消息、对附加的图片进行分类,并将这些类别导出到 Google 表格。

如需检查代码,请在 Cloud Shell 代码编辑器中打开 pubsub/index.js

检索邮件

Gmail 推送通知包含与通知关联的电子邮件地址以及历史记录 ID。为简单起见,在此 Codelab 中,您只需在收到推送通知时向 Gmail API 请求最新消息;如想获得更好的结果,请改用历史记录 ID 查找消息

// Look up the most recent message.
const listMessagesRes = await gmail.users.messages.list({
  userId: email,
  maxResults: 1
});
const messageId = listMessagesRes.messages[0].id;

// Get the message using the message ID.
const message = await gmail.users.messages.get({
  userId: email,
  id: messageId
});

return message;

分析图片附件

如果消息包含图片附件,watchGmailMessages 将调用 Cloud Vision API 为图片添加注释。在此 Codelab 中,您将要求 Cloud Vision API 对图片进行分类并返回多个图片标记;例如,如果提供了蓝天的图片,Cloud Vision API 可能会返回蓝色、天空和自然标记。

watchGmailMessages 使用 Node.js 版 Cloud Vision API 库来调用 Cloud Vision API:

// Tag the attachment using Cloud Vision API
const analyzeAttachment = async (data, filename) => {
  var topLabels = ['', '', ''];
  if (filename.endsWith('.png') || filename.endsWith('.jpg')) {
    const [analysis] = await visionClient.labelDetection({
      image: {
        content: Buffer.from(data, 'base64')
      }
    });
    const labels = analysis.labelAnnotations;
    topLabels = labels.map(x => x.description).slice(0, 3);
  }

  return topLabels;
};

更新 Google 表格

watchGmailMessages 会将此分析的结果导出到 Google 表格。其中包括发件人和附件的名称以及图片附件的标签(如果有)。

首先,创建一个 Google 表格。打开 Google 表格,然后点击新建电子表格下的空白模板。复制该工作表的 ID。例如,如果您浏览器中的地址如下所示:

https://docs.google.com/spreadsheets/d/abcdefghij01234567890/edit#gid=0

您的电子表格的 ID 为 abcdefghij01234567890。在 Cloud Shell 代码编辑器中,更新 gcf-gmail-codelab/pubsub/env_vars.yaml,并将 YOUR-GOOGLE-SHEET-ID 替换为您自己的值。

watchGmailMessages 与 Google Sheets API 连接以附加信息:

const updateReferenceSheet = async (from, filename, topLabels) => {
  await googleSheets.spreadsheets.values.append({
    spreadsheetId: SHEET,
    range: SHEET_RANGE,
    valueInputOption: 'USER_ENTERED',
    requestBody: {
      range: SHEET_RANGE,
      majorDimension: 'ROWS',
      values: [
        [from, filename].concat(topLabels)
      ]
    }
  });
};

最后一步

在 Cloud Shell 代码编辑器中,打开 gcf-gmail-codelab/pubsub/env_vars.yaml 并将 YOUR-GOOGLE-CLIENT-IDYOUR-GOOGLE-CLIENT-SECRETYOUR-GOOGLE-CALLBACK-URL 替换为您自己的值。您可以在 Google Cloud 控制台中找到这些值:在左侧导航菜单中打开 Cloud Functions,在 Cloud Functions 列表中选择 auth_init,然后查找环境变量部分。

部署代码

运行以下命令以部署 Cloud Functions 函数:

cd ~

cd gcf-gmail-codelab/pubsub

gcloud functions deploy watchGmailMessages --runtime=nodejs8 --trigger-topic=gmail-watch --env-vars-file=env_vars.yaml

如果您为 Cloud Pub/Sub 主题指定的名称不是 gmail-watch,请将上述命令中的 gmail-watch 替换为您的主题名称。部署 Cloud Functions 函数可能需要几秒钟的时间。

7. 试试看

恭喜,大功告成!向自己发送一封包含图片附件的电子邮件。几秒钟后,您创建的 Google 表格就会自动更新成您提供的信息。