見出し画像

受信したGmailの内容をkintoneに自動でレコード追加するGAS

特定のメールアドレスからGmailが届いたときに、メールの内容をそのままkintoneの活動履歴アプリに手入力するのが面倒。といった時に便利なGASを作成しました。

~なぜこのGASを作成したのか~

 ドクターメイト社では取引先の施設とメールや電話でコンタクトを取る度にkintoneにそのやり取りの日時や内容を手入力やコピペを使って、活動履歴として報告していました。
  このやり方ではメールの確認漏れが起こったり、活動報告に時間が掛かってしまいます。
 そこでドクターメイトの社員から取引先とのGmailでのやり取りの内容をkintoneに自動入力するようにして欲しいとの依頼を受け、そのプログラムをGoogle Apps Script(GAS)を使って作成していきました。

~GASのコード添付~

/*---- 初期設定ここから ----*/
// kintoneサブドメイン(https://xxxxxx.cybozu.com/k/99/だったら、xxxxxx)
const SUB_DOMAIN = "XXXXXXXX";

// kintone活動履歴アプリ番号(https://xxxxxx.cybozu.com/k/99/だったら、99)
const ACTION_APP_ID = XXX;
// kintoneアプリの名前
const ACTION_APP_NAME = "XXXX";
// kintone アプリのAPIトークン(レコード追加権限があればOK)
const ACTION_APP_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

// kintone顧客管理番号(https://xxxxxx.cybozu.com/k/99/だったら、99)
const FACILITY_APP_ID = XXX;
// kintoneアプリの名前
const FACILITY_APP_NAME = "XXXXXXXXXXXXXXXXXXXXXXXXX";
// kintone アプリのAPIトークン(レコード追加権限があればOK)
const FACILITY_APP_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

// Gmailラベル名
const LABEL = "XXXXX";
// 本文を抜粋する文字数
const EXCERPT_LENGTH = 200;
// 1回で取得するスレッド数の最大値
const MAX_THREADS = 10;
// 自ドメイン
const MY_DOMAIN = "XXXXXXXXXXXXXXXX";
/*---- 初期設定ここまで ----*/

// メインファンクション
function mainFunction() {
  // プロパティから前回取得した最終日時を取得
  let lastDateText = PropertiesService.getScriptProperties().getProperty("lastDateText");
  // 最終のメール日時がなければ初期値を代入
  if (lastDateText === null) lastDateText = "2020/01/01 00:00:00";
  // 日時の文字列からDateオブジェクトをつくる
  const lastDate = new Date(lastDateText);
  // 最新メール日時を入れる変数に最終のメール日時を代入
  let newDate = lastDate;
  // 条件にマッチするスレッドを検索して取得する
  let query = "";
  if (LABEL) query += "label:" + LABEL;
  query += " after:" + Math.floor(lastDate.getTime() / 1000);
  // マッチするスレッドを取得
  const threads = GmailApp.search(query, 0, MAX_THREADS);
  // マッチするスレッドがなければ終了
  if (threads.length === 0) return false;
  // 活動履歴登録用の配列を作成
  const actionRecords = [];
  // スレッドからメールを取得する
  const allMessages = GmailApp.getMessagesForThreads(threads);
  // 古い順にする
  allMessages.reverse();
  // スレッド毎に繰り返し
  for (const thread of allMessages) {
    // メール毎に繰り返し
    for (const mail of thread) {
      // 送信日時を取得
      const date = mail.getDate();
      // 日時が古いなら何もしない
      if (date <= lastDate) continue;
      // 日時が新しければ最新メール日時を更新
      if (date > newDate) newDate = date;
      // kintoneに登録する情報を作成
      const record = getActionRecord(mail);
      // 活動履歴登録用の配列に追加
      if (record) actionRecords.push(record);
    }
  }
  // kintone活動履歴にまとめて登録
  createKintoneRecords(actionRecords);
  // 最新のメール日時を記録
  const newDateText = Utilities.formatDate(newDate, 'Asia/Tokyo', "yyyy/MM/dd HH:mm:ss");
  PropertiesService.getScriptProperties().setProperty("lastDateText", newDateText);
}
// メールデータから活動履歴更新用のレコードデータを作成
function getActionRecord(mail) {
  //送信元のメールアドレスのみを取得
  const emailExp = new RegExp("[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*.)+[a-zA-Z]{2,}");
  // 送信元を取得
  const from = mail.getFrom();
  // 宛先を取得
  const to = mail.getTo();
  // fromとtoが入った配列をつくる
  const fromAndTo = to.split(',');
  fromAndTo.push(from);
  // メールアドレスのみ格納された配列emailsをつくる 
  const emails = new Array();
  for (let i = 0; i < fromAndTo.length; i++) {
    const array = fromAndTo[i].match(emailExp);
    emails[i] = array[0];
  }
  // メールの送信日時を取得
  const sentDate = mail.getDate();
  const actionDate = Utilities.formatDate(sentDate, 'Asia/Tokyo', "yyyy-MM-dd'T'HH:mm:ss+09:00");
  // メールの件名を取得
  const subject = mail.getSubject();
  // メールの本文に件名、From、Toを追加し、本文を指定の文字数まで抜粋
  let body = "件名: " + subject;
  body += "\nFrom: " + from;
  body += "\nTo" + to;
  body += "\n\n" + mail.getPlainBody().slice(0, EXCERPT_LENGTH);
  // メールアドレスの数だけ繰り返し
  for (email of emails) {
    // メアドが自ドメインなら何もしない
    if (email.match(MY_DOMAIN)) continue;
    // 顧客レコード番号を取得
    const facilityId = getRecordNumber(email);
    if (!facilityId) continue;
    const record = {
      "活動日時": {
        "value": actionDate
      },
      "詳細": {
        "value": body
      },
      "顧客レコード番号": {
        "value": facilityId
      }
    };
    // fromが自ドメインなら対応者のcode(メアドの@より前の部分と一致)を登録
    if (from.match(MY_DOMAIN)) {
      const account = from.match(/([a-zA-Z0-9_.+-]+)@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*.)+[a-zA-Z]{2,}/)[1];
      record["XXX"] = { value: [{ "code": account }] };
    }
    // recordを返す
    return record;
  }
}
// kintoneからレコードを取得する
function getRecordNumber(email) {
  const query = `メールアドレス = "${email}"`;
  const apps = {
    FACILITY_APP: { appid: FACILITY_APP_ID, name: FACILITY_APP_NAME, token: FACILITY_APP_TOKEN }
  };
  // kintoneから条件に適するレコードを取得
  const kintone_manager = new KintoneManager(SUB_DOMAIN, apps);
  const response = kintone_manager.search("FACILITY_APP", query);
  // レスポンスコード取得 (成功すれば200になる)
  const code = response.getResponseCode();
  if (code != 200) return false;
  // JSONをオブジェクトに変換
  const content = JSON.parse(response.getContentText());
  // レコード番号を返す
  if (content.records.length > 0) return content.records[0]["レコード番号"].value;
  else return false;
}
// 複数のkintoneのレコードを一括登録する
function createKintoneRecords(records) {
  const limit = 100; //上限100;
  const apps = {
    ACTION_APP: { appid: ACTION_APP_ID, name: ACTION_APP_NAME, token: ACTION_APP_TOKEN },
  };
  // 作成するレコードを上限数まで抜き出す
  const recordsLimited = records.slice(0, limit);
  // 作成してレスポンス取得
  const kintone_manager = new KintoneManager(SUB_DOMAIN, apps);
  const response = kintone_manager.create("ACTION_APP", recordsLimited);
  // ステータスコード取得(成功すれば200)
  const code = response.getResponseCode();
  // 200でなければ終了
  if (code != 200) { console.log(response.getContentText()); return false; }
  // 作成済みのレコードを削除
  records.splice(0, limit);
  // レコードが残っていれば次の処理へ(繰り返し)
  if (records.length > 0) postRecords(records);
  return true;
}

~GASの仕様説明~

1.GmailとのAPI連携に使用した2つのkintoneアプリ

【活動日時、詳細、顧客レコード番号】を含むkintone「活動履歴」アプリ
【メールアドレス】を含むkintone「顧客情報」アプリ

この2つのアプリのAPIトークンをGASに入力し、GmailとのAPI連携をおこなった。
フィールドコードはそれぞれ

活動日時   → 活動日時
顧客管理番号 → 顧客レコード番号
詳細     → 詳細
メールアドレス→ メールアドレス

2.Gmailのラベル作成

まずGmailの設定でToに特定のメールアドレスを含むメールのみを集めるラベルを設定します。
(ラベルの設定方法:https://dxs.co.jp/blog/gmail-label/

Gmailラベル設定画面

上に添付されているコードはこの設定したラベルに表示されるメールの内容を取り出してGASに読み込んでいる。

3.動作説明

まずkintoneのラベルに設定したメールアドレス「XXXXXXXX@XXXXXX.XXX.XX」
からメールが届いてGmailのラベル「Web問合せ」内にメールが表示されたとします。

顧客情報アプリ レコード一覧画面

上の画像のように「顧客情報」アプリに登録してあるメールが届いた際はGASがメールの内容を「活動履歴」アプリに送ってレコード作成する動作をおこないます。
届いたメールが「顧客情報」アプリに前もって登録されているものでなければ「活動履歴」のレコード自動作成はおこなわれません。

今回はメールアドレスが登録済のところからメールが届いたのでkintoneにレコード追加される動作が正常に行われます。

その後のGASの動作については以下の画像の通りです。 

受信したGmailの内容をkintoneに自動でレコード追加するGASの動作説明


~このGASによって得た成果~

 このGASの実装によって取引先とのメールでのやり取り内容の報告が自動化され、一人あたり月440分(2分×10通×22日)程度の作業時間の削減に成功しました。
 実際にドクターメイト社の業務時間の削減に貢献できたことは学生の自分には良い経験になったと感じています。

 実際に利用者の声も聴くことができ、感謝の言葉もいただきました。自分がコードを書くことでそれを利用する人の業務の負担が少しでも改善できていると考えればこれからのプログラミングの勉強へのモチベーションも高めていけると感じています。


この記事が気に入ったらサポートをしてみませんか?