MisaNeco Works Blog

2026-10-20・Automation / Small business / Google Apps Script

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

Step 1. Create the Drive folder

  1. Open Google Drive and create a new folder, for example Email attachments.
  2. 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.
  3. Copy the folder ID. You need it in Step 3.

Step 2. Create the Gmail label

  1. In Gmail, open any email.
  2. 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

  1. Go to the Apps Script home page (search for "Google Apps Script" and sign in with the same Google account).
  2. Create a new project and give it a name, like "Save attachments".
  3. 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();
}
  1. Replace PASTE_YOUR_FOLDER_ID_HERE with your folder ID. Keep the quote marks.
  2. Click Save.

How the script works

In plain English:

  1. It opens your Drive folder.
  2. It finds the SavedToDrive label, or creates it if it does not exist yet.
  3. It searches Gmail for emails that have the SaveToDrive label, do not have the SavedToDrive label, and have an attachment.
  4. 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.
  5. 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

  1. Find an email with an attachment and add the SaveToDrive label.
  2. In the Apps Script editor, choose saveAttachments in the function menu and click Run.
  3. 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.
  4. Open your Drive folder. The attachment should be there, with the date in front of the name.
  5. 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

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.

Free tools you can useSmall Business Automation Check
Related articlesA simple inventory tracker with low-stock alerts (Excel or Google Sheets)
Send appointment reminder emails automatically with Google Sheets (free, no add-ons)
Paying freelancers in the US - Form W-9, Form 1099-NEC and a simple tracking sheet