Save Gmail attachments to Google Drive automatically (free Apps Script)
Receipts, supplier invoices, signed forms, photos from customers. In a small business, many important files arrive as email attachments. Then they stay in Gmail, and finding them at tax time takes hours.
You can fix this with a short Google Apps Script. You put a label on an email, and the script saves its attachments to a Google Drive folder for you. It is free, needs no add-ons, and takes about 15 minutes to set up.
What you will build
- A Gmail label called SaveToDrive. You add it to any email whose attachments you want to keep.
- A script that finds those emails and saves every attachment to one Drive folder.
- A second label, SavedToDrive, that the script adds when it is done. This stops it from saving the same files twice.
- A trigger that runs the script every hour.
Step 1. Create the Drive folder
- Open Google Drive and create a new folder, for example Email attachments.
- Open the folder. Look at the address bar in your browser. The last part of the address, after
folders/, is the folder ID. It is a long mix of letters and numbers. - Copy the folder ID. You need it in Step 3.
Step 2. Create the Gmail label
- In Gmail, open any email.
- Click the label icon and create a new label called SaveToDrive (one word, no spaces).
You do not need to create SavedToDrive. The script makes it the first time it runs.
Step 3. Add the script
- Go to the Apps Script home page (search for "Google Apps Script" and sign in with the same Google account).
- Create a new project and give it a name, like "Save attachments".
- Delete anything in the editor and paste this:
// Saves Gmail attachments to a Google Drive folder.
// Put the label "SaveToDrive" on any email whose attachments you want saved.
// After saving, the script adds the label "SavedToDrive" so it never saves the same thread twice.
const LABEL_TO_SAVE = 'SaveToDrive';
const LABEL_DONE = 'SavedToDrive';
const FOLDER_ID = 'PASTE_YOUR_FOLDER_ID_HERE';
const MAX_THREADS_PER_RUN = 20;
function saveAttachments() {
const folder = DriveApp.getFolderById(FOLDER_ID);
const doneLabel = GmailApp.getUserLabelByName(LABEL_DONE) || GmailApp.createLabel(LABEL_DONE);
const tz = Session.getScriptTimeZone();
const query = 'label:' + LABEL_TO_SAVE + ' -label:' + LABEL_DONE + ' has:attachment';
const threads = GmailApp.search(query, 0, MAX_THREADS_PER_RUN);
threads.forEach(function (thread) {
thread.getMessages().forEach(function (message) {
const day = Utilities.formatDate(message.getDate(), tz, 'yyyy-MM-dd');
message.getAttachments({ includeInlineImages: false }).forEach(function (attachment) {
const blob = attachment.copyBlob();
blob.setName(day + ' ' + attachment.getName());
folder.createFile(blob);
});
});
thread.addLabel(doneLabel); // mark the thread as done
});
}
// Run once: checks for new labelled emails every hour.
function createHourlyTrigger() {
ScriptApp.newTrigger('saveAttachments').timeBased().everyHours(1).create();
}
- Replace
PASTE_YOUR_FOLDER_ID_HEREwith your folder ID. Keep the quote marks. - Click Save.
How the script works
In plain English:
- It opens your Drive folder.
- It finds the SavedToDrive label, or creates it if it does not exist yet.
- It searches Gmail for emails that have the SaveToDrive label, do not have the SavedToDrive label, and have an attachment.
- For each email in each conversation, it copies every attachment into the folder. It adds the email's date to the front of the file name, like
2026-10-02 receipt.pdf. Files then sort by date in Drive. - It adds the SavedToDrive label to the conversation. Next time, the search skips it.
includeInlineImages: false skips small pictures inside the email body, such as logos in email signatures. You get the real attachments, not a folder full of logos.
MAX_THREADS_PER_RUN limits how many conversations it handles in one run. Google limits how long a script can run and how much it can do each day. If you label a lot of old emails at once, the script simply works through them over several runs.
Step 4. Test it
- Find an email with an attachment and add the SaveToDrive label.
- In the Apps Script editor, choose
saveAttachmentsin the function menu and click Run. - The first time, Google asks for permission to read your Gmail and write to your Drive. Review the permissions and allow them. Only allow it if you are using your own script, as here.
- Open your Drive folder. The attachment should be there, with the date in front of the name.
- Back in Gmail, the email now has a SavedToDrive label too.
Now click Run again. Nothing new is saved, because that conversation is already marked as done.
Step 5. Run it every hour
Choose createHourlyTrigger in the function menu and click Run once. The script will now check for newly labelled emails about once an hour.
To see or remove the trigger later, click the clock icon (Triggers) on the left side of the Apps Script editor. Run createHourlyTrigger only once, or you will end up with duplicate triggers.
Make it hands-free with a Gmail filter
Adding the label by hand is fine. But you can also let Gmail do it.
In Gmail, create a filter (for example, emails from your supplier, or emails with "invoice" in the subject that have an attachment). Set the filter to apply the SaveToDrive label. Now those attachments go to Drive without you touching anything.
Things to know
- One conversation, one pass. The script marks the whole conversation as done. If a new reply with a new attachment arrives later in the same conversation, it is not saved automatically. Remove the SavedToDrive label from that conversation and the script will save its attachments again on the next run, including the old ones.
- Duplicates in Drive. Drive allows two files with the same name. If you re-run on the same email, you may get a second copy. Delete the extra one.
- Limits. Google limits script runtime and daily quotas, and the limits differ between free Gmail accounts and Google Workspace. For most small businesses, an hourly run with a small batch is well within them.
- Privacy. Attachments may include customer data. Keep the Drive folder private, or share it only with people who need it.
- Stopping it. Delete the trigger, and the script stops running. Your saved files stay in Drive.
What else could you automate?
Saving attachments is one small job that adds up over a year. Our free Small Business Automation Check asks about your country, industry and daily tasks, and shows which admin jobs are easiest to automate and how to begin.