Here's a gmail extractor google apps script that does the same thing, but for not $30!function autoExtractGmailMedia() {
const START_TIME = Date.now();
const TIME_LIMIT = 1000 * 60 * 5; // 5 minutes (leaves a 1-minute safety buffer)
const BATCH_SIZE = 50;
const FOLDER_NAME = "Gmail_Media_Export";
// 1. Retrieve our current position from the script's property store
const scriptProperties = PropertiesService.getScriptProperties();
let startIndex = parseInt(scriptProperties.getProperty('START_INDEX')) || 0;
// Locate or create the destination folder
let folder;
const folders = DriveApp.getFoldersByName(FOLDER_NAME);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(FOLDER_NAME);
}
// 2. Process batches in a loop
// Updated search query to ignore USPS and non-primary tabs
const searchQuery = 'has:attachment -from:usps.gov -category:promotions -category:updates -category:social (filename:jpg OR filename:jpeg OR filename:png OR filename:zip)';
while (true) {
const threads = GmailApp.search(searchQuery, startIndex, BATCH_SIZE);
// If the search returns empty, we've hit the end of the inbox
if (threads.length === 0) {
console.log("Extraction completely finished.");
scriptProperties.deleteProperty('START_INDEX');
deleteTriggers(); // Clean up so it doesn't keep running
return;
}
for (let i = 0; i < threads.length; i++) {
const messages = threads[i].getMessages();
for (let j = 0; j < messages.length; j++) {
const attachments = messages[j].getAttachments();
for (let k = 0; k < attachments.length; k++) {
const attachment = attachments[k];
const name = attachment.getName().toLowerCase();
const type = attachment.getContentType();
const size = attachment.getSize();
// Apply size threshold (102,400 bytes = 100KB) and file type filter
if (size > 102400) {
if (type.includes('image/') || name.endsWith('.zip')) {
folder.createFile(attachment);
}
}
}
}
}
// Increment our starting index for the next batch
startIndex += BATCH_SIZE;
// 3. The Stopwatch Check
if (Date.now() - START_TIME > TIME_LIMIT) {
console.log(`Approaching timeout at index ${startIndex}. Saving state and passing the baton...`);
scriptProperties.setProperty('START_INDEX', startIndex.toString());
scheduleNextRun();
return; // Exit to avoid the hard timeout exception
}
}
}function scheduleNextRun() {
deleteTriggers(); // Prevent duplicate overlapping triggers
ScriptApp.newTrigger("autoExtractGmailMedia")
.timeBased()
.after(60 * 1000) // Fire a new execution 1 minute from now
.create();
}
function deleteTriggers() {
const triggers = ScriptApp.getProjectTriggers();
for (let i = 0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() === "autoExtractGmailMedia") {
ScriptApp.deleteTrigger(triggers[i]);
}
}
}