- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我不确定 Google App Script 最近是否有更新,但我已经使用此脚本几个月了,但它现在已损坏并且无法工作。
这是我正在使用的脚本:
代码.gs:
// Gmail2GDrive
// https://github.com/ahochsteger/gmail2gdrive
/**
* Returns the label with the given name or creates it if not existing.
*/
function getOrCreateLabel(labelName) {
var label = GmailApp.getUserLabelByName(labelName);
if (label == null) {
label = GmailApp.createLabel(labelName);
}
return label;
}
/**
* Recursive function to create and return a complete folder path.
*/
function getOrCreateSubFolder(baseFolder,folderArray) {
if (folderArray.length == 0) {
return baseFolder;
}
var nextFolderName = folderArray.shift();
var nextFolder = null;
var folders = baseFolder.getFolders();
while (folders.hasNext()) {
var folder = folders.next();
if (folder.getName() == nextFolderName) {
nextFolder = folder;
break;
}
}
if (nextFolder == null) {
// Folder does not exist - create it.
nextFolder = baseFolder.createFolder(nextFolderName);
}
return getOrCreateSubFolder(nextFolder,folderArray);
}
/**
* Returns the GDrive folder with the given path.
*/
function getFolderByPath(path) {
var parts = path.split("/");
if (parts[0] == '') parts.shift(); // Did path start at root, '/'?
var folder = DriveApp.getRootFolder();
for (var i = 0; i < parts.length; i++) {
var result = folder.getFoldersByName(parts[i]);
if (result.hasNext()) {
folder = result.next();
} else {
throw new Error( "folder not found." );
}
}
return folder;
}
/**
* Returns the GDrive folder with the given name or creates it if not existing.
*/
function getOrCreateFolder(folderName) {
var folder;
try {
folder = getFolderByPath(folderName);
} catch(e) {
var folderArray = folderName.split("/");
folder = getOrCreateSubFolder(DriveApp.getRootFolder(), folderArray);
}
return folder;
}
/**
* Processes a message
*/
function processMessage(message, rule, config) {
Logger.log("INFO: Processing message: "+message.getSubject() + " (" + message.getId() + ")");
var messageDate = message.getDate();
var attachments = message.getAttachments();
for (var attIdx=0; attIdx<attachments.length; attIdx++) {
var attachment = attachments[attIdx];
var attachmentName = attachment.getName();
Logger.log("INFO: Processing attachment: "+attachment.getName());
var match = true;
if (rule.filenameFromRegexp) {
var re = new RegExp(rule.filenameFromRegexp);
match = (attachment.getName()).match(re);
}
if (!match) {
Logger.log("INFO: Rejecting file '" + attachment.getName() + " not matching" + rule.filenameFromRegexp);
continue;
}
try {
var folder = getOrCreateFolder(Utilities.formatDate(messageDate, config.timezone, rule.folder));
/////////////////////////////////////////////////////////////////////////////////////////////
// var file = folder.removeFile(attachment);
// file.setContent(attachment);
var fileName = attachment.getName();
var f = folder.getFilesByName(fileName);
var file = f.hasNext() ? f.next() : folder.createFile(attachment);
// file.setContent(attachment);
/////////////////////////////////////////////////////////////////////////////////////////////
if (rule.filenameFrom && rule.filenameTo && rule.filenameFrom == file.getName()) {
var newFilename = Utilities.formatDate(messageDate, config.timezone, rule.filenameTo.replace('%s',message.getSubject()));
Logger.log("INFO: Renaming matched file '" + file.getName() + "' -> '" + newFilename + "'");
file.setName(newFilename);
}
else if (rule.filenameTo) {
var newFilename = Utilities.formatDate(messageDate, config.timezone, rule.filenameTo.replace('%s',message.getSubject()));
Logger.log("INFO: Renaming '" + file.getName() + "' -> '" + newFilename + "'");
file.setName(newFilename);
}
file.setDescription("Mail title: " + message.getSubject() + "\nMail date: " + message.getDate() + "\nMail link: https://mail.google.com/mail/u/0/#inbox/" + message.getId());
Utilities.sleep(config.sleepTime);
} catch (e) {
Logger.log(e);
}
}
}
/**
* Generate HTML code for one message of a thread.
*/
function processThreadToHtml(thread) {
Logger.log("INFO: Generating HTML code of thread '" + thread.getFirstMessageSubject() + "'");
var messages = thread.getMessages();
var html = "";
for (var msgIdx=0; msgIdx<messages.length; msgIdx++) {
var message = messages[msgIdx];
html += "From: " + message.getFrom() + "<br />\n";
html += "To: " + message.getTo() + "<br />\n";
html += "Date: " + message.getDate() + "<br />\n";
html += "Subject: " + message.getSubject() + "<br />\n";
html += "<hr />\n";
html += message.getBody() + "\n";
html += "<hr />\n";
}
return html;
}
/**
* Generate a PDF document for the whole thread using HTML from .
*/
function processThreadToPdf(thread, rule, html) {
Logger.log("INFO: Saving PDF copy of thread '" + thread.getFirstMessageSubject() + "'");
var folder = getOrCreateFolder(rule.folder);
var html = processThreadToHtml(thread);
var blob = Utilities.newBlob(html, 'text/html');
var pdf = folder.createFile(blob.getAs('application/pdf')).setName(thread.getFirstMessageSubject() + ".pdf");
return pdf;
}
/**
* Main function that processes Gmail attachments and stores them in Google Drive.
* Use this as trigger function for periodic execution.
*/
function Gmail2GDrive() {
if (!GmailApp) return; // Skip script execution if GMail is currently not available (yes this happens from time to time and triggers spam emails!)
var config = getGmail2GDriveConfig();
var label = getOrCreateLabel(config.processedLabel);
var end, start;
start = new Date(); // Start timer
Logger.log("INFO: Starting mail attachment processing.");
if (config.globalFilter===undefined) {
config.globalFilter = "has:attachment -in:trash -in:drafts -in:spam";
}
// Iterate over all rules:
for (var ruleIdx=0; ruleIdx<config.rules.length; ruleIdx++) {
var rule = config.rules[ruleIdx];
var gSearchExp = config.globalFilter + " " + rule.filter + " -label:" + config.processedLabel;
if (config.newerThan != "") {
gSearchExp += " newer_than:" + config.newerThan;
}
var doArchive = rule.archive == true;
var doPDF = rule.saveThreadPDF == true;
// Process all threads matching the search expression:
var threads = GmailApp.search(gSearchExp);
Logger.log("INFO: Processing rule: "+gSearchExp);
for (var threadIdx=0; threadIdx<threads.length; threadIdx++) {
var thread = threads[threadIdx];
end = new Date();
var runTime = (end.getTime() - start.getTime())/1000;
Logger.log("INFO: Processing thread: "+thread.getFirstMessageSubject() + " (runtime: " + runTime + "s/" + config.maxRuntime + "s)");
if (runTime >= config.maxRuntime) {
Logger.log("WARNING: Self terminating script after " + runTime + "s")
return;
}
// Process all messages of a thread:
var messages = thread.getMessages();
for (var msgIdx=0; msgIdx<messages.length; msgIdx++) {
var message = messages[msgIdx];
processMessage(message, rule, config);
}
if (doPDF) { // Generate a PDF document of a thread:
processThreadToPdf(thread, rule);
}
// Mark a thread as processed:
thread.addLabel(label);
if (doArchive) { // Archive a thread if required
Logger.log("INFO: Archiving thread '" + thread.getFirstMessageSubject() + "' ...");
thread.moveToArchive();
}
}
}
end = new Date(); // Stop timer
var runTime = (end.getTime() - start.getTime())/1000;
Logger.log("INFO: Finished mail attachment processing after " + runTime + "s");
}
Config.gs:
/**
* Configuration for Gmail2GDrive
* See https://github.com/ahochsteger/gmail2gdrive/blob/master/README.md for a config reference
*/
function getGmail2GDriveConfig() {
return {
// Global filter
"globalFilter": "-in:trash -in:drafts -in:spam",
// Gmail label for processed threads (will be created, if not existing):
"processedLabel": "to-gdrive/processed",
// Sleep time in milli seconds between processed messages:
"sleepTime": 100,
// Maximum script runtime in seconds (google scripts will be killed after 5 minutes):
"maxRuntime": 45,
// Only process message newer than (leave empty for no restriction; use d, m and y for day, month and year):
"newerThan": "1m",
// Timezone for date/time operations:
"timezone": "GMT",
// Processing rules:
"rules": [
/* { // Store all attachments sent to <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8ee3f7a0e0efe3eba5fdedefe0fdcee9e3efe7e2a0ede1e3" rel="noreferrer noopener nofollow">[email protected]</a> to the folder "Scans"
"filter": "has:attachment to:<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d3beaafdbdb2beb6f8a0b0b2bda093b4beb2babffdb0bcbe" rel="noreferrer noopener nofollow">[email protected]</a>",
"folder": "'Scans'-yyyy-MM-dd"
},
{ // Store all attachments from <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fe9b869f938e929bcfbe9b869f938e929bd09d9193" rel="noreferrer noopener nofollow">[email protected]</a> to the folder "Examples/example1"
"filter": "has:attachment from:<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a2c7dac3cfd2cec793e2c7dac3cfd2cec78cc1cdcf" rel="noreferrer noopener nofollow">[email protected]</a>",
"folder": "'Examples/example1'"
}, */
{ // Store all pdf attachments from <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0d68756c607d61683f4d68756c607d6168236e6260" rel="noreferrer noopener nofollow">[email protected]</a> to the folder "Examples/example2"
"filter": "label:gmail2drive",
"folder": "'Swann'",
"filenameFromRegexp": ".*\.jpg$",
"archive": true
},
// { // Store all attachments from <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="90f5e8f1fde0fcf5a3f1d0f5e8f1fde0fcf5bef3fffd" rel="noreferrer noopener nofollow">[email protected]</a> OR from:<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8de8f5ece0fde1e8beefcde8f5ece0fde1e8a3eee2e0" rel="noreferrer noopener nofollow">[email protected]</a>
// to the folder "Examples/example3ab" while renaming all attachments to the pattern
// defined in 'filenameTo' and archive the thread.
// "filter": "has:attachment (from:<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9df8e5fcf0edf1f8aefcddf8e5fcf0edf1f8b3fef2f0" rel="noreferrer noopener nofollow">[email protected]</a> OR from:<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="96f3eef7fbe6faf3a5f4d6f3eef7fbe6faf3b8f5f9fb" rel="noreferrer noopener nofollow">[email protected]</a>)",
// "folder": "'Examples/example3ab'",
// "filenameTo": "'file-'yyyy-MM-dd-'%s.txt'",
// "archive": true
// },
/* {
// Store threads marked with label "PDF" in the folder "PDF Emails" als PDF document.
"filter": "label:PDF",
"saveThreadPDF": true,
"folder": "PDF Emails"
},
{ // Store all attachments named "file.txt" from <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="791c01181409151c4d391c01181409151c571a1614" rel="noreferrer noopener nofollow">[email protected]</a> to the
// folder "Examples/example4" and rename the attachment to the pattern
// defined in 'filenameTo' and archive the thread.
"filter": "has:attachment from:<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="096c71686479656c3d496c71686479656c276a6664" rel="noreferrer noopener nofollow">[email protected]</a>",
"folder": "'Examples/example4'",
"filenameFrom": "file.txt",
"filenameTo": "'file-'yyyy-MM-dd-'%s.txt'"
} */
]
};
}
本质上,该脚本会检查带有“gmail2drive”标签的电子邮件,如果存在,则会提取电子邮件中的附件并将其上传到我的 Google 云端硬盘中名为“Swann”的文件夹中。然后,它将标签“to-gdrive/processed”应用于已处理的电子邮件,这样它们就不会再次被处理。
有时,某些附件可能会被提取两次,从而产生重复项。因此该脚本还会检查重复项,并希望能够防止这种情况发生。
因此,这在大多数情况下都运行良好,但最近它崩溃了,导致相同的附件被多次提取,并且相同的电子邮件被多次处理的问题。就像脚本忽略了标签“to-gdrive/processed”之类的。
我尝试过使用不同的标签,结果是一样的。
我还应该澄清一下,我不是程序员或脚本编写人员。我对如何在 Google 脚本中进行此设置知之甚少。我可以按照一般说明进行操作,没问题。我希望知道如何阅读脚本的人能够解决此问题并让我知道要更改哪些内容。
提前致谢。
最佳答案
经过许多评论和chat通过对话,我们推断此问题是由于 DVR 新电子邮件被视为线程回复而产生的。这会弄乱标签并导致重复上传到云端硬盘文件夹。
新脚本:
假设收件箱中有一条规则,将标签“gmail2drive”附加到从 DVR 接收的线程,这将获取带有该标签的所有线程,处理每个线程的每条消息并将其作为新电子邮件重新发送。它还使用日期(包括毫秒)更改主题,因此它确保每封新电子邮件都有不同的主题并且独立于其他电子邮件。处理完所有消息后,将线程发送到Bin。
function OrganiseEmails() {
var threads = GmailApp.search("-in:trash -in:drafts -in:spam label:gmail2drive -label:to-gdrive-processed")
for (i in threads){
var messages = threads[i].getMessages();
for (j in messages){
if (messages[j].getAttachments().length > 0){
var to = messages[j].getTo();
var date = Utilities.formatDate(new Date(), "GMT","yyyy-MM-dd' at 'HH:mm:ss:SS' '");
var subject = "DVR motion detected - " + date;
var body = "test";
var attachment = messages[j].getAttachments()[0];
var options = {
attachments: attachment
}
GmailApp.sendEmail(to, subject, body, options);
}
}
var rem_label = GmailApp.getUserLabelByName("gmail2drive");
rem_label.removeFromThread(threads[i]);
threads[i].moveToTrash();
}
}
我对 Gmail2Drive 和 Config.gs 脚本进行了一些更改,因为现在它不会按标签过滤,而是按主题过滤:
代码.gs
getOrCreateLabel()
。我们在此脚本中没有使用过滤器,因此没有必要。var label = getOrCreateLabel(config.processedLabel);
。gSearchExp
变量声明中删除了 + "-label:"+ config.processedLabel
thread.addLabel(label);
行更改为 thread.moveToTrash();
Config.gs
globalFilter
搜索参数中添加了 in:inbox
以避免再次处理线程,因为现在它们也在“已发送”中。"processedLabel": "to-gdrive/processed",
“filter”
从“label:gmail2drive”
更改为“subject:'检测到DVR Action - '”
编辑
最后,我们决定将两个代码放在一起,因此在 code.gs
中创建一个新函数,并首先在 Gmail2Drive 函数中调用它。此外,您可以永久删除电子邮件,而不是更改标签Gmail.Users.Threads.remove("me", threadid);
发送电子邮件后。
关于google-apps-script - Gmail 到 Google Drive 脚本损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57037604/
我正在尝试使用 Drive SDK 将文件上传到 Google Drive . 我想知道是否有 API 方法来检查用户的驱动器是否有足够的容量来保存文件。如果是,请指出我应该搜索的位置,如果不是,最好
我想在我正在开发的新 android 应用程序(又名 drive.appdata 范围)中使用特殊应用程序数据文件夹中的文件。 谷歌的你们在与 Google Play Services 4.2 捆绑的
列出Google云端硬盘文件的JavaScript示例使用gapi.client.drive.files.list()。 尝试使用此方法时,出现错误“无法读取未定义的属性'files'”。 该问题和解
我正在尝试使用 Google Cloud REST API 获取特定文件夹大小。 我已经尝试过使用 REST API 的“ about ”方法,但在这种方法中,我获得了整个云存储的已用字节总数和可用空
我只是想了解在 G Suite 上使用 Team Drive 获取团队存储库与仅使用 Google Drive 上的共享文件夹相比的优势。通过搜索不同的来源并进行测试,到目前为止我发现了以下结果。 坦
我正在尝试使用 Google Drive API (v3) 更新文档 在 Google 云端硬盘中。 我已阅读此迁移指南: Google Drive API v3 Migration 并对其进行编码以
我曾尝试将我的 Web 应用程序集成到 Google 云端硬盘用户界面(以打开文件),但没有取得多大成功。我无法使用 OAuth 范围 https://www.googleapis.com/auth/
使用Google Drive API时 我使用 com.google.api.services.drive.Drive.files() 来迭代一些文件。 我注意到所有目录对象都没有权限? 当我使用 F
Google Drive API 和 Google Spreadsheet API (v 3.0) 都支持获取与以下 URL 对应的 [KEY] 的方法: https://docs.google.co
我正在尝试将本地 CSV 文件上传到 Google Drive 并在那里像 Google 电子表格一样显示它。但是,当我转到 Google Drive 并单击指向我的文件的链接时,我只能下载它,而不能
我正在尝试使用 ArrayBuffer 的内容在 Google Drive 上创建一个文件。我正在使用 Javascript 和 Drive API 的第 3 版。 我设法使用 this code s
我可以使用 google drive android api 将文本文件上传到 google drive 中的文件夹。 Sample code 但是我想上传一张图片到谷歌驱动器。这可能吗? 创建文本文
我想知道以下是否可行,因为我似乎无法在网上找到任何具体的方法: 当 Google Takeaway 服务将新的 takeout-xxx.zip 文件上传到我的 Google Drive Takeawa
是否可以对 Google Drive 上的文件执行“追加”操作? 假设我想使用 Google Drive 保存日志条目“as-they-come-in”,是否有某种“仅附加”操作可用? 最佳答案 如果
看着 Google Drive scopes .我明白: https://www.googleapis.com/auth/drive.install - 用于让用户批准安装应用程序的特殊范围 如果我希
我有一个带有两个父文件夹( FILE-1 和 FOLDER-1 )的文档( FOLDER-2 )。 如果我删除 FOLDER-1 , FILE-1也被删除。然而,我预计只有FOLDER-1将被删除,并
我正在测试Google Drive API。测试脚本执行HTTP GET来访问Files-> List API,但是我总是以某种方式在项目中得到一个空列表。我的Google驱动器中有数百个文件,因此结
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 8年前关闭。 Improve this q
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 8年前关闭。 Improve this q
我将我的应用程序的文件托管在 Google Drive 上,它会在首次启动后立即下载它们。一切都很好,但在我发布新的应用程序版本后,下载数量不断增加,文件由于某些原因变得不可用。虽然我没有改变任何东西
我是一名优秀的程序员,十分优秀!