Google Cloud Functions で Gmail の受信トレイを強化する

1. はじめに

何十億もの企業や個人が、Gmail やその他の G Suite サービスを使用してコミュニケーションを取り、データを処理しています。Google は、これらのサービスの情報をプログラムでアクセスできるように G Suite API を提供しています。この API を使用すると、日常業務のワークフローを簡単に自動化できます。このラボでは、受信メールを自動的に分類し、そのカテゴリを Google スプレッドシートに保存する強力な Gmail 拡張機能を作成します。この拡張機能は、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 のサーバーレス Functions as a Service プラットフォームです。

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 は、事前トレーニング済みモデルを使用して画像から分析情報を取得する強力な ML サービスです。

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 Functions を設定する前に、Gmail へのアクセスを承認する必要があります。OAuth クライアントを Google に登録し、関連するクライアント ID を作成する必要があります。

OAuth クライアントを登録する

Google Cloud コンソールの左側のナビゲーション メニューで、[API とサービス] を見つけます。[OAuth 同意画面] をクリックします。

91b2a3bac30bb2c5.png

[アプリケーション名] フィールドに名前を入力します(例: GCF + Gmail Codelab)。その他の設定は変更せず、ページを下にスクロールして [保存] をクリックします。

関連付けられたクライアント ID を作成する

[認証情報] タブに切り替えます。[認証情報を作成] をクリックし、[OAuth クライアント ID] を選択します。[ウェブ アプリケーション] タイプを選択し、名前を付け(ここでも GCF + Gmail Codelab を使用できます)、[作成] をクリックします。[制限] フィールドは、この段階では空のままにしておきます。

ポップアップ ウィンドウに表示されたクライアント ID とクライアント シークレットを書き留めます。ページでクライアントの名前をクリックすると、これらの値を再度表示できます。

1160d8027ea52d90.png

承認手続きを実行する

サンプルコードでは、auth/index.js は、作成したクライアント ID とクライアント シークレットを使用して連携して認可プロセスを実行する 2 つの Cloud Functions(auth_initauth_callback)を指定します。

コードを検査するには、Cloud Shell コードエディタで auth/index.js を開きます。

認可プロセスでは、アクセス トークン更新トークンの 2 種類のトークンが返されます。

  • アクセス トークンは、有効期間の短い ID 証明です。これを持つユーザーに、データへのスコープ付きアクセス権が付与されます。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 にベータ版コマンドをインストールする権限を付与します。

次に、Google Cloud コンソールに移動し、左側のナビゲーション メニューで [Cloud Functions] をクリックします。Cloud Functions のリストで auth_callback をクリックし、[トリガー] タブに切り替えます。

cb094bd341f9b299.png

45678a327c80e0f1.png

ページ上の URL をコピーします。Cloud Functions ページに戻り、Cloud Functions のリストで auth_init をクリックします。[全般] タブで、[編集] をクリックします。[環境変数、ネットワーキング、タイムアウトなど] をクリックし、GOOGLE_CALLBACK_URL の値をコピーした URL に置き換えます。

939ca3bd38047282.png

[デプロイ] をクリックして、変更を適用します。このプロセスを繰り返して、auth_callback も更新します。

最後に、左側のナビゲーション メニューを開き、[API とサービス] > [ドメインの確認] をクリックします。承認済みドメインを追加するには、[ドメインを追加] をクリックします。たとえば、先ほどコピーした URL が

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

次のドメインを承認済みドメインとして追加する必要があります。

us-central1-my-project.cloudfunctions.net

[ドメインを追加] を押して確定します。

4348748f232ceb87.png

[認証情報] ページに戻ります。OAuth クライアントの名前をクリックし、コピーした URL を [承認済みのリダイレクト URI] として追加します。Enter キーを押して確定します。

URL から /auth_callback の部分を削除し、残りの部分を承認済みの JavaScript 生成元として追加します。たとえば、URL が

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 トピックにメッセージを送信する権限を付与する必要があります。作成したトピックのコンテキスト メニュー(縦の 3 つのドット)をクリックして、[権限] を選択します。[メンバーを追加] をクリックして、新しいメンバーとして gmail-api-push@system.gserviceaccount.com を指定し、[Pub/Sub > Pub/Sub パブリッシャー] のロールを付与します。最後に、[保存] をクリックして変更を適用します。

使用する Pub/Sub トピックを指定するように、Cloud Functions auth_callback を更新します。左側のナビゲーション メニューで [Cloud Functions] をクリックし、Cloud Functions のリストで auth_callback を選択します。[全般] タブで、[編集] をクリックします。[詳細] をクリックし、PUBSUB_TOPIC の値を先ほど作成した Pub/Sub トピックの名前に置き換えます。[保存] をクリックして変更を適用します。

これで、Gmail のプッシュ通知を承認して設定する準備が整いました。新しい変更が完了するまで待ってから、[Cloud Functions] ページに戻り、Cloud Functions のリストで auth_init を選択して、[トリガー] タブに切り替えます。URL をクリックすると、[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 は、トピックのサブスクライバーとしてデプロイされると、新しいメッセージを読み取り、添付画像を分類して、そのカテゴリを Google スプレッドシートにエクスポートする Cloud Functions の関数 watchGmailMessages を指定します。

コードを検査するには、Cloud Shell コードエディタで pubsub/index.js を開きます。

メッセージの取得

Gmail のプッシュ通知には、通知に関連付けられているメールアドレスと履歴 ID が含まれます。このコードラボでは、簡略化のため、プッシュ通知が届いたときに 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 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 スプレッドシートが、入力した情報で自動的に更新されます。