如何修复Google Apps Script避免附件误存至Drive主文件夹?
解决Google Apps Script附件误存Drive根目录问题
一、先搞定避免误存的问题
看你代码里可能出问题的点:偶尔folderName为空,或者父文件夹获取异常,导致文件误存根目录。按下面改代码就能堵住漏洞:
1. 确保父文件夹存在才继续
原代码直接用.next()取文件夹,找不到会报错,万一有重名文件夹还可能取错。改成先检查:
var parentFolderIterator = DriveApp.getFoldersByName('** SIGN INS **'); if (!parentFolderIterator.hasNext()) { console.error('找不到父文件夹「** SIGN INS **」,脚本停止'); return; } var parentFolder = parentFolderIterator.next();
2. 处理空文件夹名的情况
有些邮件主题处理后folderName为空,这时候别跳过,直接扔到「未分类」子文件夹,绝对不会存到根目录:
var folderName = subject.replace(/A filled document|has been submitted to you with pdfFiller LinkToFill./gi, '').trim(); // 空文件夹名就用「未分类」兜底 if (!folderName) { folderName = '未分类'; }
3. 防止取到其他目录的同名文件夹
加个校验,确保拿到的子文件夹确实在目标父目录下:
function getOrCreateSubfolder(parentFolder, folderName) { var folders = parentFolder.getFoldersByName(folderName); if (folders.hasNext()) { var folder = folders.next(); // 检查这个文件夹的父级是不是我们指定的父文件夹 if (folder.getParents().next().getId() !== parentFolder.getId()) { // 不是的话重新创建 return parentFolder.createFolder(folderName); } return folder; } else { return parentFolder.createFolder(folderName); } }
二、加个清理根目录PDF的函数
要是已经有文件存到根目录,加个自动清理的函数,要么移到未分类文件夹,要么删掉重复的:
function cleanupRootFolderPDFs() { var parentFolderIterator = DriveApp.getFoldersByName('** SIGN INS **'); if (!parentFolderIterator.hasNext()) { console.error('找不到父文件夹「** SIGN INS **」,清理停止'); return; } var parentFolder = parentFolderIterator.next(); var rootFolder = DriveApp.getRootFolder(); // 遍历根目录所有PDF文件 var pdfFiles = rootFolder.getFilesByType(MimeType.PDF); while (pdfFiles.hasNext()) { var file = pdfFiles.next(); var filename = file.getName(); // 你可以在这里加文件名匹配规则,比如只处理包含特定关键词的PDF // 比如if (filename.includes('sign-in')) { ... } var targetFolder = getOrCreateSubfolder(parentFolder, '未分类'); var existingFiles = targetFolder.getFilesByName(filename); if (!existingFiles.hasNext()) { // 目标文件夹没同名文件就移过去 file.moveTo(targetFolder); console.log(`已移动根目录文件:${filename} 到未分类文件夹`); } else { // 有同名文件就删掉根目录的重复文件 file.setTrashed(true); console.log(`已删除根目录重复PDF:${filename}`); } } }
完整优化后的代码
把上面的改动整合起来,就是最终可用的代码:
function saveAttachments() { var searchQuery = 'label:sign-ins is:unread has:attachment newer_than:1h'; var label = GmailApp.getUserLabelByName('sign-ins'); // 校验父文件夹是否存在 var parentFolderIterator = DriveApp.getFoldersByName('** SIGN INS **'); if (!parentFolderIterator.hasNext()) { console.error('找不到父文件夹「** SIGN INS **」,脚本停止'); return; } var parentFolder = parentFolderIterator.next(); var threads = GmailApp.search(searchQuery); for (var i = 0; i < threads.length; i++) { var messages = threads[i].getMessages(); for (var j = 0; j < messages.length; j++) { var attachments = messages[j].getAttachments(); for (var k = 0; k < attachments.length; k++) { var attachment = attachments[k]; var filename = attachment.getName(); var subject = messages[j].getSubject(); var folderName = subject.replace(/A filled document|has been submitted to you with pdfFiller LinkToFill./gi, '').trim(); // 空文件夹名用「未分类」兜底 if (!folderName) { folderName = '未分类'; } var folder = getOrCreateSubfolder(parentFolder, folderName); var existingFiles = folder.getFilesByName(filename); if (!existingFiles.hasNext()) { var file = folder.createFile(attachment); label.addToThread(threads[i]); } } messages[j].markRead(); } } } function getOrCreateSubfolder(parentFolder, folderName) { var folders = parentFolder.getFoldersByName(folderName); if (folders.hasNext()) { var folder = folders.next(); // 校验文件夹父级是否正确 if (folder.getParents().next().getId() !== parentFolder.getId()) { return parentFolder.createFolder(folderName); } return folder; } else { return parentFolder.createFolder(folderName); } } // 清理Drive根目录的PDF文件 function cleanupRootFolderPDFs() { var parentFolderIterator = DriveApp.getFoldersByName('** SIGN INS **'); if (!parentFolderIterator.hasNext()) { console.error('找不到父文件夹「** SIGN INS **」,清理停止'); return; } var parentFolder = parentFolderIterator.next(); var rootFolder = DriveApp.getRootFolder(); var pdfFiles = rootFolder.getFilesByType(MimeType.PDF); while (pdfFiles.hasNext()) { var file = pdfFiles.next(); var filename = file.getName(); // 可自定义文件名匹配规则,比如只处理特定关键词的PDF // if (filename.includes('sign-in')) { var targetFolder = getOrCreateSubfolder(parentFolder, '未分类'); var existingFiles = targetFolder.getFilesByName(filename); if (!existingFiles.hasNext()) { file.moveTo(targetFolder); console.log(`已移动根目录文件:${filename} 到未分类文件夹`); } else { file.setTrashed(true); console.log(`已删除根目录重复PDF:${filename}`); } // } } }
使用提示
- 把原代码替换成上面的版本,确保「** SIGN INS **」文件夹名称和你Drive里的完全一致。
- 要是想自动清理,给
cleanupRootFolderPDFs加个时间触发器(比如每小时跑一次),或者在saveAttachments末尾加一句cleanupRootFolderPDFs();,每次处理邮件后自动清理。 - 可以根据你附件的文件名规律,调整清理函数里的匹配规则,只处理目标文件,别误删其他PDF。
内容的提问来源于stack exchange,提问作者Basics
相关产品推荐
相关产品推荐

