Gmailの添付ファイルを、
ドライブに自動保存する(GAS)。
取引先から届く請求書・見積書・注文書のPDFを、毎回ダウンロードしてフォルダに入れ直していませんか。このページでは Google Apps Script(GAS)で、Gmailの添付ファイルを指定のGoogleドライブのフォルダへ日付つきで自動保存し、保存した記録をシートに残す方法を、よくある失敗(二重保存・取りこぼし・途中で止まる)の対策込みで紹介します。
1. できること
| 項目 | このページのコード |
|---|---|
| 対象のメール | Gmailの検索式で指定(送信元・件名・ラベルなど)。例:from:(billing@example.com) has:attachment newer_than:3d |
| 保存するファイル | 拡張子で限定(PDF・Excel・CSVなど)。5KB未満(署名のロゴ画像など)と本文埋め込み画像は保存しない |
| ファイル名 | 20260924_請求書.pdf のように受信日を先頭に。ドライブで使えない記号は置き換え |
| 記録 | 「保存ログ」シートに メールID・受信日・送信元・件名・保存数・ドライブのURL |
2. 準備
- 保存先にしたいGoogleドライブのフォルダを開き、URLの
folders/の後ろの文字列(フォルダID)をコピーします。 - 新しいスプレッドシートを作り、「拡張機能 → Apps Script」を開いて下のコードを貼り付け、
FOLDER_IDを書き換えます。 - ▶ で
saveAttachmentsを一度実行し、Gmail・ドライブ・シートの許可を与えます。フォルダにファイルが入り「保存ログ」シートができれば成功です。 - 左の時計アイコン「トリガー」→「トリガーを追加」→ 関数
saveAttachments・「時間主導型」・「1時間おき」などで保存します。
3. コード全文(コピペで動きます)
const QUERY = 'has:attachment newer_than:3d -in:chats'; // 例: 'from:(billing@example.com) has:attachment newer_than:3d'
const FOLDER_ID = 'ここに保存先フォルダのID';
const EXT_OK = ['pdf', 'xlsx', 'xls', 'csv', 'docx', 'doc', 'zip', 'jpg', 'jpeg', 'png'];
const MIN_BYTES = 5 * 1024; // 署名画像などの小さいファイルは保存しない
const LOG_SHEET = '保存ログ';
const LIMIT_MS = 4.5 * 60 * 1000; // 6分の実行上限の手前で止める
function saveAttachments() {
const start = Date.now();
const lock = LockService.getScriptLock();
if (!lock.tryLock(10 * 1000)) return;
try {
const log = logSheet_();
const done = new Set(log.getLastRow() > 1
? log.getRange(2, 1, log.getLastRow() - 1, 1).getValues().map(r => String(r[0]))
: []);
const folder = DriveApp.getFolderById(FOLDER_ID);
const threads = GmailApp.search(QUERY, 0, 50);
for (const th of threads) {
for (const msg of th.getMessages()) {
if (Date.now() - start > LIMIT_MS) return; // 残りは次回の実行で
const id = msg.getId();
if (done.has(id)) continue; // 返信がついたスレッドでも新着分だけ処理
const day = Utilities.formatDate(msg.getDate(), 'Asia/Tokyo', 'yyyyMMdd');
const from = msg.getFrom().replace(/.*<|>.*/g, '').trim();
const saved = [];
for (const att of msg.getAttachments({ includeInlineImages: false })) {
const name = att.getName() || 'noname';
const ext = (name.split('.').pop() || '').toLowerCase();
if (!EXT_OK.includes(ext) || att.getSize() < MIN_BYTES) continue;
const safe = (day + '_' + name).replace(/[\\/:*?"<>|]/g, '_').slice(0, 150);
const file = folder.createFile(att.copyBlob().setName(safe));
saved.push(file.getUrl());
}
log.appendRow([id, day, from, msg.getSubject().slice(0, 100),
saved.length, saved.join('\n')]);
done.add(id);
}
}
} finally {
lock.releaseLock();
}
}
function logSheet_() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sh = ss.getSheetByName(LOG_SHEET);
if (!sh) {
sh = ss.insertSheet(LOG_SHEET);
sh.appendRow(['メールID', '受信日', '送信元', '件名', '保存数', '保存先']);
sh.setFrozenRows(1);
}
return sh;
}
書き換えるのは主に QUERY(どのメールを対象にするか)と FOLDER_ID の2つです。検索式はGmailの検索窓と同じ書き方なので、先にGmailで検索して、狙ったメールだけが出ることを確かめてから貼るのが確実です。
4. このコードが防いでいる4つの失敗
- 同じファイルが何個も保存される:保存したメールのIDを「保存ログ」シートに記録し、次回からはスキップします。トリガーが重なっても
LockServiceで同時実行を防ぎます。 - 返信がついたスレッドの新しい添付を取りこぼす:よくある「保存済みラベルを付けて
-label:保存済で除外する」方法は、ラベルがスレッド単位なので、同じスレッドに後から届いた添付を見落とします。このコードはメール1通ごとのIDで判定するため、取りこぼしません。 - 署名のロゴ画像まで保存されてフォルダが散らかる:本文埋め込み画像を除外し、拡張子と最小サイズでも絞っています。
- 件数が多い日に途中で止まる:GASの1回の実行は6分までです。4.5分で自分から止め、残りは次の実行で続きから処理します(処理済みはログで判定するので重複しません)。
5. よくあるつまずき
QUERY をGmailの検索窓に貼って、対象メールが出るか確認してください。newer_than:3d は「3日以内」の意味なので、古いメールも取り込みたいときは初回だけ newer_than:30d などに広げます(一度に最大50スレッド)。「保存数 0」の行がある:添付があっても、拡張子が
EXT_OK に無いか5KB未満だったメールです。記録だけ残して、次回からは見に行きません。権限エラーになる:フォルダIDの貼り間違いか、そのフォルダを実行するアカウントが編集できない場合です。共有ドライブのフォルダでも、編集権限があれば保存できます。
6. AIはどこに使う?
保存そのものにAIは不要です。便利なのはその次の段階で、保存した請求書の件名・送信元から「取引先・金額・支払期日」を一覧にまとめる、届いた問い合わせに返信の下書きを作る、といった使い方です。AIに渡すのは必要な部分だけにし、金額や期日は必ず人が原本で確認してください。問い合わせメールの下書きは Gmailの問い合わせ返信をAIで下書き、こちらから送る請求書は 請求書PDFとAI添え状メールを自動で下書き にまとめています。
このページのコードを含む6本を、1つのシートでまとめて動かしたい方へ
無料記事のコードは1本ずつ単独で使う前提のため、同じプロジェクトに複数入れると定数名が衝突します。セット版は添付保存・Slack/Chat通知・古いメール整理・送信元ラベル・シート書き出し・未返信リマインドの6本が同時に動くよう整理し、「今すぐ実行/定期実行ON・OFF(二重登録なし)」メニューと日本語の導入手順を付けました。APIキー不要で、追加費用はかかりません。
Gmail自動化GAS 6本セット(APIキー不要/$9)を見る →Gumroad での販売です。デジタル納品のため、ダウンロード後の返金はお受けできません(不具合時は誠実に対応します)。
自分で設定するのが不安な方へ(ココナラ・日本円):シート1列のAI一括処理と、当日分の自動サマリーメールのGAS2本+日本語手順書を、ココナラで販売しています(3,000円・税抜〜)。初期設定サポート(+4,000円)や、あなたの実データで自動化フローを1つ一緒に作る導入伴走(+12,000円)は任意のオプションです(いずれも税抜)。対応できるかは購入前の見積り相談で確認できます。
ココナラで導入相談・購入する →Gmailの定型作業を、もう一歩まとめて自動化したい方へ
届いた問い合わせをAIで分類し、登録した事実(FAQ)だけを使って返信の下書きを作る拡張版です。noreply・通知・メルマガは自動でスキップし、お試しモードで結果を確認してから本番にできます。
Gmail問い合わせ AI 下書き返信・拡張版(FAQ参照・除外送信元・お試しモード/$3)を見る → 請求書PDF+AI添え状・議事録AI要約など、そのまま動くGAS5本+日本語の導入手順書(PRO版・$39)→手で貼って使うプロンプトだけ欲しい方へ:事務AIプロンプト集12種(無料・投げ銭歓迎)
Gumroad での販売です。このページの添付ファイル自動保存のコードは無料で、有料版には含まれていません。AI を使う機能には OpenAI の API キー(従量課金)が必要です。デジタル納品のため、ダウンロード後の返金はお受けできません(不具合時は誠実に対応します)。
Gmailの受信メールをスプレッドシートに書き出す · Gmail問い合わせ返信をAIで下書き · 請求書PDFとAI添え状メールを自動で下書き · スプレッドシートから差し込みメールを下書き作成 · Googleフォームの自動返信メール · Zenn記事版 · 無料本:GAS×ChatGPT事務自動化の基本