見出し画像

Gmailで受信したメール本文をスプレッドシートに転記するGASを修正 その2

以前書いたこの記事とは別のスクリプトで別のエラーが発生した。

本来抽出すべきでないメールのデータを抽出してしまう。というのが、上記の記事で発生していた困り事だ。しかし、今回は同じデータをダブって抽出してしまうのではなく、スクリプト自体の実行エラーが発生する。という事だった。

異変に気付いたきっかけはGoogleからのメールだった。

件名
Summary of failures for Google Apps Script: (プロジェクト名)

From
noreply-apps-scripts-notifications@google.com

本文
Your script, (プロジェクト名), has recently failed to finish successfully. A summary of the failure(s) is shown below. To configure the triggers for this script, or change your setting for receiving future failure notifications, click here.

Summary:
(実行失敗履歴の表)

嫌なメールだな~と思いつつも、スプレッドシートに転記の過不足は無かった。このスクリプトは1時間に1回定時で実行しているため、処理の一時的な輻輳か何かでエラーになったが、次の実行で問題なく処理できた。とかか?
と考えながらも実害がなかったので放置していた。怠惰だ。

そして本日、いよいよ4通目ぐらいのメールを受信してしまった。さすがに気になるので、この機会に片づけるかと気合を入れてChatGPTに聞いてみた。

何らかの原因でエラーが発生しているので、コードを見直すかエラーログを確認すると良いよ。という提案だった。ChatGPTによると「エラーログを確認する: Google Apps Scriptのエディタで「表示」→「ログ」を選択して、スクリプトのログを確認します。」という事だったが、まず「表示」が見つからない。

そもそもその項目が無いんですが・・・と問い詰めた所、コードの中にLogger.log()が仕込まれている事が前提の案内だったとの謝罪を受けた。

あの・・・質問の段階でコード全文を貼ってるんですが・・・

この辺りがChatGPTもまだまだだなと思わせる所だが、普段から十分過ぎるぐらい役に立っているので許してやる事にしよう。

他にエラーログが見れそうな所は無いかな~と探してみた所、以下の箇所で発見出来た。

自身のアカウントのApps Scriptのトップ

該当のプロジェクト名の一番右にある縦三点マーク

「失敗した実行」

エラーの一覧から中身を開いて一つずつ確認してみると、定時実行のたびに同内容のエラーが発生していた。

2023/09/29 10:49:14	エラー	TypeError: Cannot read properties of null (reading '1')
				at [unknown function](コード:22:53)
				at [unknown function](コード:16:14)
				at parseMailToSpreadsheet(コード:12:11)

分かる訳がないので、当然ChatGPTに聞いてみた。

受け取った実行ログに基づくと、TypeError: Cannot read properties of null (reading '1')は、正規表現の.exec()メソッドがnullを返し、それに対して配列のインデックス1を読み取ろうとしたときに発生しています。

この問題は、メールの本文が正規表現と一致しない場合に発生します。そのため、一致する結果がnullとなり、それに対してインデックスを参照しようとするとエラーが発生します。

この問題を解決するためには、.exec()メソッドの結果がnullでないことを確認してから配列のインデックスを参照するように修正する必要があります。

もともとのスクリプトの動きは以下のようなものだ。

件名で抽出対象の未読メールを探す

本文から条件に該当する項目を抜き出してスプレッドシートに転記する

処理済みのメールを既読にする

エラーログの発生時刻を見ると、抽出対象となる未読メールは存在しない時間だ。にも関わらずメールの本文が正規表現と一致しないとはどういう事か?ありもしない問題をさも問題かのように騒ぎ立てているという事か?

ライムスター宇多丸の映画評で、押井 守の「スカイクロラ」に文句を言っていた回を思い出してしまった。

当初、「Re:」が付いた返信文が抽出されてしまうが、中身は普通の文書なので正規表現と一致しない。なので、私がメールを開封するまではエラーが出続けるという事象だと考えていたが、どうやら違ったようだ。

メールの本文が正規表現と一致しないの意味はよく分からないままだが、ChatGPTがこんな提案をしてきた。

var name = /名前:(.*)様/.exec(body)[1].trim();

この行で、.exec()の結果を直接インデックスでアクセスしています。もし正規表現と一致しなければ、.exec()nullを返すため、[1]でアクセスすることができず、上記のエラーが発生します。

未読メールが存在しない場合でも、このエラーは発生します。なぜなら、GmailApp.search()が空の配列を返すだけで、スクリプトは通常通り実行され、.exec()nullを返す可能性があるからです。

解決方法として、以下のように.exec()の結果を変数に格納し、それがnullでないことを確認した後でデータを抽出するように変更します:

var nameMatch = /名前:(.*)様/.exec(body);
var name = nameMatch ? nameMatch[1].trim() : null;

このように修正することで、メールの本文が正規表現と一致しない場合や未読メールが存在しない場合でもエラーが発生しなくなります。

実際に提案通りに修正してみた所、エラーは発生しなくなり、転記は過不足なく行われた。一件落着だがなんとなくしか事象を把握出来ていないのも気持ち悪いので、分かりやすく説明するようChatGPTに頼んでみた。

提供されたrecordEmailToSpreadsheet_package関数を確認したところ、.exec()メソッドを使用していますが、その結果を直接インデックスでアクセスする前に、nullでないことを確認しています。この確認作業により、エラーが回避されているのです。

const paymentResult = regexPayment.exec(body);
const ageResult = regexAge.exec(body);
        
if (paymentResult && paymentResult.length > 0 && ageResult && ageResult.length > 0) {
    // ...
}

ここで、paymentResultageResultのような変数は、.exec()メソッドの結果を格納しています。その後、if文の中でこれらの変数がnullでないこと(実際の結果が得られたかどうか)を確認してから、その結果を利用しています。

このようなチェックを行うことで、.exec()nullを返す場合でもエラーが発生しないようにしています。

要するに、recordEmailToSpreadsheet_package関数は、.exec()メソッドの結果を直接使用する前にその結果が有効かどうかを確認しており、それにより先に提供されたコードとは異なり、エラーが発生していないのです。

なるほど。分からん。

いや、エラーが発生していた理由と発生しなくなった理由は概ね理解出来たが、抽出対象が無いにも関わらずエラーが出ていたという部分が理解できないままだ。

まぁ、エラーが出なくなってスクリプトも普通に動いてるので、特段問題なかろうという事でこの件はクローズする事にした。

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