Fusion tables importRows via Apps Script Failing more than not - google-apps-script

I am trying to pull csv attachments from a GMail account and push them to a Fusion table. It works sometimes but most of the time it fails with the error "Execution failed: Internal error when processing import. Please try again." from the importRows call for the Fusion table. The size of the import is ~4k so well below the 1m limit.
I will try using the Fusion table SQL INSERT option instead of importRows but just wanted to see if I was perhaps doing something wrong with the importRows call. I even placed a delay of 5 seconds between calls to see if perhaps the Fusion table needed to be fed more slowly.
Here is the App Script:
function getDataFromMailbox() {
var tableID = "XXXXXXXX";
var threads = GmailApp.getInboxThreads();
if (threads.length) {
var thread = threads.pop();
var messages = thread.getMessages();
for (var j=0; j < messages.length; j++) {
var message = messages[j];
if ( message.isUnread() ) {
var from = message.getFrom();
if (from == "xxxxxx#gmail.com") {
var attachments = message.getAttachments();
for (var k=0; k< attachments.length; k++) {
var attachment = attachments[k];
Logger.log( attachment.getSize() );
FusionTables.Table.importRows(tableID, attachment, {startLine:2});
}
} else {
thread.moveToTrash(); // Thread isn't from our source
}
message.markRead();
}
}
Logger.log("Processed %s messages", messages.length);
if ( !thread.isUnread() ) { thread.moveToArchive(); }
}
}

I finally had the chance to look into this again. It looks like the sleep call was the key. If I have a 5 second sleep after a fusion table import I get the import error. If I sleep my script for 10 seconds I get a timeout error. 7 seconds seems to be just right (at least today). Here is my updated script in case anyone wants to log data to a gmail account and then pull it to a Fusion table with an App Script.
function getDataFromMailbox() {
var tableID = "XXXXXXXXXXXXXXXXXX";
var threads = GmailApp.getInboxThreads();
while (threads.length) {
var thread = threads.pop();
var messages = thread.getMessages();
for (var j=0; j < messages.length; j++) {
var message = messages[j];
if ( message.isUnread() ) {
var from = message.getFrom();
if (from == "XXXXXXXXX#gmail.com") {
var attachments = message.getAttachments();
for (var k=0; k< attachments.length; k++) {
var attachment = attachments[k];
var attString = attachment.getDataAsString();
var lines = attString.match(/^.*((\r\n|\n|\r)|$)/gm);
lines.shift(); lines.shift();
Logger.log( lines.length );
FusionTables.Table.importRows(tableID, attachment, {startLine:2});
}
} else {
thread.moveToTrash(); // Thread isn't from our source
}
Logger.log( "Processed message: " + message.getId() );
message.markRead();
Utilities.sleep(7000); // Wait for fusion tables to catch up
}
}
Logger.log("Processed %s messages", messages.length);
if ( !thread.isUnread() ) { thread.moveToArchive(); }
}
}

Related

Permanently delete gmail message after some days

I'm using this script for deleting old messages from gmail every X days.
It functions correctly, however messages are sent to trash.
I want to delete the messages permanently without sending them to trash.
Someone can modify this script?
// The name of the Gmail Label that is to be autopurged?
var GMAIL_LABEL = "mylabel";
// Purge messages automatically after how many days?
var PURGE_AFTER = "21";
function purgeGmail() {
var age = new Date();
age.setDate(age.getDate() - PURGE_AFTER);
var purge = Utilities.formatDate(age, Session.getTimeZone(), "yyyy-MM-dd");
var search = "label:" + GMAIL_LABEL + " before:" + purge;
// This will create a simple Gmail search
// query like label:Newsletters before:10/12/2012
try {
// We are processing 100 messages in a batch to prevent script errors.
// Else it may throw Exceed Maximum Execution Time exception in Apps Script
var threads = GmailApp.search(search, 0, 100);
// For large batches, create another time-based trigger that will
// activate the auto-purge process after 'n' minutes.
// if (threads.length == 100) {
// ScriptApp.newTrigger("purgeGmail")
// .timeBased()
// .at(new Date((new Date()).getTime() + 1000*60*10))
// .create();
// }
// An email thread may have multiple messages and the timestamp of
// individual messages can be different.
for (var i=0; i<threads.length; i++) {
var messages = GmailApp.getMessagesForThread(threads[i]);
for (var j=0; j<messages.length; j++) {
var email = messages[j];
if (email.getDate() < age) {
email.moveToTrash();
}
}
}
// If the script fails for some reason or catches an exception,
// it will simply defer auto-purge until the next day.
} catch (e) {}
}
thanks
It's pretty simple all you have to do is get all of your message id's in an array and then use the following two lines.
var request={"ids":messageIdArray};
Gmail.Users.Messages.batchDelete(request, "me");
You will have to enable the Advanced Gmail API
batchDelete
So if the rest of your code actually works then this should do it:
var GMAIL_LABEL = "mylabel";
var PURGE_AFTER = "21";
function purgeGmail() {
var age = new Date();
age.setDate(age.getDate() - PURGE_AFTER);
var purge = Utilities.formatDate(age, Session.getTimeZone(), "yyyy-MM-dd");
var search = "label:" + GMAIL_LABEL + " before:" + purge;
try {
var msgA=[];
for (var i=0; i<threads.length; i++) {
var messages = GmailApp.getMessagesForThread(threads[i]);
for (var j=0; j<messages.length; j++) {
var email = messages[j];
if (email.getDate() < age) {
msgA.push(email.getId());
}
}
}
} catch (e) {}
}

Need to split the row based on Error and Warning and remove particular content

While run the provided script its working perfect, but need to modify. this is the screenshot tells what i need, i am trying to change script , please help me if you can
function autocopy() {
var label = GmailApp.getUserLabelByName("Sanmina EDI Failed Concurrent Jobs Alert");
var threads = label.getThreads();
var read = threads.getMessages();
var uread = threads.isUnread();
for(var i = 0; i <= uread.length; i++) {
var message=uread(i);
}
var message1 = new message.Date();
var day = message1.getUTCDate();
var bodycontent = message.getbody();
var action = bodyContents.search("Invoice")
var action1 = bodyContents.search("Error")
var action2 = bodyContents.search("Terminated")
if (action > 0) {
var out ="Need to create SR"
} else if (action1 > 0 || action2 > 2) {
var out ="Need to create SR"
} else {
var out ="Printing output file"
}
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
activeSheet.appendRow([day, bodycontent, out]);
}
I want to extract the data from email to spreadsheet,by reading unread thread id and using for looping the reach from read thread id to unread thread id and print the mail body content and date from the unread email.
I reworked your code a bit. Put some comments in it so that you can see clearly what is happening in each line. Your issue was that you were trying to use methods on the wrong objects (for example, an array of threads does not have a getMessages method, so you have to loop through each thread and get the messages for each specific thread).
function autocopy() {
var label = GmailApp.getUserLabelByName("Sanmina EDI Failed Concurrent Jobs Alert");
// Get all threads belonging to this label
var threads = label.getThreads();
// Loop through each thread
for (var i = 0; i < threads.length; i++) {
// Check whether thread is unread
if (threads[i].isUnread()) {
// Get all messages for each unread thread
var messages = threads[i].getMessages();
// Loop through all messages for each unread thread
for (var j = 0; j < messages.length; j++) {
// Check whether message is unread
// (delete this condition if you want all messages in an unread
// thread to be printed in your spreadsheet, read or unread)
if (messages[j].isUnread()) {
var day = messages[j].getDate();
var bodyContent = messages[j].getBody(); // Use getPlainBody() instead if you don't want html tags;
var action = bodyContent.search("Invoice");
var action1 = bodyContent.search("Error");
var action2 = bodyContent.search("Terminated");
if (action > 0) {
var out = "Need to create SR"
} else if (action1 > 0 || action2 > 2) {
var out = "Need to create SR"
} else {
var out = "Printing output file"
}
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
activeSheet.appendRow([day, bodyContent, out])
}
}
}
}
}
I hope this works for you!

Count number of email sent to a person

I am trying to get the number of times that a person has been sent an email, so I can keep track of leads, for example
user#domain.com was emailed 5 times
user2#domain.com was emailed 3 times
From reading the docs I cannot figure this one out
Is this possible?
EDIT:
function myFunction(e) {
e = "someemail#gmail.com";
var threads = GmailApp.search("to:" + e + "");
var count = 0;
for (var i = 0; i < threads.length; i++) {
count++;
}
Logger.log(count) //1
}
This gives me threads but no number of messages
I think you are on the right lines using search() to find the sent items. This is a snippet I use to scan through all the unread emails in the inbox, and the processing that email. You'll want something similar:
var totalThreads = GmailApp.getInboxThreads().length
// Read in READ_AT_ONCE pages of email at a time
for (var pageindex = 0; pageindex < totalThreads; pageindex += READ_AT_ONCE) {
var threads = GmailApp.getInboxThreads(pageindex, READ_AT_ONCE)
var msgs = GmailApp.getMessagesForThreads(threads)
var numThreads = threads.length
// Read in all the threads in the batch
for (var threadIndex = 0; threadIndex < numThreads; threadIndex++) {
var numMsgs = msgs[threadIndex].length
// Process each msg in the thread
for (var msgIndex = 0; msgIndex < numMsgs; msgIndex++) {
var msg = msgs[threadIndex][msgIndex]
if (!msg.isUnread() || msg.isInTrash()) {
continue
}
Email_.processMsg(msg)
} // for each msg
} // for each thread
} // for each batch

Google Apps script stops randomly or refuses to launch

I have developed a Google Apps script in a Google Drive spreadsheet that processes e-mails with a certain label (download notifications) and adds these to the spreadsheet. I'm running this through the script editor of the spreadsheet.
My initial solution was quite inefficient - the whole analysis was repeated each time on all e-mails, which caused the runtime to increase for each day. A few days ago I got an error message "runtime exceeded", which is not strange.
My problem is that when trying to update the script to be more efficient, I get some weird problems. The script either stops randomly after processing a few e-mails, or simply refuses to start. Especially the script debugger, it begins to load but never starts.
I have tried several times over the last few days, and even created a new spreadsheet with the same code (in the same account), but still having these problems.
Sometimes when the script manages to run for a while, I have noted that the script output log does not match recent changes in the logging. I have of course saved the script before running it. It feels like there is some lock preventing my script from running/updating/refreshing?
Is there anyone here that recognize these problems?
The code is attached below.
The two relevant entry points are:
processInbox: Updates the spreadsheet based on new (starred) e-mails with a specific label. The label and star is set by an e-mail filter on reception. The star (indicating "new") is removed from each message after processing.
resetAllMsgs: Clears the spreadsheet and stars all relevant messages, causing processInbox to process all messages received with the relevant label.
function resetAllMsgs() {
Logger.log("Starting ResetAll");
var d = SpreadsheetApp.getActive();
var dl_sheet = d.getSheetByName("Download List");
var dlperday_sheet = d.getSheetByName("DownloadsPerDay");
dl_sheet.clear();
dlperday_sheet.clear();
Logger.log("Clearing spreadsheet");
dl_sheet.appendRow(["", "", "Downloads", ""]);
dl_sheet.appendRow(["", "", "Downloaders", ""]);
dl_sheet.appendRow(["Last Download Date", "First Download Date", "Email" , "Product", "Download Count"]);
dlperday_sheet.appendRow(["Date", "Download Count"]);
var label = GmailApp.getUserLabelByName("Download Notification");
// get all threads of the label
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
// get all messages in a given thread
var messages = threads[i].getMessages();
Logger.log("Starring thread " + i);
for (var j = 0; j < messages.length; j++) {
Logger.log(" Starring message " + j);
// Only starred messages are processed by processInbox
messages[j].star();
Utilities.sleep(100);
}
}
};
function processInbox() {
var d = SpreadsheetApp.getActive();
var dl_sheet = d.getSheetByName("Download List");
var dlperday_sheet = d.getSheetByName("DownloadsPerDay");
// If empty spreadsheet, reset the status of all relevant e-mails and add the spreadsheet headers
if (dl_sheet.getLastRow() <= 1) {
resetAll();
}
var label = GmailApp.getUserLabelByName("Download Notification");
var k = 0;
// get all threads of the label
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
if (threads[i].hasStarredMessages()) {
// get all messages in a given thread
var messages = threads[i].getMessages();
// iterate over each message
for (var j = 0; j < messages.length; j++) {
// Unread messages are not previously processed...
if (messages[j].isStarred()) {
var msg = messages[j].getBody();
msg = msg.replace(/\r?\n/g, "");
var email = getDownloader(msg);
if (email == "") {
Logger.log("Found no downloader info: " + messages[j].getSubject() + " " + messages[j].getDate());
}
var date = formatDate(getDownloadDate(msg));
// Check if a new date
var dateCell = find(date, dlperday_sheet.getDataRange(), 0);
if (dateCell == null) {
// If new date, append row in "downloads per day"
dlperday_sheet.appendRow([date, 1]);
dlperday_sheet.getRange(2, 1, dl_sheet.getLastRow()-1, 2).sort([1]);
}
else
{
// If existing date, update row in "downloads per day"
var dlcount = dlperday_sheet.getRange(dateCell.getRow(), dateCell.getColumn()+1).getValue();
}
var productname = getProductName(msg);
// Check if e-mail (user) already exists in the downloads list
var matchingCell = find(email, dl_sheet.getDataRange(), 0);
if ( matchingCell != null ) {
// If user e-mail exists, update this row
var lastDownloadDate = dl_sheet.getRange(matchingCell.getRow(), matchingCell.getColumn()-1).getValue();
var lastDownloadCount = dl_sheet.getRange(matchingCell.getRow(), matchingCell.getColumn()+2).getValue();
if (lastDownloadDate != date) {
dl_sheet.getRange(matchingCell.getRow(), matchingCell.getColumn()-1).setValue(date);
}
dl_sheet.getRange(matchingCell.getRow(), matchingCell.getColumn()+2).setValue(lastDownloadCount+1);
}
else // If new user e-mail, add new download row
{
dl_sheet.appendRow([date, date, email, productname, 1]);
dl_sheet.getRange(2, 4).setValue(dl_sheet.getRange(2, 4).getValue() + 1);
dl_sheet.getRange(4, 1, dl_sheet.getLastRow()-3, 5).sort([1]);
}
// Mark message as processed, to avoid processing it on the next run
messages[j].unstar();
}
}
}
}
};
/**
* Finds a value within a given range.
* #param value The value to find.
* #param range The range to search in.
* #return A range pointing to the first cell containing the value,
* or null if not found.
*/
function find(value, range, log) {
var data = range.getValues();
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].length; j++) {
if (log == 1)
{
Logger.log("Comparing " + data[i][j] + " and " + value);
}
if (data[i][j] == value) {
return range.getCell(i + 1, j + 1);
}
}
}
return null;
};
function getDownloader(bodystring) {
var marker = "Buyer Info";
var marker_begin_index = bodystring.indexOf(marker, 1000);
var email_begin_index = bodystring.indexOf("mailto:", marker_begin_index) + 7;
var email_end_index = bodystring.indexOf("\"", email_begin_index);
if (email_end_index < 1000)
{
return "";
}
var email = bodystring.substring(email_begin_index, email_end_index);
if (log == 1)
{
Logger.log("Found e-mail address: " + email + "");
Logger.log(" marker_begin_index: " + marker_begin_index);
Logger.log(" email_begin_index: " + email_begin_index);
Logger.log(" email_end_index: " + email_end_index);
}
latestIndex = email_end_index;
return email;
};
function formatDate(mydate)
{
var str = "" + mydate;
var dateParts = str.split("/");
var day = dateParts[1];
if (day.length == 1)
day = "0" + day;
var month = dateParts[0];
if (month.length == 1)
month = "0" + month;
return dateParts[2] + "-" + month + "-" + day;
};
function getDownloadDate(bodystring) {
var marker = "Download Date:</strong>";
var marker_begin_index = bodystring.indexOf(marker, latestIndex);
var date_begin_index = marker_begin_index + marker.length;
var date_end_index = bodystring.indexOf("<br>", date_begin_index);
latestIndex = date_end_index;
return bodystring.substring(date_begin_index, date_end_index).trim();
};
function getProductName(bodystring) {
var marker = "Item:</strong>";
var marker_begin_index = bodystring.indexOf(marker, latestIndex);
var pname_begin_index = marker_begin_index + marker.length;
var pname_end_index = bodystring.indexOf("</td>", pname_begin_index);
latestIndex = pname_end_index;
return bodystring.substring(pname_begin_index, pname_end_index).trim();
};
Update: Any script I run stops after about 5 seconds, even if it does not call any services.
I tried the following code:
function test() {
Logger.log("Test begins");
Utilities.sleep(5000);
Logger.log("Test ends");
}
The script terminates after about 5 sec, but the last line is not printed. If decreasing the delay to 3 seconds it behaves as expected.
Moreover, to make the script update properly after modifying it, I need to save it, start it, click cancel, and then start it again, otherwise it the log output seems to come from the old version. (I'm running this through the script editor.)
Also, the debugger refuses to start, even for the small script above. Seems to be some problem with my account (johan.kraft#percepio.se). Are there any google employee out there that can check this?

Accessing BigQuery with Google Spreadsheet

I look on the internet to see how can I import bigquery data inside google spreadsheet.
I found this appscript sample, but it doesn'twork API are not at the same level, and I do not find how to query with API2 or API#beta1 in appscript.
function runQuery() {
var ss = SpreadsheetApp.getActive();
var range = ss.getRangeByName('query');
var query = range.getCell(1, 1).getValue();
//var results = bigquery.query(query);
var header = ss.getRangeByName('header');
header.clearContent();
var output = ss.getRangeByName('output');
output.clearContent();
for (var i = 0; i < results.fields.length; i++) {
var field = results.fields[i];
header.getCell(1, 1 + i).setValue(field.id);
}
for (var i = 0; i < results.rows.length; i++) {
var row = results.rows[i].f;
for (var j = 0; j < row.length; ++j) {
output.getCell(1 + i, 1 + j).setValue(row[j].v);
}
}
}
Thanks in advance for your ideas,
GQ
UPDATE: We just added a new BigQuery + Apps Script Tutorial that should walk you through the answer to this question here: https://developers.google.com/apps-script/articles/bigquery_tutorial
#GQuery: We've very recently updated AppsScript to have access to the latest BigQuery API version (v2). Here's a simple example to get started, will display results in the AppScript log. We are working on an update to the AppScript/BigQuery documentation.
function runQuery() {
var projectId = 'YOUR PROJECT';
var sql = 'select word, word_count from publicdata:samples.shakespeare limit 100';
var queryResults;
// Run the query
try {
queryResults = BigQuery.Jobs.query(projectId, sql);
}
catch (err) {
Logger.log(err);
return;
}
// Loop until successful job completion
while (queryResults.getJobComplete() == false) {
try {
queryResults = BigQuery.Jobs.getQueryResults(projectId, queryResults.getJobReference().getJobId());
}
catch (err) {
Logger.log(err);
return;
}
}
var tableRows = queryResults.getRows();
for (var i = 0; i < tableRows.length; i++) {
var rowString = '';
var cols = tableRows[i].getF();
for (var j = 0; j < cols.length; j++) {
rowString += cols[j].getV() + '\t';
}
Logger.log(rowString);
I dont have the reputation to comment on hurricaneditka16. Therefore, I posted this answer:
This line
queryResults = BigQuery.Jobs.query(projectId, sql);
Should be replaced by
.query(
resource,
projectId);
Resource is a slight transformation on the sql you used before. Try this transformation and it will work.
function getResource(sql) {
var resource = '{"query": "sql"}'
resource = resource.replace('sql', sql);
return resource
}