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

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

ただいまの
回答率

88.81%

ウエブアプリケーションとして公開の仕方について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 833

yuko0524

score 21

(前回の質問で解決したと先走ってしまいましたが、やはりうまくいきませんでした。
まだGASに対する自分の理解が浅かったようです。)

実現したいことは、
自分が開発したGASアプリを他人(社内のアカウント)に使わせたい、ということです。

フォームとスプレッドシートを使った承認ワークフローを作りました。
スクリプト中でGmailAppをつかってメール送信しています。
自分が実行する分には問題なく意図するように動きます。

<ワークフローのイメージ>
①フォームにて申請者(自分)が項目入力後、送信⇒Gメール
⇒②A部長⇒(承認)⇒Gメール
⇒③B部長⇒(承認)⇒Gメール
⇒④自分
<ウエブアプリケーションとして公開の内容>
・次のユーザーとしてアプリケーションを実行:ウェブアプリケーションにアクセスしているユーザー
・アプリケーションにアクセスできるユーザー:kaisha.co.jpの全員

①のフォームのURLをAさんに送り、使わせようとしたら、①でコケました。
メールが送信されません。
実行者はAさんなので、Aさんが申請者となり、Gメールの送信元もAさんのアドレスとなると思って
使わせようとしておりました。

その後、ネットで調べまくりましたが、
「メールを送信するMailAppを使っている場合、Fromの送信者アドレスはウェブアプリケーションとして
公開した人のアドレスになります」という記載を見つけました。
これが原因でコケたのでしょうか。

そうなってしまうと、やりたいことが実現できなくなります。

Aさんだけでなく、Bさん、Cさんにもそれぞれが申請者で使わせたいのですが
どのような作り方をすれば良いのでしょうか。
Aさんのアカウントでログインしてスクリプトを書いて公開しないとダメなのでしょうか。

ちなみに、トライしたこととして、
Aさんに直接トリガー(フォーム送信時)を追加してもらいましたが、結果は同じで送信できませんでした。

以上、よろしくお願いいたします。

gsコード追記
★コード.gs
//scriptの所在
var url = "https://script.google.com/a/kaisha.co.jp/macros/s/AKf***bx4o**dYr0x*****XOM-Vs**qr*6*r-2S***wc4*UV6/exec";

//共有フォルダ
var url2 = "https://drive.google.com/drive/folders/1***Yc*gn*zQ*0Q*5ybS***r?usp=sharing";

var sheetName = "フォームの回答 1";

// FormApp.getActiveForm();

function sendFormMail(e) {

  // 追加行
  var row = e.range.getRow();   
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName(sheetName);
  var name = e.namedValues["申請者"];
Logger.log(url2)
  var root = e.namedValues["申請ルート選択"];
  var drv = url2;
  var user = getUserBy("name", name ,root);
  // 承認者
  var authorizer = getUserBy("id", user['authorizer_id'], root);
  var address = authorizer['mail'];
  var authorizer_nm = authorizer['name'];

  var cols = ["申請日","申請者","申請ルート選択","稟議案件名","コメント","タイムスタンプ"];
  var body="";
      body += authorizer_nm + '様<br>'
      body += '<br>';
      body += '<span style="font-weight: normal">いつもお世話になっております。<br></span>';
      body += '<br>';
      body += '下記内容をご確認くださいますよう、よろしくお願いします。<br>';
      body += '<br>';
      cols.forEach(function(col){
          body +=  col ;
          body += " : " ;
          body += '<b><font color="#0000cd">' + e.namedValues[col] + '</font></b>';
          body += '<br>';
      })

      body += '<br>';
      body += '下記ボタン【資料確認・承認ページ】をクリックしてください。<br>';


      body += '<a href="'+url+"?row=" + row +"&name=" + encodeURI(authorizer['name']) + "&root=" + encodeURI(root) + "&drv=" + encodeURIComponent(drv);
      body += '"><button type="button"><font size="3" color="#ff00ff">資料確認・承認ページ</font></button></a>';
      Logger.log('address :%s', address);
      Logger.log('authorizer_nm :%s', authorizer_nm);

      GmailApp.sendEmail(address,         //宛先
                     '設備投資稟議:承認依頼', //件名
                     body ,                  //本文
                    {htmlBody: body} ,
                         {noReply: true}
      );
}


function getUserBy(key, value, root){
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sh = spreadsheet.getSheetByName(root);
  var values = sh.getDataRange().getValues();
  var keys = headerKeys(sh);

  for (var i = 0; i < values.length; i++) {
    var row = values[i];
    row = rowToHash(row, keys); 
    if (row[key] == value) {
      return row;
    }
  }
}

// ヘッダ行を取得
function headerKeys(sh) {
  return sh.getRange(1,1,1, sh.getLastColumn()).getValues()[0];
}

//行の情報をオブジェクトに変換
function rowToHash(array, keys) {
  var hash = {};
  array.forEach(function(value, i) {
    hash[keys[i]] = value;
  })
  return hash;
}


// 承認ページ表示時
function doGet(e) {
  //必要な値を画面に持たせておく
  var row = e.parameter.row;
  var name = e.parameter.name;
  var root = e.parameter.root;
  var drv = e.parameter.drv;

  var html = HtmlService.createTemplateFromFile("shonin");

  html.row = row;
  html.name = name;
  html.root = root;  
  html.url = url;
  html.drv = drv;

  html.method = "get";

  Logger.log('html  :"%s"', html);

  return html.evaluate();

}

function doPost(e) {
  var shonin = e.parameter.shonin;
  var row = e.parameter.row;
  var name = e.parameter.name;
  var root = e.parameter.root;
  var drv = e.parameter.drv;
  // シートに承認を記入
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName(sheetName);
//    Logger.log(sheet);

  var values = sheet.getDataRange().getValues();

  var rowData = values[row-1];
  var idx = rowData.length;

  var status = "";

  var timestamp = Utilities.formatDate( new Date(), 'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss');


  var cur = -1;
  rowData.some(function(col,i){
    if (!col){//空の列を取得
      idx = i;
      return true;
    }
  });
  idx++;

  if (shonin == 1) {
    status = "承認";
  } else {
    status = "却下";
  }

  sheet.getRange(1, idx).setValue("状態");
  sheet.getRange(row, idx).setValue(status);
  idx++;

  sheet.getRange(1, idx).setValue("承認者");
  sheet.getRange(row, idx).setValue(name);
  idx++;

  sheet.getRange(1, idx).setValue("処理日時");
  sheet.getRange(row, idx).setValue(timestamp);

  // 承認者をメールに記載するため再取得
  values = sheet.getDataRange().getValues();

  if (shonin == 1) {

    // 次の承認者をさがす
    var user = getUserBy("name", name, root);
    var authorizer_id = user['authorizer_id'];

    if (authorizer_id) {//上位承認者がいる場合
      // 次の承認者にメール送信
      var authorizer = getUserBy("id", authorizer_id ,root);
      Logger.log(name + 'のauthorizer_idは'+ authorizer_id);
     sendMail(values, row, authorizer, drv, root, true);

    }
  } else {
    // 却下時は申請者にメール送信
    var name = sheet.getRange(row, 2).getValue();
    var user = getUserBy("name", name, root);
    sendMail(values, row, user, drv, root, false);
  }
  var html = HtmlService.createTemplateFromFile("complete");
  return html.evaluate();
}


function sendMail(values, row, user, drv, root, approved){
    var rowData = values[row-1];
    var body="";
    body += '<br>';
    body += user['name'] + '様<br>'
    body += '<br>';
    body += '<span style="font-weight: normal">いつもお世話になっております。<br></span>';
    body += '<br>';
    body += '下記内容をご確認くださいますよう、よろしくお願いします。<br>';
    body += '<br>';
    rowData.forEach(function(col,idx){
    if (!col) return true;
    var key = values[0][idx];
    body += key;
    body += " : ";
    if (['申請日'].indexOf(key) > -1) {
      body += '<b><font color="#0000cd">' + Utilities.formatDate( col, 'Asia/Tokyo', 'yyyy年M月d日') + '</font></b>';
    } else if (['処理日時'].indexOf(key) > -1) {
      body += '<b><font color="#0000cd">' + Utilities.formatDate( col, 'Asia/Tokyo', 'yyyy年MM月dd日 HH:mm:ss') + '</font></b>';
    } else if (['共有ドライブのリンク先'].indexOf(key) > -1) {

    }else {
      body += '<b><font color="#0000cd">' + col + '</font></b>';
    }
    body += '<br>';
  });

  if (approved==true){
      body += '<br>';
      body += 'ボタン【資料確認・承認ページ】をクリックしてください。<br>'
      body += '<a href="'+url+ "?row=" + row +"&name=" + encodeURI(user['name']) + "&root=" + encodeURI(root) + "&drv=" + encodeURIComponent(drv);
      body += '"><button type="button"><font size="3" color="#ff00ff">資料確認・承認ページ</font></button></a>';      

  }else{    
    body += "承認が却下されました。";
  }

  var address = user['mail'];
  var title = approved ? "設備投資稟議:承認依頼" : "承認依頼が却下されました";
  GmailApp.sendEmail(address, 
                     title, 
                     body ,
                    {htmlBody: body} ,
                    {noReply: true});
}

  

HTML追記
★complete.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <h3>----------------------------------------------------------------------</h3>
    <h3><b> 【処理完了】次の承認者へ通知完了。このタブを閉じてください。</b></h3>
    <h3>----------------------------------------------------------------------</h3>   
  </body>
</html>


★shonin.html
<!-- 承認リンクURLが押されたときに表示する画面 -->
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
        h1 {
         font-weight: normal;
        }
        h2 {
        font-weight: normal;
        }
        h3 {
        font-weight: normal;
        }
        h4 {
        font-weight: normal;
        }
        h5 {
        font-weight: normal;
        }
    </style>
  </head>
  <body>
    <h4>---------------------------------------------------------</h4>
    <h3><b>    設備投資稟議:承認依頼画面</b></h3>
    <h4>---------------------------------------------------------</h4>     
        <h4>  下記<font color="#FF00FF">リンク</font>より稟議資料の内容をご確認いただき、共有ドライブ上にて承認印・コメント入力をお願いします。</h4>
        <h4>  <a href="<?= drv ?>" target="_blank"><font color="#FF00FF">稟議資料へのリンク(共有ドライブ)</font></a></h4>
        <h4>  捺印、入力終わりましたら、下の<font color="#0033FF">承認</font>或いは<font color="#0033FF">却下</font>を選択して<font color="#0033FF">送信</font>してください。</h4>
    <form action="<?= url ?>" method="post">
      <h3><b>  <input type="radio" name="shonin" value="1" checked="checked">承認
      <input type="radio" name="shonin" value="0">却下
      <input type="hidden" name="row" value="<?= row ?>">
      <input type="hidden" name="name" value="<?= name ?>">
      <input type="hidden" name="root" value="<?= root ?>">
      <input type="hidden" name="drv" value="<?= drv ?>">      
      <input type="submit" value="送信"></b></h3>
        <h5>  ◆承認のとき ・・・次の承認者へ承認依頼メールが送られます。</h5> 
        <h5>  ◆却下のとき ・・・申請者へ却下通知メールが送られます。</h5> 
    </form>
  </body>
</html>
承認ルート(画像)

イメージ説明

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yuko0524

    2019/05/07 12:01

    ご回答ありがとうございます。
    申請者の名前の一致は確認しており、私が申請者となって実行する分には、
    問題なく次の承認者にGメールが送信されます。このときのアカウントは
    当然ながら私です。
    ところが、違う人(Aさんとします。AさんのPCで実行します。アカウントはAさんです)に私の作ったこのツールを使わせると(共有ドライブに置いています)、コケてしまうんです。
    次の承認者にメールが行かず、undefined からプロパティ「mail」を読み取れません云々のエラーとなります。
    私が思い込みをしていて気づかない部分があるのかもしれませんが、
    実行するユーザーが関係しているのでしょうか。

    キャンセル

  • hiroshi0240

    2019/05/07 12:17

    Logger.logでuserとauthorizerの値を取ってみて下さい。

    キャンセル

  • yuko0524

    2019/05/07 16:38

    ログの出力結果になります。
    user --> {authorizer_id=, mail=*****@kaisha.co.jp, name=〇田, id=1.0}
    authorizer ーー> undefined
    でGメール送信ならず、でした。

    承認ルートのリスト一覧の画像を、質問に追記しました。

    id=1とid=6は同一者になります。
    id=6が起票者(申請者)で、最終的に起票者に完了を伝える意味でid=1にも同じ人を指定しています。
    この結果を見ると、id=1を拾っていますね。
    id=6を拾っていたと思い込んでいました。ログでの確認を軽視しておりました。すみません。
    ご指摘ありがとうございます。
    となると、ここが原因のような気がします。
    もう少しテストしてみて、結果をご報告いたします。

    キャンセル

回答 2

+1

ご質問、回答からundefinedになっているのが、ユーザーデータ(送信者設定用メールアドレス)と推察し、ご回答します。
まず、Googleフォームから送信のトリガーを受け取ってメール送信するのであれば、スクリプトの実行者(メールの送信者)はトリガーの設定者になると思います。(送信者にトリガー設定者のアドレスを入れたくなければオプションでnoReply:trueをいれればOK)
フォーム送信者名を取りたい場合はパラメータから.response.getRespondentEmail();で受け取れますが、メール送信者にはできないかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/26 13:06

    ご回答、誠にありがとうございます。
    質問させてください。
    もし、「送信者にトリガー設定者のアドレスを入れたくなければオプションでnoReply:true」を採用して
    メール送信された場合、そのメールは誰の送信済みに入ってくるのでしょうか。ツールを実行した人ですか?それともスクリプトのオーナーである私でしょうか。

    キャンセル

  • 2019/04/26 13:31 編集

    あ、すみませんnoReplyオプションはG Suite契約アカウントでしか使えないみたいですが、その場合送信者はnoreply@G Suite契約ドメインになりますので、どちらのアカウントの送信履歴にも残りません。

    キャンセル

check解決した方法

0

おかげ様で解決しました。
私の承認ルートの作り方に問題がありました。

最終ルート(id=1)のnameを変えたら
(〇田 → 〇田_最終通知)、
意図する通り、最後までGメール通知での承認フローが流れました。

一人で騒いで勝手に解決となり、大変申し訳ございません…。
ご協力本当にありがとうございました。
思い込みをせず、logを確認することを肝に銘じます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.81%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る