Google Apps Scripts - Extract data from gmail into a spreadsheet - javascript

this is the first script i try to write from scratch. It's been no good up to now so i'm going to ask for some help.
Case: I recieve e-commerce confirmation emails from e-commerce sites no reply email address. In the email's body they send email address from buyers. I want to send an automated mail to the body's email address.
How i plan to do this (any suggetions to eliminate steps will be thanked).
Use a rule to tag incoming emails with a unique tag.
Use that tag to identify emails in gmail with a script, go one by one and extract the info i need. Use regex with the emails body content to extract the email address i need to send the automated emails. Plan is to get: subject, date, email from body.
Write all that info to a spreadsheet.
Get rid of unique tag info to prevent duplicate runs.
Then use form mule addon to send emails from the spreadsheet.
So far, i've dealt with steps 1 (easy), and been stuggling with steps 2 and 3 (im not a coder, i can read, undestrand and hack. writing from scratch is a completely different thing). Ive dealt with 4 before i think this is the best way to deal with it.
With the script i extract info to the spreadsheet, with the addon i use the info from the spreadsheet to send emails.
This is the code ive written so far. I've left the regex part for later cause i cant even write anything into the spreadsheet yet. once i get that working, ill start working in the regex and "remove the label" aspects of the script.
function myFunction() {
function getemails() {
var label = GmailApp.getUserLabelByName("Main tag/subtag");
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
var messages=threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var message=messages[j];
var subject=message.getSubject();
tosp(message);
}
}
}
function tosp(message){
var body=message.getBody()
var date=message.getDate();
var subject=message.getSubject();
var id= "my spreasheet id";
var ss = SpreadsheetApp.openById(id);
var sheet = ss.getActiveSheet();
sheet.appendRow(subject,date,body);
}
}
Any help would be appreciated.
Thanks
Sebastian

Following is the code I wrote and tested that performs the steps 2, 3 and 4 mentioned by you perfectly well.
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var label = GmailApp.getUserLabelByName("MyLabel");
var threads = label.getThreads();
for (var i=0; i<threads.length; i++)
{
var messages = threads[i].getMessages();
for (var j=0; j<messages.length; j++)
{
var msg = messages[j].getBody();
var sub = messages[j].getSubject();
var dat = messages[j].getDate();
ss.appendRow([msg, sub, dat])
}
threads[i].removeLabel(label);
}
}
One of the faults in your code was that the appendRow function accepts an array of elements specified within [ ] brackets.
Depending on where you're attaching this script, your line of code:
var ss = SpreadsheetApp.openById(id);
is not necessary if the script is being written in the script editor of the Spreadsheet where you want these emails to be logged. However, if there are multiple sheets in that spreadsheet, you can replace my line
var ss = SpreadsheetApp.getActiveSheet();
by
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
Another suggestion is that the current code will give you messages in HTML format. Hence, if you want to get the message in plain text as you see it, use:
var msg = messages[i].getPlainBody();
Now you can write another function for regex and pass the message msg to that. Hope this helps!

I made a ready-to-use script, explaining how to use it (from the start) as well, for those who need more assistance.
It's on gmail-to-google-sheets-script repository. Just read the content and follow the instructions.
How to use
Create a new Google Sheet
Access menu Tools > Script Editor
Copy the content from gmailt-to-sheets.gs to editor, replacing the sample code there
Replace the value on SEARCH_QUERY to your real query (Do your search on gmail first, copy and paste the search terms there)
Select saveEmails on menu (near "run" and "debug" buttons)
Click on "Run" button
It will ask for authorization at first run, proceed accepting it (it's your Gmail account authorizing your Google Script account)
After run, the results will be applied to you sheet
Changing fields
If you want to save different message attributes, take a look at gmail-message class and change your script file the code below comments with a ✏️ (pencil).

Related

send email with different PDFs to different emails attachment

I am trying to do automate send email to multiple sender(10 emails) with different PDFs(10). Is there a way to attach a pdf in the spreadsheet column next to email address? Then send email with sales quote in pdf as attachment. Is this can be done in JS in google sheet.
Appreciate if someone help me out.
If you're using Google Sheets it's possible, but you have to get creative. In fact you can send emails, with javascript, from google sheets using google scripts. I think if you get creative with a hidden sheet in the same workbook, have a formula populate that sheet with the layout of the PDF, then export that sheet as a PDF to attach to the email... it's doable.
You may find some inspiration here.
Basic send email from google sheets example here.
So, JavaScript runs in the client side. It means that your code is running the user browser. In a brief, you can't send emails just using JavaScript. You're going to need a server to do that.
For example, you may use Spring Boot with Java that already has a lot implemented method that makes your task, i.e, sending an email, super easy.
Have a look at http://spring.io/projects/spring-boot
You can do this by following the below steps,
Uploading the 10 attachments on one google drive folder
On your google sheet add the below script to get the file id
function listFilesInFolder() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("FileID").activate(); //The name of the google sheet is FileID in my case
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow(["File Name", "File-Id"]);
//change the folder ID below to reflect your folder's ID (look in the URL when you're in your folder)
var folder = DriveApp.getFolderById("*[Enter Folder ID here]*");
var contents = folder.getFiles();
var cnt = 0;
var file;
while (contents.hasNext()) {
var file = contents.next();
cnt++;
data = [
file.getName(),
file.getId(),
];
sheet.appendRow(data);
}
}
Build a simple script to send emails and have your 10 emails on one column and all the File IDs generated from the above code on the next column. Below is a sample script to send emails from spreadsheets,
function sendEmails() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Emails").activate(); // Emails is the sheet which has the email and File ID columns
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1, 1).getValue(); // Template is the sheet which has my email body
for (var i = 2;i<=lr;i++){
var currentEmail = ss.getRange(i, 1).getValue(); //Email IDs are on the first column for me
var currentAttachment = ss.getRange(i, 2).getValue(); //Assuming your File IDs are on the second column
var waiver = DriveApp.getFileById(currentAttachment);
var liabilityWaiver = waiver.getAs(MimeType.PDF);
MailApp.sendEmail(currentEmail, subjectLine, messageBody, {attachments:[liabilityWaiver],
cc:'abc#abc.com'}); // the cc is in case you want to CC someone else on the email
I hope this helps!

How to allow a user to write to a spreadsheet without sharing the file being written to

I want the user to be able to write information to a master sheet. I'm able to get the user to write to it by sharing the master sheet. However, I don't want them to really have access to view it. Is there any work-around this?
function writeRecords(currentSheet) {
// get current sheet
var currentLastRow = currentSheet.getLastRow();
var currentRange = currentSheet.getRange(2, 1, currentLastRow, 6);
var currentValues = currentRange.getValues();
// get master sheet
var masterSpreadSheet = SpreadsheetApp.openById("fakesheetid")
var masterSheet = masterSpreadSheet.getSheetByName('Sheet1');
var masterLastRow = masterSheet.getLastRow();
// need to insert into master spreadsheet startin from its last row
masterSheet.getRange((masterLastRow + 1), 1, currentLastRow, 6).setValues(currentValues);
}
Create a web app that run as you.
Related
HOW TO modify a google spreadsheet from collaborators that aren't editors?
Perhaps you should consider using Google Forms?
Google Forms allows you to set up an interface to gather information from a user and use a Google Sheet as the repository for which this information is dumped into.

Send email after new document is created from template that includes URL from new document

I have some script in Sheets that sends an email after a button is pressed letting me know the sheet is newly created. However, the way I have written the script sends me a link to the template, and not the newly created sheet. I want to have the email created include the URL from the new sheet and not the template. I have the script used below (with some information changed for anonymity):
function sendemail() {
MailApp.sendEmail("name#gmail.com", "New Sheet Created",
"The link for the new sheet is
https://docs.google.com/spreadsheets/");
}
Thank you for the help, I plan to check back frequently to answer any questions. If I need to clarify anything, please let me know. Thank you!
I think this answer might be what you are looking for:
https://webapps.stackexchange.com/questions/93305/how-to-find-url-of-the-current-sheet
function getSheetUrl() {
var SS = SpreadsheetApp.getActiveSpreadsheet();
var ss = SS.getActiveSheet();
var url = '';
url += SS.getUrl();
url += '#gid=';
url += ss.getSheetId();
return url;
}

Remove an attachment of a Gmail email with Google Apps Script

Using Google Apps Script (http://script.google.com), I know from the docs, how to send, forward, move to trash messages, etc. but I don't find how to remove a file attachement of an email, i.e.:
keep the text content (either in HTML or just plain text would be fine)
keep the original sender, keep the recipient
keep the original message date/hour (important!)
remove the attachment
If it's not possible via the API, is there a way to resend the message to myself, while keeping 1, 2 and 3?
Note: the GmailAttachment class looks interesting and allows to list recipients:
var threads = GmailApp.getInboxThreads(0, 10);
var msgs = GmailApp.getMessagesForThreads(threads);
for (var i = 0 ; i < msgs.length; i++) {
for (var j = 0; j < msgs[i].length; j++) {
var attachments = msgs[i][j].getAttachments();
for (var k = 0; k < attachments.length; k++) {
Logger.log('Message "%s" contains the attachment "%s" (%s bytes)',
msgs[i][j].getSubject(), attachments[k].getName(), attachments[k].getSize());
}
}
}
but I don't find how to remove an attachment.
Note: I've already studied many other solutions for doing this, I've already read nearly every article about this (solutions with dedicated web services, with local clients like Thunderbird + Attachment extractor plugin, etc.), but none of them are really really cool. That's why I was looking for a solution to do it manually via Google Apps Script.
Looks like messages will have to be re-created-ish:
Messages are immutable: they can only be created and deleted. No message properties can be changed other than the labels applied to a given message.
Using Advanced Gmail Service with the Gmail API insert() you can hack your way around it using: Gmail.Users.Messages.insert(resource, userId)
This advanced service must be enabled before use.
Example: [fill in the EMAIL_ID with an email_id or in whatever way you want to get the email]
function removeAttachments () {
// Get the `raw` email
var email = GmailApp.getMessageById("EMAIL_ID").getRawContent();
// Find the end boundary of html or plain-text email
var re_html = /(-*\w*)(\r)*(\n)*(?=Content-Type: text\/html;)/.exec(email);
var re = re_html || /(-*\w*)(\r)*(\n)*(?=Content-Type: text\/plain;)/.exec(email);
// Find the index of the end of message boundary
var start = re[1].length + re.index;
var boundary = email.indexOf(re[1], start);
// Remove the attachments & Encode the attachment-free RFC 2822 formatted email string
var base64_encoded_email = Utilities.base64EncodeWebSafe(email.substr(0, boundary));
// Set the base64Encoded string to the `raw` required property
var resource = {'raw': base64_encoded_email}
// Re-insert the email into the user gmail account with the insert time
/* var response = Gmail.Users.Messages.insert(resource, 'me'); */
// Re-insert the email with the original date/time
var response = Gmail.Users.Messages.insert(resource, 'me',
null, {'internalDateSource': 'dateHeader'});
Logger.log("The inserted email id is: %s",response.id)
}
This will remove the attachments from the email and re-insert it into your mailbox.
edit/update: New RegExp to work with html&plain-text only emails - should now work on multiple boundary strings

Removing Edit Access from a Sheet using email from a cell

I am trying to figure out how to remove someone from a spreadsheet using google app scripts.
Essentially, I have a central spreadsheet with information such as emails, names, UID's etc on it. I am trying to pull the email from this spreadsheet and use the removeEditor function to remove that email from another spreadsheet. You can view the code below.
var officerIDrow = officerID + 1;
var Tracker = SpreadsheetApp.getActive().getSheetByName('P_Tracker'); //the button is on the same sheet as this, this is why it is get active.
var PTBooking = SpreadsheetApp.openById("1JPS69ko99dQTEwjplF_l2l2G_T8RyHjxCyMxXd_AV_s"); //Referring to the other sheet where the email will be removed from editors.
var EmailAddressRange = "F" + officerIDrow; //This is the column where the emails are stored. The officer ID row refers to the user inputted value in a dialog. Don't worry about this, I have already checked to see if this is the issue,
var EmailAddress1 = Tracker.getRange(EmailAddressRange);
var EmailAddress2 = EmailAddress1.getValue();
var EmailAddress3 = Utilities.formatString(EmailAddress2); //In my desperation, I was trying to see if setting it as string would help.
PTBooking.removeEditor(EmailAddress3);
This isn't the full version of the code. If you'd like to see it, you can click here. But all that matters is above, everything else works fine.
The code above runs fine until it hits the last line where it tries to remove the email. The error message that appears says: "Invalid email: ". I'm assuming after the "email:" bit, it should display what has been pulled. But it doesn't! I have no idea why it isn't finding and using the email to remove people.
Can anyone spot any issues?
Thanks,
Shaun.
This basic test worked for me. It could read email address from the spreadsheet then remove editors from the external sheet. I tried to copy your example, but I don't know how the officerIDrow works, but I assume it's a number. So just stored a number as a var
function myTest() {
var ss = SpreadsheetApp.openById("ID HERE");
var idRow = 11;
var tracker = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("tracker");
var emailCell = "F"+idRow;
Logger.log(emailCell);
var emailAddress = tracker.getRange(emailCell).getValue();
Logger.log(emailAddress);
ss.removeEditor(emailAddress);
var editors = ss.getEditors();
Logger.log(editors);
}
I've left the Logger bits in as it will help point you at what script is doing at each point.
The email address in the cell must be plain, such as google#google.com

Categories

Resources