[GWSStudio100本ノック] 受信メールの署名から取得した連絡先を自動でGoogle Contactsに連携するエージェントを作成してみた(GAS構築編)

 2025.12.06 Yudai Imai

はじめに

本記事は、Google Workspace Studio(旧Flows)の実践ノウハウを100本紹介する連載「Google Workspace Studio活用方法100本ノック」の一つとなります。  

今回は、こちらのブログの受信メールの署名から連絡先情報を抜き出し、Google Contactsを自動的に更新するエージェントを実現するためのGoogle Apps Script(GAS)の構築を説明する番外編的な内容となります。エージェントから連携されるメールアドレス・名前・会社名・電話番号をもとにして、Google Contactsに連絡先を登録する処理を説明させていただきます。

難易度 中級者向け(GASの構築を含むため)
実現すること 受信メールの署名から連絡先情報を抽出し、Google Contactsへ自動登録・更新するようなるため、連絡先の管理を省力化することができます
想定する対象者 新しい取引先や問い合わせが多く、連絡先管理の手間を減らしたい営業・CS担当
利用サービス Gmail、Google Contacts、Google Apps Script

ユースケース

今回作成するエージェントの代表的なユースケースとしては以下のようなことが考えられると思います。

  • 営業担当の新規取引先登録の自動化
    • 初めてメールが届いた相手の署名を解析し、会社名を含む連絡先をContactsへ即登録。後続の商談管理に活用することができます。
  • サポート窓口での顧客情報更新
    • 問い合わせメールの署名に記載された部署名や電話番号を自動で反映し、既存の連絡先情報を最新状態に保つことができます。
  • 採用チームの候補者管理
    • 候補者からのメール署名をもとに、連絡先リストを自動整備。面談調整やフォローアップの連絡がスムーズになります。

前提条件

今回のエージェントを作成するための前提条件は以下となります。Google Workspace Studioは2025年12月時点ではそれまではFlowsという名前で提供されていたサービスからリネームされたサービスかつまだ提供されて間もないため、このブログの内容が最新ではなくなる可能性があることをご了承ください。

  • 利用環境:Google Workspace Studioにアクセスできるユーザーであること。
  • 利用アプリ:Gmailで対象メールが受信できるように用意されていること。Google Apps Scriptが作成できる環境が存在しており、番外編のGASの構築とWorkspace Studioへのインストールが完了していること。
  • 社内ルール:メール内容をAIに渡す際の社内ポリシーや情報管理ルールを確認済みであること。

構築手順

今回のブログではGoogle Apps Scriptの構築の概要については詳しく説明しません。もしGoogle Apps Scriptの構築について詳しく知りたい場合はGoogleの公式ドキュメントなどを確認するようにされてください。

まずは、Google Apps Scriptのサイトにアクセスしてください。そして、新しいプロジェクトを作成して適当な名前をつけてください。今回は「Workspace Studio用の連絡先登録機能」という名前を付けました。

そして、サイドメニューの歯車ボタンから設定画面にアクセスして、全般設定の中の「「appsscript.json」マニフェスト ファイルをエディタで表示する」のチェックボタンにチェックを入れてください。

設定が完了したらエディタの画面に戻ってください。そして、ファイルの中の「appsscript.json」ファイルを選択して、エディタに以下の内容を入力して保存してください。保存した後にサービスのところにPeopleが出てきていれば大丈夫です。

{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
    "enabledAdvancedServices": [
      {
        "userSymbol": "People",
        "version": "v1",
        "serviceId": "peopleapi"
      }
    ]
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Contact Manager",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "upsertContactAction",
          "state": "ACTIVE",
          "name": "Upsert Contact",
          "description": "Registers or updates a Google Contact based on email.",
          "workflowAction": {
            "inputs": [
              {
                "id": "name",
                "description": "Full Name",
                "cardinality": "SINGLE",
                "dataType": { "basicType": "STRING" }
              },
              {
                "id": "company",
                "description": "Company Name",
                "cardinality": "SINGLE",
                "dataType": { "basicType": "STRING" }
              },
              {
                "id": "email",
                "description": "Email Address",
                "cardinality": "SINGLE",
                "dataType": { "basicType": "STRING" } 
              },
              {
                "id": "phone",
                "description": "Phone Number",
                "cardinality": "SINGLE",
                "dataType": { "basicType": "STRING" }
              }
            ],
            "outputs": [
              {
                "id": "executionResult",
                "description": "Result message of the operation",
                "cardinality": "SINGLE",
                "dataType": { "basicType": "STRING" }
              }
            ],
            "onConfigFunction": "onConfigContact",
            "onExecuteFunction": "onExecuteContact"
          }
        }
      ]
    }
  }
}

そして、ファイルの中の「コード.gs」ファイルを選択して、エディタに以下の内容を入力して保存してください。

/**
* Google Workspace Studio 用のヘルパー関数: カードをプッシュするアクションを生成
 */
function pushCard(card) {
  return {
      "action": {
        "navigations": [{
            "push_card": card
          }
        ]
      }
  };
}

/**
* Google Workspace Studio 用のヘルパー関数: 出力変数をFlowに返す
 */
function outputVariables(variableDataMap) {
 const workflowAction = AddOnsResponseService.newReturnOutputVariablesAction()
   .setVariableDataMap(variableDataMap);
 const hostAppAction = AddOnsResponseService.newHostAppAction()
   .setWorkflowAction(workflowAction);
 const renderAction = AddOnsResponseService.newRenderActionBuilder()
   .setHostAppAction(hostAppAction)
   .build();
 return renderAction;
}

/**
 * ■ 設定画面 (Configuration Card) の生成
 */
function onConfigContact() {
  var card = {
    "sections": [
      {
        "header": "Configure Contact Details (People API)",
        "widgets": [
          {
            "textInput": {
              "name": "name",
              "label": "Full Name",
              "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } }
            }
          },
          {
            "textInput": {
              "name": "company",
              "label": "Company Name",
              "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } }
            }
          },
          {
            "textInput": {
              "name": "email",
              "label": "Email Address",
              "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } }
            }
          },
          {
            "textInput": {
              "name": "phone",
              "label": "Phone Number",
              "hostAppDataSource" : { "workflowDataSource" : { "includeVariables" : true } }
            }
          }
        ]
      }
    ]
  };
  return pushCard(card);
}

/**
 * ■ 実行関数 (Execution Function)
 */
function onExecuteContact(event) {
  console.log("Execution Event: " + JSON.stringify(event));

  const inputs = event.workflow.actionInvocation.inputs;
  
  // 各値の取得
  const name = inputs["name"] ? inputs["name"].stringValues[0] : "";
  const company = inputs["company"] ? inputs["company"].stringValues[0] : "";
  const email = inputs["email"] ? inputs["email"].stringValues[0] : "";
  const phone = inputs["phone"] ? inputs["phone"].stringValues[0] : "";

  var resultMessage = "";

  try {
    // People APIを使ったロジックを実行
    resultMessage = upsertContactWithPeopleApi(name, company, email, phone);
  } catch (e) {
    resultMessage = "Error: " + e.toString();
    console.error(resultMessage);
  }

  const variableDataMap = {
    "executionResult": AddOnsResponseService.newVariableData().addStringValue(resultMessage)
  };
  
  return outputVariables(variableDataMap);
}

/**
 * ■ ロジック部分 (People API版)
 * ContactsAppの代わりにAdvanced ServiceのPeople APIを使用します。
 */
function upsertContactWithPeopleApi(name, company, email, phone) {
  if (!email) {
    throw new Error("'email' is required.");
  }

  // 1. メールアドレスで既存の連絡先を検索
  // queryにメールアドレスを指定して検索します
  const searchResult = People.People.searchContacts({
    query: email,
    readMask: "names,metadata,emailAddresses"
  });

  let existingContact = null;
  if (searchResult.results && searchResult.results.length > 0) {
    // 検索結果の中で、実際にメールアドレスが一致するものを探す(念のため)
    existingContact = searchResult.results[0].person;
  }

  // APIに送信するデータオブジェクトの構築
  const contactResource = {};

  // 名前 (givenNameにフルネームを入れる簡易実装)
  if (name) {
    contactResource.names = [{ givenName: name }];
  }

  // 電話番号 (配列で渡すとそのリストで上書きされます)
  if (phone) {
    contactResource.phoneNumbers = [{ value: phone, type: "mobile" }];
  }

  // 会社名
  if (company) {
    contactResource.organizations = [{ name: company, title: "" }]; // titleが必要なら追加
  }

  // メールアドレス (新規作成時のみ必須、更新時はキーとして使うのでリソースには含めなくてもよいが、念の為)
  if (!existingContact) {
    contactResource.emailAddresses = [{ value: email, type: "work" }];
  }

  // --- 実行 ---
  
  if (existingContact) {
    // === 更新 (Update) ===
    // 更新には resourceName と etag が必須です
    const resourceName = existingContact.resourceName;
    const etag = existingContact.etag; // 同時編集競合を防ぐためのタグ
    
    contactResource.etag = etag;

    // 更新したいフィールドを指定 (マスク)
    // ここに含まれるフィールドは、contactResourceの内容で「完全に置換」されます
    const updateFields = [];
    if (name) updateFields.push("names");
    if (phone) updateFields.push("phoneNumbers");
    if (company) updateFields.push("organizations");

    if (updateFields.length > 0) {
      People.People.updateContact(contactResource, resourceName, {
        updatePersonFields: updateFields.join(",")
      });
      return "Updated contact for: " + email;
    } else {
      return "Contact exists, but no fields to update for: " + email;
    }

  } else {
    // === 新規作成 (Create) ===
    People.People.createContact(contactResource);
    return "Created new contact for: " + email;
  }
}

すべての保存が完了したら画面右上にある「デプロイ」ボタンを選択した後に、「デプロイをテスト」を選択してください。

デプロイをテストのポップアップ画面が出てくると思いますので、この画面の中の「Application(s): Workspace Studio」の右側に出てくる「インストール」ボタンを選択してください。はじめてインストールする時には認証画面が出てくると思いますがその時は画面の表示に従って認証を実施してください。

インストールが完了するとWorkspace Studio側の中に作成した処理が追加されます。この時にWorkspace Studioに表示されない場合は画面の再読み込みを試してみてください。

実行テスト

実行テストについてはこちらのブログの内容を確認してください。一連のエージェントの実行の流れを記載させていただいております。

今回のGAS側の機能としてはWorkspace Studioから連携されるデータについても確認を実施しており、もしWorkspace Studioからメールアドレスが含まれていない場合はGoogle Contactsに追加されないような動きとしています。もしメールアドレスが含まれていない場合はログとしてErrorのログが出るようになっています。

まとめ

メールの署名から連絡先を手作業で登録していると、更新し忘れや表記ゆれが発生しがちです。Google Workspace Studioで署名抽出とGASを組み合わせれば、受信と同時にGoogle Contactsを最新化する仕組みを構築できます。

本記事ではContacts登録ロジックをGASで登録する処理とWorkspace Studioにインストールする方法を解説しました。エージェントの構築と合わせて試してみて、連絡先管理の自動化による業務効率化を体感してみてください。

 


BACK TO LIST

   

Recent post最新記事

Contentsコンテンツ