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 を有効にするには、画面左上のハンバーガー メニューをクリックして、左側のナビゲーション サイドバーを開きます。

ナビゲーション メニューで [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 モードを選択] をクリックします。

このラボでは、任意のデータベースの場所を使用できます。[データベースを作成] をクリックして 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 をアクティブにする] ボタンをクリックします。

画面の下部に新しいパネルが表示されます。

[コードエディタを起動] ボタンをクリックして、Cloud Shell コードエディタを起動します。

Cloud Shell コードエディタが新しいウィンドウで開きます。
コードをダウンロードする
Cloud Shell で次のコマンドを実行して、プロジェクトのクローンを作成します。
git clone https://github.com/googlecodelabs/gcf-gmail-codelab.git cd gcf-gmail-codelab
Cloud Shell コードエディタに、新しいフォルダ gcf-gmail-codelab が表示されます。
3. アーキテクチャの概要
このラボのワークフローは次のとおりです。

- ユーザーが Gmail のプッシュ通知を設定します。受信トレイに新しいメッセージが届くたびに、Gmail から Cloud Pub/Sub に通知が送信されます。
- Cloud Pub/Sub は、新しいメッセージ通知を Google Cloud Functions に配信します。
- 新しいメッセージの通知が届くと、Cloud Functions インスタンスが Gmail に接続して新しいメッセージを取得します。
- メールに画像が添付されている場合、Cloud Functions インスタンスは Cloud Vision API を呼び出して添付ファイルを分析します。
- Cloud Functions インスタンスは、選択した Google スプレッドシートを更新し、メッセージの送信者と添付ファイルのダウンロード先を指定します。
4. Gmail へのアクセスを承認する
メールを自動的に読み取るように Cloud Functions を設定する前に、Gmail へのアクセスを承認する必要があります。OAuth クライアントを Google に登録し、関連するクライアント ID を作成する必要があります。
OAuth クライアントを登録する
Google Cloud コンソールの左側のナビゲーション メニューで、[API とサービス] を見つけます。[OAuth 同意画面] をクリックします。

[アプリケーション名] フィールドに名前を入力します(例: GCF + Gmail Codelab)。その他の設定は変更せず、ページを下にスクロールして [保存] をクリックします。
関連付けられたクライアント ID を作成する
[認証情報] タブに切り替えます。[認証情報を作成] をクリックし、[OAuth クライアント ID] を選択します。[ウェブ アプリケーション] タイプを選択し、名前を付け(ここでも GCF + Gmail Codelab を使用できます)、[作成] をクリックします。[制限] フィールドは、この段階では空のままにしておきます。
ポップアップ ウィンドウに表示されたクライアント ID とクライアント シークレットを書き留めます。ページでクライアントの名前をクリックすると、これらの値を再度表示できます。

承認手続きを実行する
サンプルコードでは、auth/index.js は、作成したクライアント ID とクライアント シークレットを使用して連携して認可プロセスを実行する 2 つの Cloud Functions(auth_init と auth_callback)を指定します。
コードを検査するには、Cloud Shell コードエディタで auth/index.js を開きます。
認可プロセスでは、アクセス トークンと更新トークンの 2 種類のトークンが返されます。
- アクセス トークンは、有効期間の短い ID 証明です。これを持つユーザーに、データへのスコープ付きアクセス権が付与されます。
auth_callbackは、これらのトークンを Cloud Datastore に保存します。 - 更新トークンは、新しいアクセス トークンを取得するために使用され、有効期間が大幅に長くなります。
通常、これらは暗号化されるか、アクセス トークンとは別に保存されます。
Cloud Shell コードエディタで auth/env_vars.yaml を編集します。YOUR-GOOGLE-CLIENT-ID と YOUR-GOOGLE-CLIENT-SECRET は、実際の値に置き換えてください。詳しくは、前の手順をご覧ください。YOUR-GOOGLE-CLIENT-CALLBACK-URL と YOUR-PUBSUB-TOPIC の値は、今のところ変更しないでください。

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 をクリックし、[トリガー] タブに切り替えます。


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

[デプロイ] をクリックして、変更を適用します。このプロセスを繰り返して、auth_callback も更新します。
最後に、左側のナビゲーション メニューを開き、[API とサービス] > [ドメインの確認] をクリックします。承認済みドメインを追加するには、[ドメインを追加] をクリックします。たとえば、先ほどコピーした URL が
https://us-central1-my-project.cloudfunctions.net/auth_callback
次のドメインを承認済みドメインとして追加する必要があります。
us-central1-my-project.cloudfunctions.net
[ドメインを追加] を押して確定します。

[認証情報] ページに戻ります。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/

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 でログイン] ページにリダイレクトされます。

ご自身の Gmail アカウントでログインします。アカウントの受信トレイに新しいメッセージが届くと、プッシュ通知がトリガーされます。ログインすると、次のページが表示されます。

[許可] をクリックしてアクセスを承認します。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 は blue、sky、nature などのタグを返すことがあります。
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-ID、YOUR-GOOGLE-CLIENT-SECRET、YOUR-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 スプレッドシートが、入力した情報で自動的に更新されます。