✈️

【GAS】フライト情報をGoogleフォームに入力→Gmailに送信→カレンダーに自動登録

2024/11/09に公開

GmailからGoogleカレンダーに自動で予定を入れてくれる機能、みなさん使ってますか?
あれ便利ですよね〜

https://www.travelgo.com/ja-jp/

で、最近ly.comという予約サイトから激安航空券とったりをよくするのですが、ここから来るメールになぜかGmail反応してくれないんですよね。いちいちカレンダー手動入力面倒だし、性格的にカレンダーのフォーマットが他と統一されなくなってしまいそうなのもなんだか嫌です。

https://zenn.dev/cureapp/articles/5354844b8a734f

で、どうにかする方法を調べていたら上記の素晴らしい記事を見つけたので、こちらをもう少し改変してGoogleフォームからメールを飛ばし、カレンダーにフライト予定を自動登録するところまでやってみました。

直接カレンダーに入力すりゃいいじゃん、と自分でも思いますが、色々な面含めて自動登録のほうが都合がよいです。その理由が書かれている点も含めてまず上記記事を参照してください。

フライト情報を入力するフォームをつくる

こんな感じのフォームをまず作ります。

https://docs.google.com/forms/d/e/1FAIpQLScBWe8QNUvlq7eYJWvbuKt6eWEap7p8By12s2WVZ1eZzbgThg/viewform?usp=sf_link

JSON-LDで航空券を表示する際の情報がとれていればOKです。
以下などが参考になります。

https://www.zoho.com/jp/mail/help/highlighting-email-snippets.html#alink17

フォーム送信をトリガーにしてJSON-LDつきメールを自分に送るGASを書く

https://qiita.com/kakakaori830/items/be67250732c4ea1838d1

スプレッドシートは紐付けさせず、フォームの右上メニューから直接スクリプトを作成し、以下のような関数を作ります。

function onFormSubmit(e) {
  FormApp.getActiveForm(); // 書いておかないとエラーでる
  const res = e.response.getItemResponses();

  // メールテンプレートを先に取得
  const template = HtmlService.createTemplateFromFile('mail_template');

  // フォーム内容を取得
  template.passanger = res[0].getResponse();
  template.reservationNumber = res[1].getResponse();
  template.flightNumber = res[2].getResponse();
  template.airlineName = res[3].getResponse();
  template.airlineCode = res[4].getResponse();
  template.departureAirport = res[5].getResponse();
  template.departureCode = res[6].getResponse();
  template.departureTime = res[7].getResponse();
  template.arrivalAirport = res[8].getResponse();
  template.arrivalCode = res[9].getResponse();
  template.arrivalTime = res[10].getResponse();
  
  // JSON-LD
  template.flightInfo = {
    '@context': 'http://schema.org',
    '@type': 'FlightReservation',
    'reservationNumber': template.reservationNumber,
    'reservationStatus': 'http://schema.org/Confirmed',
    'underName': {
      '@type': 'Person',
      'name': template.passanger
    },
    'reservationFor': {
      '@type': 'Flight',
      'flightNumber': template.flightNumber,
      'airline': {
        '@type': 'Airline',
        'name': template.airlineName,
        'iataCode': template.airlineCode
      },
      'departureAirport': {
        '@type': 'Airport',
        'name': template.departureAirport,
        'iataCode': template.departureCode
      },
      'departureTime': template.departureTime,
      'arrivalAirport': {
        '@type': 'Airport',
        'name': template.arrivalAirport,
        'iataCode': template.arrivalCode
      },
      'arrivalTime': template.arrivalTime
    }
  };

  // メール送信
  MailApp.sendEmail({
    to: Session.getActiveUser().getEmail(),
    subject: 'フライト情報 予定自動登録メール',
    htmlBody: template.evaluate().getContent()
  });
}

この関数が、フォーム送信をトリガーにして実行されるように設定します。
設定後、エラーが出る前提でこのエディタのまま 実行 ボタンをクリックすると「承認が必要です」の画面が出てくるので承認をしておきます。そうでないとトリガーで起動してもPermission Errorが出てしまいます。

https://misapon.blogspot.com/2016/03/google-app-script-getactiveform-you-do.html

2行目の FormApp.getActiveForm() は、初回の承認要請を開くために必要なようで、一度承認してしまえば不要な行だが存在していないと初回起動で必ずコケる、という曲者です。

メールのテンプレートとなるHTMLを用意する

元々参考にさせていただいた記事では、別のアプリで作成したJSON-LDを手動で貼り付けて静的に生成したHTMLメールを送るという仕組みでしたが、ここでは動的に作成してみます。

<!DOCTYPE html>
<html>
  <head>
    <script type="application/ld+json">
      <?!= JSON.stringify(flightInfo) ?>
    </script>
  </head>
  <body>
    <h2>フライト基本情報</h2>
    <table>
      <tbody>
        <tr><th scope="row">搭乗者名</th><td><?= passanger ?></td></tr>
        <tr><th scope="row">航空会社予約番号</th><td><?= reservationNumber ?></td></tr>
        <tr><th scope="row">フライト番号</th><td><?= flightNumber ?></td></tr>
        <tr><th scope="row">航空会社名</th><td><?= airlineName ?> (<?= airlineCode ?>)</td></tr>
      </tbody>
    </table>
    <h2>出発</h2>
    <table>
      <tbody>
        <tr><th scope="row">空港名</th><td><?= departureAirport ?> (<?= departureCode ?>)</td></tr>
        <tr><th scope="row">日時</th><td><?= departureTime ?></td></tr>
      </tbody>
    </table>
    <h2>到着</h2>
    <table>
      <tbody>
        <tr><th scope="row">空港名</th><td><?= arrivalAirport ?> (<?= arrivalCode ?>)</td></tr>
        <tr><th scope="row">日時</th><td><?= arrivalTime ?></td></tr>
      </tbody>
    </table>
  </body>
</html>

body部分は本来なくてもよい部分ですが、何のメールかわからなくなりそうだったので念のためいれています。ここは色々とアレンジできるかもしれませんが取り急ぎシンプルに作っています。

head内のJSON-LDが入っている部分が肝で、テンプレート側でこのような JSON.stringify() をしてあげないとダブルクオートがエスケープされてしまい、うまく認識されません。

https://web-breeze.net/gas-passing-data-to-html/

「オブジェクトを受け渡す」の項を参照

うまくいくとこんな感じに

メール側

カレンダー側

フライト類は特に常にこれで統一しておきたいものです。

応用できそう

  • ChatGPT Function Callingなどを用いて、メールの中から自動で要素を拾い上げてこのフォームにセットして送信してくれるようなもの。
  • スプレッドシートに都市名・空港名・航空会社名・IATAコードを書いておき、検索で出してこれるようにする(大変そうだけど普通にサービス化できそう)

Discussion