ChatGPTと一緒にプログラミングの実際 - 中編
前編では、私たちとChatGPTが一緒にkintone用のメール送信プラグイン「Gsender」のGoogleの新しい認証方式への移行作業に取り組む様子をお伝えしました。今回の中編では、引き続き一般の皆さんに向けて、ChatGPTの力を借りながら、WebサイトからGmailを使ってメールを送信する機能を持つアプリケーションの開発に挑戦してみます。
プロジェクトの途中で、ChatGPTが最新の技術にも通じていることが判明しましたが、実際にプログラムを動作させるとエラーが発生。人との協力を通じて解決を試みるも、Googleによって非推奨とされている既存技術を使おうとするなど、完璧ではない面もありました。この中編では、そんなChatGPTの協力の様子や実際に起こった出来事をお伝えしていきます。
AIアシスタントとしてのChatGPTの活躍が、皆さんがプログラミングを進める際の参考になれば嬉しいです。それでは、どのようにしてWebサイトからGmailを使ってメールを送信するアプリの開発に挑戦し、ChatGPTと共に問題を解決していくのか、お楽しみください!
ChatGPTより
1. ChatGPTとの対話
Q12.
大変です! Google Chromeでメール送信画面を表示させていますが、ディベロッパーツールのConsoleタグに次のような警告が表示されています。これはどうしたことでしょうか。
=gapi.loaded_0?le=scs:159 Your client application uses libraries for user authentication or authorization that will soon be deprecated. See the Migration Guide for more information.
《なぜこのように警告が表示されるのかはわかっていたが、古い認証方式から新しい認証方式への書き換えを促すために、わざと警告をChatGPTに示してみた》
A12.
ChatGPTは、非推奨になるAPIのことを知っている。
「Google Identity Servicesへの移行ガイド」を参考にして、移行することを推奨してくれた。
Q13.
では、具体的に、HTMLファイルと send_email.js はどのように書き換えればよいでしょうか。
A13.
HTMLファイルとsend_email.jsの新しい実装方法を提示してくれた。
《新しいことは知らないと思っていたので、ちゃんと回答してくれることに驚いた》
Q14.《回答が途中で途切れたので》
続けて
A14.
《回答の、説明とコードの表示が逆になっている:ChatGPTのバグか?》
Q15.
send_email.js の新しい実装コードが途中で途切れています。お手数ですが、もう一度 send_email.js のコードだけ教えてください。
《新しいコードを再度表示するよう求めた》
A15.
send_email.js の新しいコードを再表示。
Q16.
質問があります。HTMLファイルにクライアントIDを書くと誰もがクライアントIDを見ることができます。これは情報セキュリティ上の問題があるのではないでしょうか。
《コードについて質問》
A16.
クライアントIDは秘密情報ではないが、クライアントシークレットは秘密情報です。
Q17.
なるほどよくわかりました。誤解していてすみません。
《ちゃんとお礼しておく》
A17.
《励ましてくれた》
Q18.
新しいJavaScriptプログラムの名前は、send_email2.js に変えました。HTMLファイルからsend_email2.jsを読み込むようにしました。また、クライアントIDをHTMLファイルにセットしました。APIキーを書く場所が見当たりませんが、これはもう書かなくていいのでしょうか。
《質問:APIキーは必要ないのか?》
A18.
Google Identity Services(GIS)によって取得したアクセストークンがAPIキーの代わりになるので、APIキーは不要。
Q19.
新しいHTMLファイルとsend_email2.jsとをwebサーバに載せました。そして、Google Chromeで新らしいHTMLファイルにアクセスしました。ブラウザ画面にGoogleのロゴ付きで「Sign In」と書いてあるボタンがあったので、ログインしました。ここまでの手順は間違いないでしょうか。
《後で迷宮入りするといやなので、ここで手順を確認》
A19.
手順が正しい旨、回答。更に動作確認をするよう求められる。
Q20.《残念ながらメールの送信に失敗》
Google Chromeの画面に表示されている「Send Email」というボタンをクリックしました。しかし、メールは送信できず、「Failed to send email.」というアラート窓が表示されました。ディベロッパーツールのConsoleには「POST https://www.googleapis.com/gmail/v1/users/me/messages/send 401」と表示されています。更に、以下のようなErrorオブジェクトも表示されています。Errorオブジェクトの各キーの値を列挙します。
code: 401
message: "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."
status: "UNAUTHENTICATED"
A20.
認証情報が無効です。
解決策を提示。
Q21.
指示どおり、Chromeからログアウトし、再度ログインしました。また、ブラウザのキャッシュとCookieも削除しました。しかし、メールを送信できず、同じエラーが発生していました。そこで、send_email2.htmlの onSignIn 関数内で、教えてもらったコードと置き換えました。すると、今度はちゃんとメールを送信できるようになりました。どうもありがとう!!感謝感激です!!
《解決策どおりに行うとメールの送信に成功した》
A21.
素晴らしいですね!良かったです!
Q22.
何度もすみません。ChromeのConsoleをよく見ると以下のような警告がまだ表示されています。これを修正したコードではなかったのでしょうか。
Your client application uses libraries for user authentication or authorization that will soon be deprecated. See the Migration Guide for more information.
《しかし、まだ新しいコードにはなっていなかった》
A22.
失礼しました。以前の回答では警告メッセージの解消に焦点を当てていませんでした。
コードの変更箇所を提示。
《元々の趣旨を忘れているのかい?過去の入力も覚えているんじゃなかったのかい? と少しあきれる》
Q23.
念のため、書き直した後の新しいHTMLファイルのソースを教えてください。
A23.
HTMLのソースファイルの中身を提示。
Q24.
書き直した、send_email2.js も念のため教えてください。
A24.
send_email2.js の中身を提示。
Q25.
send_email2.jsにクライアントIDを書くところがありますが、HTMLファイルにも書くことになっていて二重に書くのはムダのような気がします。改善できないでしょうか。
《クライアントIDを2箇所に書いてあるがムダに感じ、改善を要請》
A25.
ムダを省いたコードの提示。
《この後もコードのムダな部分が発生する。冗長な箇所を取り除いた上でコードを提示してくれるわけではないようだ。コードのムダを省くのは最後に行うことにし、以後は冗長箇所の指摘はしないことにした》
Q26.
あとひとつ質問があります。send_email2.jsにAPIキーを書くところがありますが、APIキーは必要なのでしょうか。少し前で、「Google Identity Services ライブラリを使った場合はAPIキーが必要ない」という話をしたような気がするのですが。人間の私は記憶があいまいで申し訳ないですが、確認させてください。
《不要と言っていた「APIキー」を書く行があったので質問した》
A26.
APIキーは不要。
《回答に一貫性が感じられない。一貫性の確保は人の仕事なのかもしれない。》
Q27.
WebサーバにHTMLファイルと send_email2.js を載せ、Google ChromeでHTMLファイルにアクセスしてみました。しかし、「Send Email」ボタンが無効(グレー)になっており、クリックできません。ディベロッパーツールのConsoleには次のエラーが表示されております。どのように修正すればよろしいでしょうか。
[GSI_LOGGER]: Failed to render button before calling initialize().
《別のエラーが発生し、メールを送信できなくなった》
A27.
Google Identity Services ライブラリの初期化が完了する前にボタンを表示してることが原因とのこと。修正版を回答。
《完璧なコードを書いてくれるわけではないと気付く》
Q28.
変更したHTMLファイルの中に、data-login_uri という属性があります。この属性の値には何を書けばよいのでしょうか。
《コードについて質問》
A28.
data-login_uriは不要。
修正コードを提示。
《やはり冗長なコードを出力するのだなという印象》
Q29.
修正したHTMLファイルと send_email2.js をwebサーバにアップロードしました。WebブラウザにてHTMLファイルを再読込しました。
すると、Googleアカウントの「ログイン」ボタンがブラウザに表示されていましたので、クリックしました。すると、「Googleでログイン」窓が開きましたので、自分のGoogleアカウントをクリックしました。窓は自動的に閉じましたが、「Send Email」ボタンは無効(グレー)のままでクリックできません。Consoleにはエラーや警告は表示されていません。
《Send Emailボタンがグレーでクリックできない。元の課題からだんだん脇道(深い泥沼?)に入り込んでいく。Q34.まで混乱したやりとりが続く》
どのように修正すればよろしいでしょうか。
A29.
説明が不十分だったと追加のコードを提示。
《やはり完璧なコードを書いてくれるわけではないんだな》
Q30.
HTMLファイルを修正しwebサーバにアップロードしました。ブラウザでアクセスして、Googleアカウントでログインしました。しかし、まだ「Send Email」ボタンは無効のままです。Consoleにエラーや警告は表示されていません。
A30.
修正版を提示。
Q31.
onSignIn関数のコードを、send_email2.js の末尾に追加しました。webサーバに載せて、再度HTMLファイルをChromeで読み込みました。Googleアカウントでログインしましたが、やはり「Send Email」ボタンは無効のままです。
A31.
修正版を提示。
Q32.
おっしゃるようにHTMLファイルと send_email2.js を修正し、webサーバにアップロードしました。再度HTMLファイルをChromeで読み込みました。そしてGoogleアカウントでログインしてました。しかし、「Send Email」ボタンは無効のままです。ChromeのConsoleには何も表示されていません。
あと、HTMLに書き加えた signOut関数は send_email2.js に書いてもよいのではないでしょうか。
A32.
説明不足だったことを認め、修正版を提示。
《行き当たりばったりで修正しているだけではないかという疑惑が沸いてきた》
Q33.
HTMLファイルと send_email2.js を修正しwebサーバにアップロードしました。ブラウザでアクセスしましたところ、その直後に次のエラーが発生しています。gapiは古い形式の書き方だったのでは?
Uncaught ReferenceError: gapi is not defined send_email2.js:65
《古い形式の書き方が混ざっており、ちゃんと趣旨を理解しているのか不安になる》
A33.
修正版を提示。
Q34.
https://apis.google.com/js/platform.js はGoogleによって非推奨となりました。このため、https://apis.google.com/js/platform.js を使わないコードにしてください。
《あからさまに「古い形式」を提示してきたので、非推奨の旨を伝えた。ちょっといらついてきた》
A34.
別の古い形式でのコードを提示。
Q35.《仕切り直すことにした》
ちょっとお待ちください。https://apis.google.com/js/api.js もGoogleによって非推奨とされています。この一連のやりとりの前半で、Consoleに「Your client application uses libraries for user authentication or authorization that will soon be deprecated. See the Migration Guide for more information.」と表示されるので、「Google Identity Services ライブラリ」に移行しなければならなくなりました。その修正をしているのに、再び https://apis.google.com/js/api.js を使うのでは、本末転倒というものです。目的を見失わないようにお願いいたします。
《ChatGPTは迷宮入りしてしまっている。プログラム作成の趣旨も見失っている。本来の目的をきっちりと伝えた》
A35.
Google Identity Servicesライブラリへの移行について同意。
修正箇所を提示。
Q36.
すみません、人間の私は混乱してきました。お手数ですが、最新のHTMLファイルと send_email2.js のコードを全て表示してもらえますか。
《コードどうを書けばいいのか混乱してきた》
A36.
修正版のコードを提示。
Q37.《更に別のエラーが発生▶泥沼化》
HTMLファイルとsend_email2.jsを修正し、webサーバにアップロードしました。ブラウザでアクセスしたところ以下のエラーが発生しました。HTMLファイルの名前は gmail2.html としてありますので、この5行目で発生したエラーのようです。修正方法を教えてください。
gmail2.html:5 GET https://www.gstatic.com/gsi/client net::ERR_ABORTED 404
《URLが間違いなのは明白。ChatGPTがどう回答するか見もの》
A37.
スクリプトのURL間違いを認め修正版を提示。
《おいおい、読み込むべきスクリプトのURLを間違えるなんて、基本ができてないじゃないか。人間ならうっかり間違えることもあるけど、AIなのにどうしたことなの? この人(ChatGPT)ってほんとにプログラミングできるのかな、意味わかってプログラムを書いてるのかなと疑問が沸く》
Q38.
修正してHTMLファイルをアップロードしました。ブラウザでアクセスしたところ、https://your-domain.com/login にリダイレクトされてしまいます。この行は不要だったと思いますので削除して再度試して見ます。
《ChatGPTを信用できなくなってきたので、率先して間違いを直していくことにした》
A38.
間違いを認め、修正版を提示。
《どう直すかはわかってるので、修正版なんかいらないのにと思う》
Q39.
HTMLファイルを修正し、webサーバにアップロードしました。ブラウザでアクセスし、Googleアカウントにログインしました。しかし、「Send Email」ボタンは無効のままです。ブラウザのConsoleには何も表示されていません。どうもGoogleアカウントのログインボタンをクリックしても、Googleアカウントでログインした状態にならないようです。
《私の方でエラー発生の本質に気づき始める。そこで以下のように率先して修正。》
そこで、つぎのようにHTMLファイルを修正し、ブラウザでアクセスしたところ、ちゃんとGoogleアカウントでログインできました。しかし、エラーも発生しましたので、これはこの後お知らせします。
#HTMLファイル
<!DOCTYPE html>
<html>
<head>
<title>Send Email with Google Identity Services</title>
<script src="https://accounts.google.com/gsi/client" async defer>
</script><script src="send_email2.js" async defer>
</script>
</head>
<body>
<div id="g_id_onload"
data-client_id="YOUR_CLIENT_ID.apps.googleusercontent.com"
data-callback="handleCredentialResponse">
</div>
<div class="g_id_signin"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="sign_in_with"
data-size="large"
data-logo_alignment="left">
</div>
<button id="sendEmailButton" onclick="sendEmail()" disabled>Send Email</button>
<button id="signOutButton" onclick="signOut()" hidden>Sign Out</button>
</body>
</html>
A39.
内容について確認の旨、回答。
Q40.
ブラウザによる CORSブロックです。そもそも、Gmail APIでは「承認済みの JavaScript 生成元」によりアクセスが許可される話でした。XMLHttpRequestを使ったアクセスが良くないのではないでしょうか。
エラーの中身は次のとおりです。
Access to XMLHttpRequest at 'https://www.googleapis.com/oauth2/v4/tokeninfo?id_token=undefined' from origin 'https://www.akazawa.org' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
A40.
CORSエラーについての解説と、修正箇所の提示。
《しかし、非推奨のコードを提示してきた。完全に今回の趣旨を理解していないばかりか、ChatGPTは行き当たりばったりのコードしか書かないと確信》
Q41.
gapiは非推奨になったので使わないで欲しいのです。
《もうあきれている》
A41.
別の方法でのAPIアクセスを提示。
《APIアクセス方法を変えても仕方ないのでは? しかも、どこにも定義されてない関数まで使っている。これはもうダメだな》
Q42.
getIdToken関数を呼び出していますが、この関数はどこにも定義されていませんよね。
《もうこれはダメだ。でも一応指摘してみた》
A42.
謝罪と同意。
IDトークンが必要だからと、それを取得するようにコードを修正。
Q43.
念のため、修正した send_mail2.js のコードを以下に示します。間違いがあれば指摘してください。
《しかし、コードを提示する前にenterキーを押してしまった》
A43.
コードが見当たらないので、修正版のコードを提示してくれた。
Q44.
おお、すばらしい!!とうとう「Send Email」ボタンが有効になりました!!さすがはChatGPT-4ですね。これからボタンをクリックしますよ!
《急に解決!うれしい!意味はないかもしれないけど、一応おだてておく》
A44.
感謝の意。
Q45.
「Send Email」ボタンをクリックしました。しかし、残念ながら「Failed to send email.」というalert の小窓が開きます。ブラウザのConsoleには次のエラーが発生しています。fetch先のURLが存在しないようです。もうちょっとで完成と思いますので是非協力してください。よろしくお願いいたします。
https://www.googleapis.com/gmail/v1/users/me/messages/send 401
《しかし、残念ながらメールの送信には失敗した》
A45.
認証に問題がある旨の説明。
Bearerトークンを正しく設定するようにコードを修正。
《コードをチェックすると、定義していない googleUser を使っている。また勝手に架空のものを作って・・・やっぱりChatGPTだけに任せられないな・・・》
Q46.
その場合、googleUserが定義されていないので動作しないと思います。
《配慮しつつ指摘》
A46.
見落としていたと認める。
修正箇所を提示。
《AIてせも見落とすなんてあるんだ。困るな。また getIdTokenなんている定義してない関数も使っている。返値も使ってないのにこの関数は不要なんじゃないの?。行き当たりばったりだし、プログラムの意味も理解してないようだ。もうこれはダメだ》
Q47.
ここで、getIdToken関数が使われていますが、この関数が未定義です。返値も使っていませんから、この行は不要でありませんか。
A47.
あっさりgetIdToken関数の不要を認める。
修正版を提示。
Q48.
ではここで話を変えましょう。今までのことは忘れてください。
《見切りを付ける》
A48.
承知しました。新しい話題や質問があればお気軽にお聞かせください。どのようにお手伝いできるか教えていただければ幸いです。
《同意》
2. まとめ
前編での、WebサイトからGmailを使ってメールを送信するアプリケーションの開発を受けて、中編では、Googleの認証方式を非推奨の古い方式から新しい方式に書き換える作業に挑戦しました。
ChatGPTと共に作業するなかで以下のような数々の問題が発生しました。
冗長なコードが生成される。
メールの送信に失敗する。
完璧なコードを書いてくれるわけではない。
送信ボタンがグレーのままでクリックできない。
古い方式を持ち出してくる。
プログラムを作る目的を見失い、直近の問題解決に対処療法的にコードを生成している。
結果的には人が主導して正しいコードを提示しつつ、ChatGPTをガイドしていく必要性が出てきました。最終的には、この流れのままではプログラムの完成は無理と判断し、仕切り直すことにしました。
後編では視点を変えて、Googleの新しい認証方式に対応したプログラムへの書き換えに再度チャレンジします。