【GAS×Googleフォーム】回答者だけに解説PDFの閲覧権限を自動付与してメール送付する方法(URL漏れ対策)

テストでGoogleフォームを使うと、「解説PDFを配布したい」一方で、こんな問題が起きがちです。

  • DriveのPDFを「大学内のユーザー」に共有すると、フォーム回答前にURLを回されて先に読めてしまう
  • 「リンクを知っている全員」共有にすると、当然もっと危険
  • でも、フォーム回答後はすぐ解説を配りたい

そこで今回は、フォーム回答者にだけDriveのPDF閲覧権限を自動付与し、URLをメールで送る仕組みをGAS(Google Apps Script)で作ります。

目次

この記事でできること(ゴール)

フォーム送信後に自動で:

  1. 回答者のメールアドレスを取得(※フォーム設定で「メールアドレスを収集」ON)
  2. 解説PDFを「非公開」にしたまま、回答者だけを閲覧者に追加
  3. 解説PDFのURLを回答者にメール送信

つまり、URLを誰かに転送されても 権限がない人は開けない ので、
「回答した人だけが解説を見られる」状態を作れます。

前提条件(ここができてないと動かない)

1) フォーム側の設定

フォームの設定で:

  • ✅ 「メールアドレスを収集」ON

これがOFFだと getRespondentEmail() が空になり、誰にも送れません。

2) 解説PDFはDriveに置いておく

解説PDFのURLをコードに貼ります。

以下のプログラムをグーグルフォームに入力

①グーグルフォームの右側の3つの縦の点をクリック

②「Apps Script」をクリック

③プログラムをコピペ

④Ctrl + Sで保存

// ★解説PDFの共有URL(そのまま貼る) 以下のURLを消してURLを貼ってください。
const EXPLANATION_PDF_URL =
  "https://drive.google.com/file/d/1o????????????????????????????/view?usp=drive_link";

// (任意)テスト送信用:自分のメール
const ADMIN_EMAIL = "あなたの大学メール@xxx.ac.jp"; // ★必要なら変更

function onFormSubmit(e) {
  // ---- 手動実行対策:e が無いなら説明して終了 ----
  if (!e || !e.response) {
    Logger.log("onFormSubmit は手動実行できません。フォーム送信トリガーで動かしてください。");
    Logger.log("手順:installTrigger() を1回実行 → フォームを送信");
    return;
  }

  const response = e.response;

  // 回答者メール(フォームで「メールアドレスを収集」ONが必須)
  const to = (response.getRespondentEmail && response.getRespondentEmail()) || "";
  if (!to) {
    Logger.log("回答者メールが取得できません。フォーム設定で「メールアドレスを収集」をONにしてください。");
    return;
  }

  // PDFファイルIDをURLから抽出して取得
  const pdfId = extractDriveFileId_(EXPLANATION_PDF_URL);
  const pdfFile = DriveApp.getFileById(pdfId);

  // PDFは非公開のままにして、送信者にだけ閲覧権限付与
  // ※これを入れると既存共有設定を上書きするので、この方法で配布する運用ならOK
  pdfFile.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE);
  pdfFile.addViewer(to);

  // メール送信
  const subject = "【解説PDF】閲覧権限を付与しました";
  const body =
    "回答お疲れさまでした。\n\n" +
    "解説PDFをあなたのGoogleアカウントで閲覧できるようにしました。\n" +
    "▼解説PDF\n" + EXPLANATION_PDF_URL + "\n\n" +
    "※開けない場合:右上のアカウントが、Googleフォームに回答したアカウントかを確認してください。\n";

  GmailApp.sendEmail(to, subject, body);

  Logger.log("Mail sent to: " + to);
}

// トリガーを作成(これだけ手動で1回実行)
function installTrigger() {
  // 既存トリガーを整理(重複防止)
  const triggers = ScriptApp.getProjectTriggers();
  triggers.forEach(t => {
    const fn = t.getHandlerFunction();
    if (fn === "onFormSubmit" || fn === "installTrigger") {
      ScriptApp.deleteTrigger(t);
    }
  });

  // フォーム送信時トリガーを作る
  ScriptApp.newTrigger("onFormSubmit")
    .forForm(FormApp.getActiveForm())
    .onFormSubmit()
    .create();

  Logger.log("Trigger installed: onFormSubmit (フォーム送信時)");
}

// メール送信だけ単体テスト(任意)
function testSendMail_() {
  GmailApp.sendEmail(ADMIN_EMAIL, "GASテスト", "GASからメール送信できています");
}

// Drive URLからIDを抜く
function extractDriveFileId_(urlOrId) {
  const s = String(urlOrId).trim();

  // すでにIDっぽいなら返す
  if (/^[a-zA-Z0-9_-]{20,}$/.test(s)) return s;

  // /d/FILE_ID/ を抜く
  const m = s.match(/\/d\/([a-zA-Z0-9_-]+)\//);
  if (m && m[1]) return m[1];

  // id=FILE_ID 形式
  const m2 = s.match(/[?&]id=([a-zA-Z0-9_-]+)/);
  if (m2 && m2[1]) return m2[1];

  throw new Error("DriveファイルIDをURLから抽出できません: " + s);
}

トリガーの設定

①左側の「トリガー」をクリック

②「+ トリガーを追加」をクリック

③以下を設定

onFormSubmit
Head
フォームから
フォーム送信時

④「保存」をクリック

セキュリティ上の注意(現実的な話)

この方法は「URLを回されても見れない」のでかなり強いです。
ただし、閲覧できた学生が

  • PDFをダウンロードして配布する

のは完全には防げません(人間側の運用が必要)。

まとめ

Driveの共有設定だけだと、どうしても「URLが漏れたら終わり」になりがちです。
今回の方法は、フォーム回答をトリガーにして個別アカウントへ閲覧権限を付与するので、

  • 事前入手
  • URL転送

をかなり抑止できます。

授業運用の小テスト・解説配布にちょうどいい仕組みです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

GoodMorning!

デジタルの海原を冒険しながら、美食の宝を探し求める探検家です。テクノロジーの世界を舞台に、新しい発見を求めて、キーボードの海を横断。そして、実世界では、隅々まで足を運んで、舌鼓を打つ価値のある美味しいお店を見つけ出します。

私の使命は、小さなITの豆知識から始まり、心を満たすグルメスポットの紹介まで、あなたの日常にちょっとしたスパイスを加えること。画面の向こう側から、気軽に楽しめる話題を届けたいのです。ここでは、私が「これは!」と思った技術的な小話や、舌の記憶に残るような食べ物屋さんを紹介していきます。

このWebサイトは、ITとグルメ、二つの世界を融合させた、まさにデジタルと現実の融合点。ふらっと立ち寄って、新たな発見や、ほっこりするような話題で一息ついていただけたら幸いです。知識の海を冒険し、味覚の旅を楽しみましょう。毎日を少しだけ特別なものに変える、そんな情報をお届けします。

GoodMorning!

I am an explorer who ventures across the digital sea in search of gastronomic treasures. In the world of technology, I traverse the sea of keyboards in search of new discoveries. And in the real world, I visit every nook and cranny to find a delicious restaurant worth tantalizing your taste buds.

My mission is to add a little spice to your everyday life, starting with little IT tidbits and ending with foodie spots that fill your heart. I want to bring you topics that you can easily enjoy from the other side of the screen. Here, I'm going to share with you some of the technical tidbits and I will introduce small technical stories and food shops that will leave a lasting impression on your taste buds.

This Web site is truly a fusion point of digital and reality, combining the two worlds of IT and gourmet. I hope you will stop by and take a breather with new discoveries and dusty topics. Come explore the sea of knowledge and enjoy a journey of taste. I will bring you the information that will change your everyday life into something a little more special.

目次