使用 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 并点击它。在新页面中,点击选择 Datastore 模式

98012c91fd4080d4.png

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

Google Cloud Vision

Google Cloud Vision API 是一项强大的机器学习服务,可使用预训练模型从图片中提取数据洞见。

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

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

再次打开左侧导航边栏,然后找到 API 和服务。点击媒体库。在搜索 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.png

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

10f8631ef48bed22.png

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

下载代码

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

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

cd gcf-gmail-codelab

您应该会在 Cloud Shell 代码编辑器中看到一个名为 gcf-gmail-codelab 的新文件夹。

3. 架构概览

以下是本实验的工作流程:

79c5d3e43f674b33.png

  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 Function 以自动读取电子邮件之前,您必须先授权其访问 Gmail。您需要向 Google 注册 OAuth 客户端并创建关联的客户端 ID。

注册 OAuth 客户端

在 Google Cloud 控制台的左侧导航菜单中,找到 API 和服务。点击 OAuth 权限请求页面

91b2a3bac30bb2c5.png

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

创建关联的客户端 ID

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

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

1160d8027ea52d90.png

执行授权流程

在示例代码中,auth/index.js 指定了两个 Cloud Functions,即 auth_initauth_callback,它们协同工作以执行授权流程,使用您刚刚创建的客户端 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.png

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

939ca3bd38047282.png

点击部署以应用更改。重复上述流程,并更新 auth_callback

最后,打开左侧导航菜单,然后依次点击 API 和服务 > 域名验证。如需添加已获授权的网域,请点击添加网域。例如,如果您之前复制的网址如下所示

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

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

us-central1-my-project.cloudfunctions.net

添加网域进行确认。

4348748f232ceb87.png

返回凭据页面。点击 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 控制台,然后在左侧导航菜单中依次点击 Pub/Sub > 主题。点击创建主题。输入主题名称,例如 gmail-watch,然后点击创建。此外,您必须向 Gmail 授予向您的 Pub/Sub 主题发送消息的权限:点击您刚刚创建的主题的上下文菜单(三个竖点),然后选择权限;点击添加成员,指定 gmail-api-push@system.gserviceaccount.com 作为新成员,并向其授予 Pub/Sub > Pub/Sub Publisher 角色;最后,点击保存以应用更改。

更新 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.png

使用您自己的 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 可能会返回 blueskynature 标记。

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 Function:

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 表格自动更新为您提供的信息。