Using Google App Script's pageToken to store attachments on Google Drive

Essentially, my goal is to save all attachments from received emails to a specific folder in Google Drive (mostly .PDF files). However, I've encountered a limitation with the search function which only allows me to retrieve up to 500 attached files. I came across something called pageToken but I'm unsure how to incorporate it into my code. Any guidance, advice, or examples on how to address this would be greatly appreciated.

function saveGmailtoGoogleDrive() {

  const folderId = '1apaQJjDSK-bNfd3ZgiFqK23cE7SCPqoB'; //Google Drive Folder

  const searchQuery = 'label:unread has:attachment'; //Filter

  const threads = GmailApp.search(searchQuery, 0, 500);

  

  threads.forEach(thread => {
    const messages = thread.getMessages();
    messages.forEach(message => {

      const attachments = message.getAttachments({
          includeInlineImages: false,
          includeAttachments: true
          
      });

      attachments.forEach(attachment => {

        // Insert the attachment to google drive folder

        Drive.Files.insert(
          {
            title: attachment.getName(),
            mimeType: attachment.getContentType(),
            parents: [{ id: folderId }]
          },
          attachment.copyBlob()
        );
      });
    });
  });
};

function saveGmailtoGoogleDrive() {

  const folderId = '1apaQJjDSK-bNfd3ZgiFqK23cE7SCPqoB'; //Google Drive Folder

  const searchQuery = 'label:unread has:attachment'; //Filter

  const threads = GmailApp.search(searchQuery, 0, 500);

  

  threads.forEach(thread => {
    const messages = thread.getMessages();
    messages.forEach(message => {

      const attachments = message.getAttachments({
          includeInlineImages: false,
          includeAttachments: true
          
      });

      attachments.forEach(attachment => {

        // Insert the attachment to google drive folder

        Drive.Files.insert(
          {
            title: attachment.getName(),
            mimeType: attachment.getContentType(),
            parents: [{ id: folderId }]
          },
          attachment.copyBlob()
        );
      });
    });
  });
};

Answer №1

When using the method search(query, start, max), the arguments to be passed are query, start, max. It is worth noting that the current maximum value allowed for max is 500. If this limit is exceeded, an error message stating Argument max cannot exceed 500. will be displayed. The parameter start determines the starting position of the search operation and can play a crucial role in achieving your desired outcome. You can incorporate this information into your script with the following modifications:

Modified script:

From:

const threads = GmailApp.search(searchQuery, 0, 500);

To:

let [start, end] = [0, 500];
let threads = [];
do {
  const t = GmailApp.search(searchQuery, start, end);
  start += end;
  threads = [...threads, ...t];
} while (threads.length == start);
  • With this modification, you will be able to retrieve more than 500 emails stored in the variable threads.

Reference:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for customizing the blinking cursor in a textarea

I am experimenting with creating a unique effect on my website. I have incorporated a textarea with transparent text overlaying a pre element that displays the typed text dynamically using JavaScript. This creates an illusion of the user typing in real-tim ...

Find the current elapsed time using Wavesurfer in real time

I am currently utilizing the waveSurfer library created by katspaugh for playing audio files. In order to display 'elapsed time / total time', I have written code in the following manner: waveSurfer.on('play', function() { $scope.g ...

The font size appears significantly smaller than expected when using wkhtmltoimage to render

I am trying to convert text into an image, with a static layout and size while adjusting the font size based on the amount of text. I prefer using wkhtmltoimage 0.12.5 as it offers various CSS styling options. Currently, I am working on a Mac. Below is a ...

Ways to ensure the bootstrap table header width aligns perfectly with the body width

I am having an issue with my bootstrap table where the header width is smaller than the body width because I set the table width to auto. How can I align the header and body widths? Here is a link to a plunker showcasing the problem. https://plnkr.co/edit ...

jquery add to table id, not to a table within

Having trouble adding a table row to a specific table ID without it appending to other tables with different IDs nested inside. I've searched for a solution but can't seem to find one. Can someone help me figure out what I'm doing wrong? Her ...

Setting up package.json to relocate node_modules to a different directory outside of the web application:

My web app is currently located in C:\Google-drive\vue-app. When I run the command yarn build, it installs a node_modules folder within C:\Google-drive\vue-app. However, since I am using Google Drive to sync my web app source code to Go ...

Issue: Module '@angular/compiler' not found

After downloading an angular template, I encountered an issue while running "ng serve": Cannot find module '@angular/compiler' Error: Cannot find module '@angular/compiler' ... I tried various solutions found on the internet, incl ...

When Infinite Scroll is integrated into another file with HTML tags stacked on top, it will not load additional posts when scrolling down

I have implemented an Infinite Scroll feature that dynamically loads more data from a database as users scroll to the bottom of the page. However, I encountered an issue when trying to include this functionality in another .PHP file. If I insert any HTML ...

inject a $scope object into a view when a button is clicked

Right now, I am using an array as a $scope object $scope.data { item1: "Value", item2: "Value Alt" } Every item corresponds to a form input with a default value. My goal is to create a new form from the same data set upon an ng-click event while main ...

How can I retrieve information from an HTML or JavaScript object?

Imagine a scenario where you have an HTML table consisting of 5,000 rows and 50 columns, all generated from a JavaScript object. Now, suppose you want to send 50 checked rows (checkbox) from the client to the server using HTTP in JSON format. The question ...

Can you explain the purpose of CLOUDINARY_DEFAULT_URL and CLOUDINARY_DEFAULT_PUBLICID to me?

Need help with my user sign up page Here is my .env file This is my signup controller code: const User = require('../model/User'); const bcrypt = require('bcrypt'); const { uploadToCloudinary } = require('../utils/cloudinary&apos ...

Executing two Ajax calls in ReactJS with different parameters can improve the efficiency of your

Why does the second Ajax call overwrite the first one, causing the results to be different each time I refresh it? In the first Ajax call, I have set tests: [], testsHistories: [] in the setState function. However, the second Ajax call only sets the stat ...

Error in Access-Control-Allow-Origin when using Node.js and JSONP

It seems like JSONP eliminates cross domain restrictions. I am currently attempting to create a JSONP service with node and express. Below is a simple example of the code: self.routes['/portfolio'] = function(req, res) { // Website you wis ...

Incorporating OpenLayers and TypeScript: Issue with Event.map.forEachFeatureAtPixel, where the argument type is not compatible with the parameter type

I am currently attempting to implement Open Layers v7.2.2 with TypeScript. {When not using TypeScript, the code functions properly} function OnMapClick(event: MapBrowserEvent<UIEvent>) { event.map.forEachFeatureAtPixel(event.pixel, function(curren ...

How to properly fill state values for testing components with React Testing Library?

Introducing my custom component -> export default() => { const [list, setList] = useState([]) const handleAddToList = () => { // Executes an API call and updates the list state. setList(response); } return ( <div> ...

Unable to view images on Wordpress theme

I am currently facing an issue where some images in my asset folder are not displaying properly when I convert my HTML/CSS/JS template to Wordpress. The main problem is with the image that should show up when you first visit the website. Below is the CSS c ...

Generating an interactive button click feature within a cell of a data table

Can someone help me figure out why I am getting a SyntaxError when trying to trigger a function in a datatable cell using an onclick event on a button? The button is successfully created, but the error occurs when clicking it. The problem seems to lie wit ...

Using jQuery's click function to manipulate multiple div elements

Currently, I am attempting to use jQuery's click function in order to implement a hover effect on a selected div without having to differentiate between the divs in the JavaScript code. Here is what I have so far: $(document).ready(function(){ $ ...

Eliminating the use of am/pm and implementing a 24-hour format on the x-axis of a time series

Currently, I am attempting to create a time series plot with second precision in the format of HH:mm:ss (24 hours per day), as indicated in the documentation provided by moment js. However, I have encountered an issue where the format I specify is not bei ...

The initial number is inserted within the text box upon entering the final number

Whenever I enter the final digit, the text-box swallows up the initial number (it vanishes), resulting in an additional space. https://i.stack.imgur.com/Vfm8s.png https://i.stack.imgur.com/od4bQ.png Upon clicking outside of the text-box, the formatting ...