テストでGoogleフォームを使うと、「解説PDFを配布したい」一方で、こんな問題が起きがちです。
- DriveのPDFを「大学内のユーザー」に共有すると、フォーム回答前にURLを回されて先に読めてしまう
- 「リンクを知っている全員」共有にすると、当然もっと危険
- でも、フォーム回答後はすぐ解説を配りたい
そこで今回は、フォーム回答者にだけDriveのPDF閲覧権限を自動付与し、URLをメールで送る仕組みをGAS(Google Apps Script)で作ります。
この記事でできること(ゴール)
フォーム送信後に自動で:
- 回答者のメールアドレスを取得(※フォーム設定で「メールアドレスを収集」ON)
- 解説PDFを「非公開」にしたまま、回答者だけを閲覧者に追加
- 解説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転送
をかなり抑止できます。
授業運用の小テスト・解説配布にちょうどいい仕組みです。