How to permanently delete Mails within scripts via MailApp? - google-apps-script

I have found the following script in this forum and works really smoothly (takes files, saves files in the right folder, etc.). Namely I receive a txt. file every morning with relative quantities which I would like to import and save to my Gdrive (to later use in other scripts). The file is named with todays date which I have used the Utilities.formatDate function to obtain.
Unfortunately every time I run the script I get all files from even from previous days which would spam my folder full in a couple of days. Therefore my question is whether one can delete the emails after the script that my google search query will not find the previous emails the following day?
Any help with this conundrum appreciated!!
P.S: Email comes from the same recipient, with an identical subject "Stock_Load", however the attachment is named "date"_Todays Date.
// GLOBALS
//Array of file extension which you would like to extract to Drive
var fileTypesToExtract = ['txt'];
//Name of the folder in google drive i which files will be put
var folderName = 'GmailToDrive';
//Name of the label which will be applied after processing the mail message
var labelName = 'GmailToDrive';
function GmailToDrive(){
//build query to search emails
var query = 'filename:stock_'+Utilities.formatDate(new Date(), "GMT", "yyyyMMdd").toString()+'.gpg.txt';
//filename:jpg OR filename:tif OR filename:gif OR fileName:png OR filename:bmp OR filename:svg'; //'after:'+formattedDate+
for(var i in fileTypesToExtract){
query += (query == '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
}
query = 'in:inbox has:nouserlabels is:unread' + query;
var threads = GmailApp.search(query);
var label = getGmailLabel_(labelName);
var Folder = DriveApp.getFolderById("XXX");
for(var i in threads){
var mesgs = threads[i].getMessages();
for(var j in mesgs){
//get attachments
var attachments = mesgs[j].getAttachments();
for(var k in attachments){
var attachment = attachments[k];
var isImageType = checkIfImage_(attachment);
if(!isImageType) continue;
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
Folder.addFile(file);
}
}
threads[i].addLabel(label);
}
};
//This function will get the parent folder in Google drive
function getFolder_(folderName){
var folder;
try {folder = DriveApp.getFolder(folderName)}
catch(e){ folder = DriveApp.createFolder(folderName);}
return folder;
}
//getDate n days back
// n must be integer
function getDateNDaysBack_(n){
n = parseInt(n);
var today = new Date();
var dateNDaysBack = new Date(today.valueOf() - n*24*60*60*1000);
return dateNDaysBack;
}
function getGmailLabel_(name){
var label = GmailApp.getUserLabelByName(name);
if(label == null){
label = GmailApp.createLabel(name);
}
return label;
}
//this function will check for filextension type.
// and return boolean
function checkIfImage_(attachment){
var fileName = attachment.getName();
var temp = fileName.split('.');
var fileExtension = temp[temp.length-1].toLowerCase();
if(fileTypesToExtract.indexOf(fileExtension) != -1) return true;
else return false;
}

Related

Copying attachments from Gmail to Google Drive folder and overwriting old files with Apps Script

I am trying to user Google Apps Script to automate downloading attachments from a Gmail inbox to a specific folder on the account's Google Drive. I found the code below that does that part well, but I also need it to overwrite files of the same name with the new file or delete the old file and upload the new in its place. Also, it still seems to be downloading all filetypes from emails that have more than one attachment when I just need .xlsx files to be copied. Any help would be much appreciated. (credit goes to googleappsscript.org for the code)
// GLOBALS
//Array of file extension which you would like to extract to Drive
var fileTypesToExtract = ['jpg', 'tif', 'png', 'gif', 'bmp', 'svg'];
//Name of the folder in google drive i which files will be put
var folderName = 'GmailToDrive';
//Name of the label which will be applied after processing the mail message
var labelName = '#indrive';
function GmailToDrive(){
//build query to search emails
var query = '';
//filename:jpg OR filename:tif OR filename:gif OR fileName:png OR filename:bmp OR filename:svg'; //'after:'+getDateNDaysBack_(1)+
for(var i in fileTypesToExtract){
query += (query === '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
}
query = 'in:inbox has:nouserlabels ' + query;
// query += ' after:'+getDateNDaysBack_(1);
var threads = GmailApp.search(query);
var label = getGmailLabel_(labelName);
var parentFolder;
if(threads.length > 0){
parentFolder = getFolder_(folderName);
}
var root = DriveApp.getRootFolder();
for(var i in threads){
var mesgs = threads[i].getMessages();
for(var j in mesgs){
//get attachments
var attachments = mesgs[j].getAttachments();
for(var k in attachments){
var attachment = attachments[k];
// var isDefinedType = checkIfDefinedType_(attachment);
// if(!isDefinedType) continue;
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
parentFolder.addFile(file);
root.removeFile(file);
}
}
threads[i].addLabel(label);
}
}
//This function will get the parent folder in Google drive
function getFolder_(folderName){
var folder;
var fi = DriveApp.getFoldersByName(folderName);
if(fi.hasNext()){
folder = fi.next();
}
else{
folder = DriveApp.createFolder(folderName);
}
return folder;
}
//getDate n days back
// n must be integer
function getDateNDaysBack_(n){
n = parseInt(n);
var date = new Date();
date.setDate(date.getDate() - n);
return Utilities.formatDate(date, Session.getScriptTimeZone(), 'yyyy/MM/dd');
}
function getGmailLabel_(name){
var label = GmailApp.getUserLabelByName(name);
if(!label){
label = GmailApp.createLabel(name);
}
return label;
}
//this function will check for filextension type.
// and return boolean
function checkIfDefinedType_(attachment){
var fileName = attachment.getName();
var temp = fileName.split('.');
var fileExtension = temp[temp.length-1].toLowerCase();
if(fileTypesToExtract.indexOf(fileExtension) !== -1) return true;
else return false;
}
Here is a sample code:
// GLOBALS
//Array of file extension which you would like to extract to Drive
var fileTypesToExtract = ['xlsx'];
//Name of the folder in google drive i which files will be put
var folderName = 'GmailToDrive';
//Name of the label which will be applied after processing the mail message
var labelName = '#indrive';
function GmailToDrive() {
var query = '';
for(var i in fileTypesToExtract){
query += (query === '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
}
query = 'in:inbox has:nouserlabels ' + query;
Logger.log(query);
var threads = GmailApp.search(query);
var label = getGmailLabel_(labelName);
var parentFolder = getFolder_(folderName);
for(var i in threads){
var mesgs = threads[i].getMessages();
for(var j in mesgs){
//get attachments
var attachments = mesgs[j].getAttachments();
for(var k in attachments){
var attachment = attachments[k];
Logger.log(attachment.getName());
Logger.log(attachment.getContentType())
//Check if attached file is xlsx file
if(attachment.getContentType() == MimeType.MICROSOFT_EXCEL){
var attachmentBlob = attachment.copyBlob();
//Check if filename exist in the drive folder then remove the file
var files = parentFolder.getFilesByName(attachment.getName());
while (files.hasNext()) {
var file = files.next();
Logger.log("FILE EXIST. Removing.....");
//Remove existing file
file.setTrashed(true);
}
//Create a new file in the drive folder
var newFile = parentFolder.createFile(attachmentBlob);
}
}
}
threads[i].addLabel(label);
}
}
function getGmailLabel_(name){
var label = GmailApp.getUserLabelByName(name);
if(!label){
label = GmailApp.createLabel(name);
}
return label;
}
//This function will get the parent folder in Google drive
function getFolder_(folderName){
var folder;
var fi = DriveApp.getFoldersByName(folderName);
if(fi.hasNext()){
folder = fi.next();
}
else{
folder = DriveApp.createFolder(folderName);
}
return folder;
}
Modifications done:
Replace fileTypesToExtract to just extract .xlsx files
Check if current attachment is a xlsx file using GmailAttachment.getContentType()
Include checking if the current attachment exist in the drive folder using Folder.getFilesByName(name). Then remove the file using File.setTrashed(trashed)
Create a new file using Folder.createFile(blob)
In your script you commented out the inDefinedType functionality.
with regard to replacing file content or deleting files of same name you could
look for all of the files in parentFolder with getFilesByName() and trash all of the old ones.

Save attachments from last mails

I need saving the attachments im mails from one sender with file format 'gz' to folder GmailToDrive in Google-drive with replacement old file
Here Apps script saving attachments from last mail I get answer with script, but something is wrong.
I think, this - query = 'in:inbox has:nouserlabels ' + query + ' AND from:entrepot#fmlogistic.fr AND older_than:4h';
Can you help me? thank you very much!
// GLOBALS
//Array of file extension which you would like to extract to Drive
var fileTypesToExtract = ['gz'];
//Name of the folder in google drive i which files will be put
var folderName = 'GmailToDrive';
//Name of the label which will be applied after processing the mail message
var labelName = 'GmailToDrive';
function GmailToDrive(){
var query = '';
//filename:jpg OR filename:tif OR filename:gif OR fileName:png OR filename:bmp OR filename:svg'; //'after:'+formattedDate+
for(var i in fileTypesToExtract){
query += (query === '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
}
//ADD the only email adress you want to check + EDIT : only last 24h emails
query = 'in:inbox has:nouserlabels ' + query + ' AND from:entrepot#fmlogistic.fr AND older_than:4h';
var threads = GmailApp.search(query);
var label = getGmailLabel_(labelName);
var parentFolder;
if(threads.length > 0){
parentFolder = getFolder_(folderName);
}
var root = DriveApp.getRootFolder();
for(var i in threads){
var mesgs = threads[i].getMessages();
for(var j in mesgs){
//ADD: check if the mail is unread:
if (mesgs[j].isUnread()) {
var attachments = mesgs[j].getAttachments();
for(var k in attachments){
var attachment = attachments[k];
var isDefinedType = checkIfDefinedType_(attachment);
if(!isDefinedType) continue;
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
parentFolder.addFile(file);
root.removeFile(file);
}
}
} // close if unread
} // close for msg loop
//ADD: Set thread (all mail included) as read
GmailApp.markThreadRead(threads[i]);
threads[i].addLabel(label);
}
As per documentation:
older_than can be used for messages older than a time period using d (day), m (month), and y (year)
So, 4h won't work.

Adding Replace Existing File to GmailToDrive App Script - Follow up Question

This is an additional question off of the related post: Adding Replace Existing File to GmailToDrive App Script answered by #Tanaike.
I'm trying to use the code from the previous post with the Edit function with an xlsx file. Everything seems to be working fine where it grabs the file and saves it and it even updated the modified date in the google drive folder. However, the content of the excel file does not change from the original. I've enabled the Drive API. Is this compatible with xlsx file types? Is there something additional needed to actually update the content in the file and not just the metadata?
// GLOBALS
//Array of file extension which you would like to extract to Drive
var fileTypesToExtract = ['xlsx'];
//Name of the folder in google drive i which files will be put
var folderName = 'YourfolderName;
//Name of the label which will be applied after processing the mail message
var labelName = 'Saved2';
function GmailToDrive(){
//build query to search emails
var query = '';
//filename:jpg OR filename:tif OR filename:gif OR fileName:png OR filename:bmp OR filename:svg'; //'after:'+formattedDate+
for(var i in fileTypesToExtract){
query += (query === '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
}
query = 'in:inbox label:MyCustomLabel has:attachment ' + query;
var threads = GmailApp.search(query);
var label = getGmailLabel_(labelName);
var parentFolder;
if(threads.length > 0){
parentFolder = getFolder_(folderName);
}
var root = DriveApp.getRootFolder();
for(var i in threads){
var mesgs = threads[i].getMessages();
for(var j in mesgs){
//get attachments
var attachments = mesgs[j].getAttachments();
for(var k in attachments){
var attachment = attachments[k];
var isDefinedType = checkIfDefinedType_(attachment);
if(!isDefinedType) continue;
var attachmentBlob = attachment.copyBlob();
var existingFile = DriveApp.getFilesByName(attachment.getName());
if (existingFile.hasNext()) {
var file = existingFile.next();
Drive.Files.update({}, file.getId(), attachmentBlob);
} else { // Added
var file = DriveApp.createFile(attachmentBlob); // Added
parentFolder.addFile(file); // Added
root.removeFile(file); // Added
}
}
}
threads[i].addLabel(label);
}
}
//This function will get the parent folder in Google drive
function getFolder_(folderName){
var folder;
var fi = DriveApp.getFoldersByName(folderName);
if(fi.hasNext()){
folder = fi.next();
}
else{
folder = DriveApp.createFolder(folderName);
}
return folder;
}
//getDate n days back
// n must be integer
function getDateNDaysBack_(n){
n = parseInt(8);
var date = new Date();
date.setDate(date.getDate() - n);
return Utilities.formatDate(date, Session.getScriptTimeZone(), 'yyyy/MM/dd');
}
function getGmailLabel_(name){
var label = GmailApp.getUserLabelByName(name);
if(!label){
label = GmailApp.createLabel(name);
}
return label;
}
//this function will check for filextension type.
// and return boolean
function checkIfDefinedType_(attachment){
var fileName = attachment.getName();
var temp = fileName.split('.');
var fileExtension = temp[temp.length-1].toLowerCase();
if(fileTypesToExtract.indexOf(fileExtension) !== -1) return true;
else return false;
}
Because .xlsx is the Excel format, Apps Script can't modify its content because it's not a Google product, it's like trying to modify a pdf using Apps Script, but don't worry, you could convert the .xlsx file into the native Google Spreadsheet format and then handle it like a normal Google Spreadsheet. This function will do the conversion for you:
// this Function will convert your .xlsx files into native Google Spreadsheet format
function convertExceltoGoogleSpreadsheet(parentFolder) {
var files = parentFolder.getFiles();
while(files.hasNext()){
var file = files.next();
// If the file contains the .xlsx extention in its name
// then it will return an array with length 2
var filename = file.getName().split(/.xlsx?/);
if(filename.length > 1){
// build info to create the new file with Google Spreadsheet format
var resource = {
title: filename[0],
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{id: parentFolder.getId()}],
};
// Return the response after creating the file
return Drive.Files.insert(resource, file.getBlob());
}
}
}
Then, use that function in this part of your code:
...
var attachmentBlob = attachment.copyBlob();
var existingFile = DriveApp.getFilesByName(attachment.getName());
if (existingFile.hasNext()) {
var file = existingFile.next();
Drive.Files.update({}, file.getId(), attachmentBlob);
} else {
var file = DriveApp.createFile(attachmentBlob)
parentFolder.addFile(file);
root.removeFile(file);
}
// Let's change the format and insert a "Hello world" message
// ----START----
var spreadSheetResponse = convertExceltoGoogleSpreadsheet(parentFolder);
var spreadSheetId = spreadSheetResponse.getId()
var sheet = SpreadsheetApp.openById(spreadSheetId).getSheets()[0];
sheet.getRange(1, 1).setValue("Hello world");
// ----END----
...
Notice
In my code I left the .xlsx file in the Drive, if you want you could delete it after converting it iinto the native Google Spreadsheet format
Docs
This is what I used to help you:
SpreadsheetApp
Drive - Class File

Google apps script running slow

I have a homemade script for saving attachments to Drive from Gmail. I'm looping through the attachments and Logging the time when each attachment is saved. I've noticed some weird discrepancies between some saves. As the following image shows. Sometimes there is a minute and a half between loops. Each file is a pdf and they are all roughly the same size, e.g. 100 kb. each. It's not unusual that this script processes 50 attachments from a single email.
My for loop is as follows:
for (var k in attachments) {
var attachment = attachments[k];
var isDefinedType = checkIfDefinedType_(attachment);
if (!isDefinedType) continue;
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
if (parentFolder.addFile(file)) {
root.removeFile(file);
writeToSheet(file, message, msgId, k, totalattachments)
}
}
Below are the relevant functions.
function checkIfDefinedType_(attachment) {
var fileName = attachment.getName();
var temp = fileName.split('.');
var fileExtension = temp[temp.length - 1].toLowerCase();
if (fileTypesToExtract.indexOf(fileExtension) !== -1) return true;
else return false;}
function writeToSheet(file, message, msgId, k, totalattachments) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var fileId = file.getId();
var fileUrl = file.getUrl();
var formattedDate = Utilities.formatDate(new Date(), "GMT", "dd-MM-yyyy HH:mm:ss");
var emailSubject = message.getSubject();
var emailFrom = message.getFrom();
var sheet = ss.getSheetByName('Log');
sheet.appendRow([msgId, formattedDate, emailFrom, emailSubject, k, totalattachments, file, fileId, fileUrl]);}
Is there something wrong with my code?
Well turns out, saving a file to the root, then copying it to another directory and then delete the original file takes longer than just put it in the correct directory to begin with.
I changed this:
var file = DriveApp.createFile(attachmentBlob);
if (parentFolder.addFile(file)) {
root.removeFile(file);
}
to this:
var file = parentFolder.createFile(attachmentBlob);
Although I'm pretty sure this method wasn't always possible. Maybe I'm mistaken.

Save attachments from only new messages

I copied some codes to move Gmail attachments to Google Drive, add a label to the mail, then trash or archive the mail (I have tried both trash and archive but results are the same):
The incoming mails are from the same sender (a machine) with the same subject every time.
The email arrives at random timing, could be several mails in a minute or nothing in few hours.
The filenames has the suffix in yyyy-mm-dd-hh-mm-ss format.
The problem I am facing is when the script processes the new emails in the inbox, it also processes those in the trash. This results duplication of older files. Same problem happens even if I change moveToTrash() to moveToArchive().
How can I prevent my script from duplicating older files (from previously processed emails)?
function GmailToDrive(){
//build query to search emails
var query = '';
//filename:jpg OR filename:tif OR filename:gif OR fileName:png OR filename:bmp OR filename:jpeg'; //'after:'+formattedDate+
for(var i in fileTypesToExtract){
query += (query === '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
}
query = 'in:inbox has:nouserlabels ' + query;
var threads = GmailApp.search(query);
var label = getGmailLabel_(labelName);
var parentFolder;
if(threads.length > 0){
parentFolder = getFolder_(folderName);
}
var root = DriveApp.getRootFolder();
for(var i in threads){
var mesgs = threads[i].getMessages();
mesgs.reverse();
for(var j in mesgs){
//get attachments
var attachments = mesgs[j].getAttachments();
for(var k in attachments){
var attachment = attachments[k];
var isDefinedType = checkIfDefinedType_(attachment);
if(!isDefinedType) continue;
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
parentFolder.addFile(file);
root.removeFile(file);
}
}
threads[i].addLabel(label);
threads[i].moveToTrash();
threads[i].refresh();
}
}