SkillStack Lab(スキスタ)運営者の「スタック」です。
Gmailに届く請求書やCSVなどの添付ファイルを、毎回ダウンロードしてGoogleドライブへ保存していませんか。
GAS(Google Apps Script)を使えば、条件に合うGmailを検索し、添付ファイルだけを指定したGoogleドライブへ自動保存できます。
この記事では、Gmailの添付ファイルをGoogleドライブへ保存する実用的なGASコードから、PDF・CSVだけに絞る方法、二重保存の防止、トリガー設定、6分制限への対策までまとめて解説します。
私はこれまで、GASを使った社内備品・PCの貸出管理や期限超過メール、簡易ワークフローの通知などを実務で構築・運用してきました。
その経験から強く感じるのは、業務自動化では「とりあえず動くコード」よりも、二重処理やエラーが起きても自分で原因を追える仕組みにすることが重要だという点です。
まずは少量のテストメールで動作を確認しながら、自社の運用に合わせて調整してください。
※本記事には広告・プロモーションが含まれています。

- Gmailの添付ファイルをGoogleドライブへ保存するGASコード
- 件名・送信者・PDF・CSVで対象を絞る方法
- 署名画像など不要なインライン画像を除外する方法
- 保存済みメールを二重処理しない仕組み
- 時間主導型トリガーで自動実行する方法
- 6分制限・クォータ・権限・共有ドライブの注意点
GASでGmailの添付ファイルをGoogleドライブへ保存するコード
最初に、今回作る仕組みの全体像を確認しておきましょう。
- Gmailから条件に一致するメールを検索する
- メールから添付ファイルを取得する
- PDFやCSVなど必要なファイルだけに絞る
- Googleドライブの指定フォルダへ保存する
- 処理済みのスレッドへラベルを付ける

1.保存先のGoogleドライブでフォルダIDを確認する
最初に、添付ファイルを保存したいGoogleドライブのフォルダを開きます。
ブラウザのURLが次のようになっている場合、folders/より後ろの部分がフォルダIDです。
https://drive.google.com/drive/folders/xxxxxxxxxxxxxxxxxxxx
この例では、xxxxxxxxxxxxxxxxxxxxの部分を後ほどGASへ設定します。
フォルダIDは保存先を特定する重要な情報です。コードを社外へ公開する場合は、実際に使用しているIDを載せないでください。
2.Apps Scriptへコードを貼り付ける
Apps Scriptで新しいプロジェクトを作成し、次のコードを貼り付けます。
以下は、件名に「請求書」を含むメールからPDF・CSVだけを保存する基本例です。
const CONFIG = {
folderId: 'YOUR_FOLDER_ID',
subjectKeyword: '請求書',
senderContains: '',
allowedExtensions: ['pdf', 'csv'],
processedLabel: 'gas-saved',
lookbackDays: 30,
maxThreads: 50
};
function saveGmailAttachments() {
const folder = DriveApp.getFolderById(CONFIG.folderId);
const processedLabel =
GmailApp.getUserLabelByName(CONFIG.processedLabel) ||
GmailApp.createLabel(CONFIG.processedLabel);
const query = buildSearchQuery_();
const threads = GmailApp.search(
query,
0,
CONFIG.maxThreads
);
const cutoff =
Date.now() - CONFIG.lookbackDays * 24 * 60 * 60 * 1000;
for (const thread of threads) {
try {
let matchedMessageCount = 0;
let savedFileCount = 0;
const messages = thread.getMessages();
for (const message of messages) {
if (message.getDate().getTime() < cutoff) {
continue;
}
if (
CONFIG.subjectKeyword !== '' &&
!message.getSubject().includes(CONFIG.subjectKeyword)
) {
continue;
}
if (
CONFIG.senderContains !== '' &&
!message.getFrom()
.toLowerCase()
.includes(CONFIG.senderContains.toLowerCase())
) {
continue;
}
matchedMessageCount++;
const attachments = message.getAttachments({
includeInlineImages: false,
includeAttachments: true
});
for (const attachment of attachments) {
const fileName = attachment.getName();
if (!isAllowedExtension_(fileName)) {
continue;
}
const receivedAt = Utilities.formatDate(
message.getDate(),
Session.getScriptTimeZone(),
'yyyyMMdd_HHmmss'
);
const outputName =
receivedAt + '_' + fileName;
folder
.createFile(attachment)
.setName(outputName);
savedFileCount++;
}
}
if (matchedMessageCount > 0) {
thread.addLabel(processedLabel);
}
console.log(
'保存完了: ' +
savedFileCount +
'件 / thread=' +
thread.getId()
);
} catch (error) {
console.error(
'処理失敗: thread=' +
thread.getId() +
' / ' +
error.message
);
}
}
}
function buildSearchQuery_() {
const conditions = [
'has:attachment',
'newer_than:' + CONFIG.lookbackDays + 'd',
'-label:' + CONFIG.processedLabel
];
if (CONFIG.subjectKeyword !== '') {
conditions.push(
'subject:"' + CONFIG.subjectKeyword + '"'
);
}
if (CONFIG.senderContains !== '') {
conditions.push(
'from:' + CONFIG.senderContains
);
}
return conditions.join(' ');
}
function isAllowedExtension_(fileName) {
if (CONFIG.allowedExtensions.length === 0) {
return true;
}
const parts =
fileName.toLowerCase().split('.');
if (parts.length === 1) {
return false;
}
const extension = parts.pop();
return CONFIG.allowedExtensions.includes(extension);
}
最初に変更する場所は、基本的にCONFIGの中だけです。
| 設定 | 意味 | 設定例 |
|---|---|---|
folderId |
保存先フォルダ | GoogleドライブのフォルダID |
subjectKeyword |
件名に含む文字 | 請求書 |
senderContains |
送信元 | billing@example.com |
allowedExtensions |
保存する拡張子 | pdf、csv |
lookbackDays |
何日前まで検索するか | 30 |
maxThreads |
1回で処理する最大スレッド数 | 50 |
PDFだけなら、次のように変更します。
allowedExtensions: ['pdf']
すべての通常添付ファイルを対象にしたい場合は空配列にします。
allowedExtensions: []
送信者を限定しないなら、senderContainsは空文字のままで構いません。
3.最初は手動実行して権限を承認する
コードを保存したら、まずsaveGmailAttachmentsを手動で実行します。
このスクリプトはGmailのメッセージとGoogleドライブへアクセスするため、初回実行時にはGoogleアカウントによる権限の承認が必要です。
いきなり数百件を処理せず、検索条件を狭くして5〜10件程度のテストメールから確認するのがおすすめです。
保存先、ファイル名、対象メール、除外したい添付ファイルが想定どおりになっていることを確認してから自動実行へ進みます。
Gmailの検索条件で対象メールを絞り込む
Gmail添付保存の自動化では、コードを書くこと以上に「どのメールを対象にするか」が重要です。
受信メールを無条件ですべて処理すると、必要のない添付ファイルまで保存する原因になります。

GASのGmailApp.search()では、普段Gmailの検索欄で使っている検索演算子を利用できます。
| 検索条件 | 意味 | 例 |
|---|---|---|
has:attachment |
添付ファイルがある | has:attachment |
subject: |
件名を指定 | subject:”請求書” |
from: |
送信者を指定 | from:billing@example.com |
filename: |
ファイル名・種類を指定 | filename:pdf |
newer_than: |
一定期間内のメール | newer_than:30d |
-label: |
指定ラベルを除外 | -label:gas-saved |
Google公式のGmailヘルプでも、has:attachmentやfilename:pdfなどの検索演算子が案内されています。
from:による絞り込みは対象メールを選ぶための条件です。これだけで送信者の真正性や安全性を保証できるわけではありません。
署名ロゴなどのインライン画像は除外する
メールには、本文内の署名ロゴなどが画像データとして含まれる場合があります。
Google Apps ScriptのgetAttachments()には、通常の添付ファイルとインライン画像を分けて取得するオプションがあります。
今回のコードでは次の指定を入れています。
message.getAttachments({
includeInlineImages: false,
includeAttachments: true
});
これにより、本文内のインライン画像を除外し、通常の添付ファイルを取得できます。
さらに拡張子をPDF・CSVだけに絞ることで、保存対象をより限定しています。
Googleドライブの保存先と共有ドライブの注意点
マイドライブ内のフォルダを扱う基本的な処理では、DriveApp.getFolderById()でフォルダを取得し、createFile()で添付ファイルを保存できます。
ただし、会社でGoogle Workspaceを使用している場合は「共有ドライブ」へ保存したいケースもあるでしょう。
共有ドライブを本格的に扱う場合は、単純に「DriveAppならすべて対応できる」と考えないでください。Googleは、共有ドライブへのアクセスや最新機能の利用にはAdvanced Drive Serviceの使用を案内しています。
共有ドライブを業務で使用する場合は、保存先の権限、スクリプト実行アカウント、共有ドライブ側のポリシーを確認したうえで設計してください。
Google公式の現在の仕様は、Apps ScriptのDriveAppリファレンスで確認できます。
トリガーを設定してGmail添付保存を自動実行する
手動実行で問題なく保存できたら、Apps Scriptの「時間主導型トリガー」を設定します。
Apps Scriptの画面左側から「トリガー」を開き、「トリガーを追加」を選択します。
- 実行する関数:
saveGmailAttachments - イベントのソース:時間主導型
- 時間ベースのタイプ:分・時間・日単位から選択
- 実行頻度を選んで保存
たとえば「15分おき」「30分おき」「1時間おき」など、業務上必要な更新頻度に合わせます。
Google Apps Scriptでは、時間主導型トリガーを最短1分間隔まで設定できます。ただし、一般的なバックオフィス業務なら常に最短間隔へする必要はありません。

インストール型トリガーは、トリガーを作成したGoogleアカウントの権限で動作します。
そのため、個人担当者のアカウントだけに依存してしまうと、異動・退職時の引き継ぎが問題になる可能性があります。
スタック自動化そのものより、「誰のアカウントで動き、担当者が変わったとき誰が保守するか」まで決めておくことが実務では重要です。
処理済みラベルで二重保存を防ぐ
トリガーを繰り返し実行するときに必須なのが、同じ添付ファイルを何度も保存しない仕組みです。
今回のコードでは、処理後のGmailスレッドへgas-savedというラベルを付けています。
検索条件には、
-label:gas-saved
を含めているため、通常の再実行では同じスレッドを対象外にできます。
この方法は「処理済みラベルをスレッド単位で付ける」基本形です。同じメールスレッドへ後日新しい添付ファイルが追加される運用では、新着添付まで除外する可能性があります。そのような業務では、Gmail APIやメッセージIDを使った処理履歴管理を検討してください。
GASには1回6分の実行時間制限がある
小規模な処理では問題になりにくいものの、月末などに大量のメールをまとめて処理する場合はApps Scriptのクォータを意識する必要があります。


2026年8月18日時点のGoogle公式情報では、通常のApps Scriptは個人アカウント・Google Workspaceともに1実行あたり6分です。
| 主な制限 | 個人アカウント | Google Workspace |
|---|---|---|
| 1回のスクリプト実行 | 6分 | 6分 |
| Gmail read/write | 20,000回/日 | 50,000回/日 |
| トリガー総実行時間 | 90分/日 | 6時間/日 |
クォータは変更される可能性があるため、大量処理へ使う場合はGoogle公式のApps Scriptクォータを確認してください。
今回のコードでは、1回に検索するスレッド数をmaxThreads: 50にしています。
処理件数が多い場合は、1回にすべて処理しようとするよりも、検索条件と処理件数を分割する方が管理しやすくなります。


GAS自動化全般で起こりやすい制限や属人化については、GASでスプレッドシートを自動化するときの6分制限と運用上の注意点でも詳しく整理しています。
Gmail添付保存で起こりやすいエラーと対策
コードを業務で使い始めると、「保存されない」「同じファイルが増える」などの問題が起こることがあります。
代表的な症状と確認ポイントを整理します。
| 症状 | 主な確認ポイント |
|---|---|
| 対象メールが見つからない | 件名・送信元・期間の検索条件を確認 |
| 署名ロゴまで保存される | includeInlineImages: falseを確認 |
| PDF以外も保存される | allowedExtensionsを確認 |
| 同じファイルが増える | 処理済みラベルと検索条件を確認 |
| フォルダが見つからない | フォルダIDと実行アカウントの権限を確認 |
| 途中で処理が止まる | 6分制限・クォータ・処理件数を確認 |
| 自動実行だけ失敗する | トリガーを作成したアカウントと実行履歴を確認 |
自動実行に失敗したら「実行数」を確認する
時間主導型トリガーは、人が画面を見ていない状態で動きます。
処理に失敗した場合はApps Script左側の「実行数」を開き、ステータスとエラーメッセージを確認してください。
インストール型トリガーで例外が発生した場合、Googleから失敗通知メールが送られる仕組みもあります。
自動化した後も、ときどき実行履歴を確認し、「動いているつもり」の状態を作らないことが重要です。
CSVの文字化けは「保存」と「読み込み」を分けて考える
GASでCSVを扱うと「文字化け」がよく話題になりますが、単純にメール添付のBlobをGoogleドライブへ保存するだけなら、GAS側でCSV本文を文字列へ変換する必要はありません。
今回のコードも、添付ファイルをそのままDriveへ保存しています。
文字コードを意識する必要が大きくなるのは、CSVをgetDataAsString()などで読み込み、文字列として加工・再出力するときです。
「保存したCSVをExcelで開いたら文字化けした」という場合は、元ファイルの文字コードや開く側のアプリも確認してください。GASで保存したことだけが原因とは限りません。
実務でGASを使うならセキュリティと属人化にも注意する
Gmailの添付ファイルを自動保存できると便利ですが、メールやGoogleドライブには会社の重要情報が含まれる可能性があります。
Google Apps ScriptでGmailの添付ファイルへアクセスする処理には、Gmailへのアクセス権限が必要です。
そのため、コードだけでなく次の点まで確認してください。
- どのGoogleアカウントでスクリプトを動かすか
- 保存先フォルダを誰が閲覧できるか
- 対象とする送信者・件名をどこまで限定するか
- 担当者の異動・退職時に誰が引き継ぐか
- エラー発生時に誰が実行履歴を確認するか
特に経理関係の請求書や個人情報を含む添付ファイルを扱う場合は、保存先の共有権限を広げすぎないよう注意しましょう。



業務で使うなら「コードが動いた」で完成ではありません。エラー時の確認方法と引き継ぎ方法まで決めて、初めて運用できる仕組みになります。
コピペだけで本番運用せずコードの意味も理解する
GASのサンプルコードは便利ですが、インターネット上のコードをそのまま会社のGmailへ接続することはおすすめしません。
最低限、次の部分が何をしているのか確認してください。
GmailApp.search()で何を検索しているかgetAttachments()で何を取得しているかDriveAppでどこへ保存しているか- どの時点で処理済み扱いになるか
- エラーが発生したとき何が残るか
変数、配列、条件分岐、ループ、関数といったJavaScriptの基本を理解していれば、自社の件名や保存ルールが変わっても修正しやすくなります。
「GASをどこまで自作してよいのか」「6分制限や属人化まで含めて考えたい」という方は、先ほど紹介したGAS自動化の注意点も参考にしてください。
GASでGmail添付ファイルを保存するときのよくある質問
まとめ|Gmail添付保存は小さくテストしてから自動化する
GASを使えば、Gmailの添付ファイルをGoogleドライブへ自動保存できます。
基本的な流れはシンプルです。
- Gmailの検索条件を決める
- 添付ファイルを取得する
- PDFやCSVなど必要な形式だけに絞る
- Googleドライブへ保存する
- 処理済みを記録して二重保存を防ぐ
- トリガーで定期実行する


ただし、会社の業務で使うなら「自動で保存できた」で終わりではありません。
6分制限、二重保存、権限、エラー確認、担当者の引き継ぎまで含めて設計することで、長く使える自動化になります。
最初は少量のテストメールで動作を確認し、問題がなければ対象メールと実行頻度を徐々に広げていくのが安全です。
この記事のコードを読んでも「どこを変更すればよいか分からない」という場合は、いきなり本番運用せず、JavaScriptやGASの基礎から確認する方法もあります。
Udemyを使う場合は、現在公開されているGAS・JavaScript関連講座の内容、更新日、プレビューなどを比較し、自分が必要な部分を学べるか確認してください。
GASを自力で修正できるようにしたい方へ






