質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

1回答

1673閲覧

GAS、vueでの変数の扱いについて

zamzam24

総合スコア9

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2021/11/16 07:16

編集2021/11/18 08:00

前提・実現したいこと

※初心者です。初めに書いていなくてすみません。
GASとVueで、メール受信時に内容をスプレッドシートに転記し、
さらに転記したメールの内容をWebブラウザにアラートかプッシュ通知で表示するプログラムを
作成しようとしています。
※追記
taretailやいろんなサイトでメール、スプレッドシートの動かし方を知って、それをコピペ、編集したものになります。

エラーが起きると特定のエラーメールを受信するようにしているため、(別の機器)
それに合わせてメールの内容をスプレッドシート経由でHTMLブラウザに表示するようにしたいと思い作成を始めました。
メール内容をコピペしてシート2のA1に転載し、A1のデータをmaildataと共通させることでアラートとして出したいと考えています。
(アラートとして追記が一番やりやすそうだったのでそうしました)
メールをfunction:mainのトリガーを毎分起動して確認し、1分以内のエラーメールをシート2のA1に転載しています。(ここまでは大丈夫)
ついでにmaildataというグローバル関数に入れ込むことで、HTMLから参照できるかと思いましたがうまくいっていないです。
(A1への転載はうまくいっていますが、maildataがHTMLに送られていない?)
※追記終了

発生している問題・エラーメッセージ

Vueのwatch関数でmaildataに格納したメールデータを監視し、変化があった場合に表記させたいのですが、
maildataという変数を読み込めておらず、機能していないように思います。
(document.writeでmaildataでは表示されない?)
maildataを関数として使えるようにしたいのですが、宣言や定義そのものが足りない、間違っているのでしょうか。
どうしてもわからないため、教えていただけると助かります。

該当のソースコード

※appscript.json

json

1 2{ 3 "timeZone": "Asia/Tokyo", 4 "dependencies": { 5 "enabledAdvancedServices": [ 6 { 7 "userSymbol": "Gmail", 8 "version": "v1", 9 "serviceId": "gmail" 10 }, 11 { 12 "userSymbol": "Drive", 13 "version": "v2", 14 "serviceId": "drive" 15 } 16 ] 17 }, 18 "webapp": { 19 "executeAs": "USER_DEPLOYING", 20 "access": "MYSELF" 21 }, 22 "oauthScopes": [ 23 "https://www.googleapis.com/auth/spreadsheets.currentonly", 24 "https://www.googleapis.com/auth/spreadsheets", 25 "https://www.googleapis.com/auth/script.external_request", 26 "https://www.googleapis.com/auth/gmail.readonly", 27 "https://www.googleapis.com/auth/gmail.modify", 28 "https://mail.google.com/" 29 ], 30 "exceptionLogging": "STACKDRIVER", 31 "runtimeVersion": "V8" 32} 33

gs

1 2function doGet(e){ 3 var html = HtmlService.createTemplateFromFile("index").evaluate(); 4 var content = html.getContent(); 5 return HtmlService.createTemplate(content).evaluate(); 6 } 7 8function getData(ssId,sheetName) { 9 // スプレッドシートの取得 10 var ss = SpreadsheetApp.openById(ssId); 11 // データの取得 12 var values = ss.getSheetByName(sheetName).getDataRange().getValues(); 13 return values; 14} 15 16function fetchContactMail() { 17 //取得間隔 18 var now_time= Math.floor(new Date().getTime() / 1000) ;//現在時刻を変換 19 var time_term = now_time - (60 + 3); //63秒にして取得できない事態がないように 20 21 //検索条件指定 22 var strTerms = '(subject:{' + error + '} is:unread after:'+ time_term + ')'; 23 24 //取得 25 var myThreads = GmailApp.search(strTerms); 26 var myMsgs = GmailApp.getMessagesForThreads(myThreads); 27 var valMsgs = []; 28 for(var i = 0; i < myMsgs.length;i++){ 29 valMsgs[i] = " " + myMsgs[i].slice(-1)[0].getDate().getMonth() + "/"+ myMsgs[i].slice(-1)[0].getDate().getDate() 30 + " " + myMsgs[i].slice(-1)[0].getDate().getHours() + ":" + myMsgs[i].slice(-1)[0].getDate().getMinutes() 31 + "\n[from]" + myMsgs[i].slice(-1)[0].getFrom() 32 + "\n" + myMsgs[i].slice(-1)[0].getSubject() 33 valMsgs[i] = valMsgs[i] + "\n\n[Message]\n"+ myMsgs[i].slice(-1)[0].getPlainBody(); 34 35 } 36 return valMsgs; 37 } 38 39 function main() { 40var sheet = SpreadsheetApp.openById("スプレッドシートID").getSheetByName("シート2"); 41var t=HtmlService.createTemplateFromFile("index");//上で検索したメールをシート2に転載し、共通変数maildataに入れ込む。この処理が間違っている気がします 42 new_Me = fetchContactMail() 43 if(new_Me.length > 0){ 44 for(var i = new_Me.length-1; i >= 0; i--){ 45 sheet.getRange("A1").setValue(new_Me[i]); 46 t.new_Me[i] = maildata; 47 48 } 49 } 50} 51 52function include(filename) { 53 return HtmlService.createTemplateFromFile(filename).evaluate().getContent(); 54} 55 56//追加 57var sheet = SpreadsheetApp.openById("1HPx6SzFB8hdd37bwCianXOC5L2Yya2Xu4CmBQzlRAWY").getSheetByName("シート2"); 58var errormail = sheet.getRange("A1").getValue(); 59function newmail(){ 60 return SpreadsheetApp.openById("シートID").getSheetByName("シート2").getRange("A1").getValue(); 61} 62

html

1//変更後 2<!DOCTYPE html> 3<html> 4 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 5 <head> 6 <base target="_top"> 7 8 <!-- vue.js --> 9<meta charset="UTF-8"> 10 11 <?!= include('js'); ?> 12 13 </head> 14 <body> 15 16<div id= "app" > 17 <p>{{ message }}</p> 18 </div> 19<?!= include('css'); ?> 20 21 22</body> 23</html>

html

1//変更前 2<!DOCTYPE html> 3<html> 4 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 5 <head> 6 <base target="_top"> 7 8 <!-- vue.js --> 9<meta charset="UTF-8"> 10 </head> 11 <body> 12 13 <?!= include('js'); ?> 14 15<script> 16 17 window.hex = () => { 18 document.alert("検知しています") 19 } 20 21</script> 22 23</body> 24</html>

js

1 2<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 3 4<script> 5google.script.run.withSuccessHandler(vuetest).newmail(); 6 7function vuetest(message){ 8 new Vue({ 9 el: "#app", 10 data:{ 11 message : message 12 }, 13 watch:{ 14 message:function(){ 15alert(message) 16 }, 17 } 18}); 19} 20</script>
//消去 <script> var vm = new Vue({ el: "#vm", data: { message: maildata }, watch:{ message:{ window.hex() document.alert("変更を検知しました") } } }) </script>

試したこと

追加・変更部分で、messageをメールの中身に変更はできました。ただ、メールに対応してシート2A1が変化しても、Webアプリでは何も変化しません。
メッセージという変数参照では呼び出している中身が変化しても、下の処理は行われないのでしょうか?

補足情報(FW/ツールのバージョンなど)

GASのWebブラウザで編集しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/11/16 10:28 編集

やりたいことは以下のようなことでしょうか? ・同じような内容のメールが、指定のGmailアカウントの受信フォルダに 一定間隔または不定期に送信されるようになっている ・任意のタイミング(☆)でその受信フォルダの最新のメール1通の内容を読み取り、 そのメールの内容が以前に取得していた内容から変化している場合は、プラウザにアラートを出して通知する。 また、変化の有無を監視しようとしているのはmaildataという変数のようですが、 その前段階の「fetchContactMail」関数の内容がいまいちわかりません。 (そもそも質問のコードには、maildataという変数がどこにも定義されていないように見受けられます) 質問に記載されていない部分を含めて、可能な限り全部のコードを記載していただけないでしょうか? (コメント欄ではインデントが省略されてしまいますので、コードはこのコメントの続きではなく、 編集ボタンを押して質問文自体を編集して記載ください)
zamzam24

2021/11/16 14:44

やりたい機能の仕様と併せて、明日出させていただきます。fetchcontactmail変数で指定の文面を含み、2分以内に受信したメールの内容を取り出しています
退会済みユーザー

退会済みユーザー

2021/11/17 13:30 編集

「試したこと」の「変数ではない数値の入出力はできた」というのは、どの部分のことを言っているのでしょうか? あと、 new_Meという変数は、複数のメール内容を持ち得る配列として扱われています。 最新のメール1通だけを比較すればよいのではないかと思うのですが、なぜnew_Meは配列にしているのでしょうか。
zamzam24

2021/11/17 23:09

出力のmaildataをhogehogeとかに変えたら文字がHTML上にでたくらいです。しょうもないことですみません。 new_Me部分も自分ではうまくできなかったので、公開されていたコードを利用させてもらっています。 前提として書いていなくてすみませんでした。
guest

回答1

0

ベストアンサー

バックエンド(GAS)内での変数maildataの変化を、フロント(js.html?)内のVueのwatchプロパティで
直接監視することはできません。

アプローチとしては、
(1)GAS側は、「最新のメールを取得し、直近のメールの内容を文字列にして返す」関数を実装したウェブアプリとして作成。
(2)フロント側(index.html)で、setIntervalを利用して一定間隔で(1)の関数を呼び出し、
返ってくる文字列をVueのwatchで監視。変化がある場合はalertで表示する。

という方向になろうかと思います。

フロント(html)から、バック(GAS)内の関数を呼び出す、という流れです。
(つまりGAS側からフロントエンド(ブラウザ)へのプッシュ通知ではなく、フロントエンド側からGASのデータをプルしてくる形です)


下記は参考のコードです。

【コード.gs】
※GAS側のトリガー設定は、スプレッドシートに常時一定間隔でエラー内容を記載する必要がなければ不要です。

js

1// エラーメールの内容を記録するシート 2var sheet = SpreadsheetApp.openById("スプレッドシートID").getSheetByName("シート2"); 3// 直近のエラーメールの内容 4var errormail = sheet.getRange("A1").getValue() 5 6/* 7* 最新のメールを取得し、日時・本文を加工して返す関数 8*  戻り値: 9*  条件に合致するメールがある場合:最新のメールの内容(string) 10*  条件に合致するメールがない場合:null 11*/ 12function fetchContactMail() { 13 // 現在時刻 14 var now_time = Math.floor(new Date().getTime() / 1000); 15 16 // 検索条件:現在時刻から63秒以内に受信した未読メール 17 // (ただしエラーメールの内容が空白の場合、一週間以内まで範囲を広げる) 18 var pasttime = errormail !== '' ? 60 + 3 : 60*60*24*7; 19 var time_term = now_time - pasttime; 20 var strTerms = '(is:unread after:' + time_term + ')'; 21 22 //最新のメールを取得 23 var myThreads = GmailApp.search(strTerms, 0, 1); 24 var myMsgs = GmailApp.getMessagesForThreads(myThreads); 25 if (myMsgs.length == 0) return null; 26 var msg = myMsgs[0].slice(-1)[0]; 27 // メール日時・本文の取得・加工 28 var valMsg = " " + (msg.getDate().getMonth() + 1) + "/" + msg.getDate().getDate() 29 + " " + msg.getDate().getHours() + ":" + msg.getDate().getMinutes() 30 + "\n[from]" + msg.getFrom() 31 + "\n" + msg.getSubject() 32 + "\n\n[Message]\n" + msg.getPlainBody(); 33 34 sheet.getRange("A1").setValue(valMsg); 35 return valMsg; 36} 37 38function doGet(e) { 39 var html = HtmlService.createTemplateFromFile("index").evaluate(); 40 var content = html.getContent(); 41 return HtmlService.createTemplate(content).evaluate(); 42} 43

【index.html】

HTML

1<!DOCTYPE html> 2<html> 3<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 4 5<head> 6 <base target="_top"> 7 <meta charset="UTF-8"> 8</head> 9 10<body> 11 12 <div id="app"> 13 <p>{{ message }}</p> 14 </div> 15 16 <script> 17 new Vue({ 18 el: "#app", 19 data: function() { 20 return{ 21 // 初期値を設定 22 message: <?= errormail ?> 23 } 24 }, 25 created () { 26 setInterval(() => { 27 // 1分ごとに最新のメールの内容を取得(GAS側の関数を呼び出し、 28 // 戻り値を引数にしてchangeValメソッドを呼び出す。) 29 google.script.run.withSuccessHandler(this.changeVal).fetchContactMail(); 30 }, 60000) 31 }, 32 watch: { 33 message: function(newMsg) { 34 alert("新しいエラーメールを受信しました。\n" + newMsg); 35 }, 36 }, 37 methods: { 38 changeVal :function(val) { 39 var vm = this; 40 vm.message = val; 41 } 42 } 43 }); 44 </script> 45</body> 46</html>

 

・補足
元の質問文のコードのfetchContactMail()について:

function fetchContactMail() { for(var i = 0; i < myMsgs.length;i++){ valMsgs[i] = " " + myMsgs[i].slice(-1)[0].getDate().getMonth() + "/"+ myMsgs[i].slice(-1)[0].getDate().getDate() + " " + myMsgs[i].slice(-1)[0].getDate().getHours() + ":" + myMsgs[i].slice(-1)[0].getDate().getMinutes() + "\n[from]" + myMsgs[i].slice(-1)[0].getFrom() + "\n" + myMsgs[i].slice(-1)[0].getSubject() valMsgs[i] = valMsgs[i] + "\n\n[Message]\n"+ myMsgs[i].slice(-1)[0].getPlainBody(); }

おそらく、「一定期間内のすべてのメールから、本文に特定の単語が含まれているものを抜き出す」スクリプトのようなものをコピペされたのだと思いますが、
今回は最新のメールだけ取得できれば良いので、for文でループさせる必要はありません。

var myThreads = GmailApp.search(strTerms, 0, 1); var myMsgs = GmailApp.getMessagesForThreads(myThreads); if (myMsgs.length == 0) return null; var msg = myMsgs[0].slice(-1)[0];

のようにすることで、strTermsに指定した条件に合致する最新のメールを取得できます。

元の質問文のコードのmain()について:

function main() { 略 new_Me = fetchContactMail() if(new_Me.length > 0){ for(var i = new_Me.length-1; i >= 0; i--){ sheet.getRange("A1").setValue(new_Me[i]); t.new_Me[i] = maildata; } }

t.new_Me[i] = maildata;
の部分ですが、maildataはどこにも定義されていないのでエラーになると思います。
(フロント側で定義されているように見えてもバック側では共有されません)

回答のコードでは、プリンティングスクリプトレットを使用して、GAS側のグローバル変数 errormailの内容(文字列)を、
Vueのmessageの初期値に設定しています。(下記)
(このように、ページの読み込み時にGAS側の変数の内容をフロントに渡すことは可能です)

diff

1 new Vue({ 2 el: "#app", 3 data: function() { 4 return{ 5 // 初期値を設定 6+ message: <?= errormail ?> 7 } 8 },

投稿2021/11/18 13:08

編集2021/11/18 23:01
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zamzam24

2021/11/18 23:00

ありがとうございます! 確認して挑戦させて頂きます 色々ご丁寧に教えていただけて助かります!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問