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 と 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

新しいフォルダ gcf-gmail-codelab が Cloud Shell コードエディタに表示されます。

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

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

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

91b2a3bac30bb2c5.png

[Application name] に名前(GCF + Gmail Codelab など)を入力します。その他の設定は変更せずに、ページを下にスクロールして [保存] をクリックします。

関連するクライアント ID を作成する

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

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

1160d8027ea52d90.png

認可プロセスを実行する

サンプルコードでは、auth/index.jsauth_initauth_callback の 2 つの Cloud Functions の関数が指定されています。この関数が連携し、先ほど作成したクライアント ID とクライアント シークレットを使用して、認証プロセスを実行します。

コードを調べるには、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 など)を入力し、[作成] をクリックします。さらに、Pub/Sub トピックにメッセージを送信する権限を Gmail に付与する必要があります。作成したトピックのコンテキスト メニュー(縦に並んだ 3 つの点)をクリックし、[権限] を選択します。[メンバーを追加] をクリックし、新しいメンバーとして 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 を選択して、[トリガー] タブに切り替えます。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 は、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 スプレッドシートを開き、[Start a new spreadsheet] の [空白] テンプレートをクリックします。シートの 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 スプレッドシートが入力した情報で自動的に更新されます。