Grabbing multiple attachments with a specific file name in Google Appscript - google-apps-script

Needing help with adding 'n' number of attachments.
Code below:
for(var i = 2; i<=lr; i++)
{
var Contact_Person = ss.getRange(i,4).getValue();
var PDFs = ss.getRange(i,6).getValue();
//The above i am grabbing the PDF name from a column in My sheet.
//This name is used for generating my Mail Merge File.
var contents = DriveApp.getFolderById('1ouiQE2cERaRMC_rnSftJCqQCpr2B4x3D').getFiles();
PDFs = DriveApp.getFilesByName(Contractor_Name);
if(PDFs.hasNext())
{
var attach = [];
while(contents.hasNext())
{
var file = contents.next();
if (file.getMimeType() == "application/pdf")
{
attach.push(file);
}
}
GmailApp.sendEmail(currentEmail, Subject, messageBody,
{
attachments: [PDFs.next().getAs(MimeType.PDF), attach[0],attach[1],attach[2], attach[3],],
name: 'Test'
});
}
//This section is for me to grab 1 attachment according to the name specified for that row matching
//the Merged file in the google drive folder.
//I am also trying to attach from a separate folder N number of files to this email.
Pdfs is a variable holding getting values from Column 6 in my Spreadsheet.
This column per row has a set of names.
When the program runs it performs a mail merge and then sends an email to the user of a specific row.
Example:
Email Subject Reference No. Contact Person Contractor Name PDFs
***#gmail.com Test XXXXX Mr. Dan XYZ Company XYZ Company

Answer:
You can just push them all to the same array.
More Information:
From the documentation on GmailApp.sendEmail(recipient, subject, body, options):
Advanced parameters
attachments BlobSource[] an array of files to send with the email
So you can attach them all in one array.
Code Snippet:
if (PDFs.hasNext()) {
var attach = [];
attach.push(PDFs.next().getAs(MimeType.PDF));
while (contents.hasNext()) {
var file = contents.next();
if (file.getMimeType() == "application/pdf") {
attach.push(file);
}
}
GmailApp.sendEmail(currentEmail, Subject, messageBody, {
attachments: attach,
name: "Test"
});
}
References:
Class GmailApp - sendEmail(recipient, subject, body, options) | Apps Script | Google Developers

Related

Can I send multiple uploaded attachments from a Google Form/Google Sheet in an automated email?

I am trying to create a Google Form linked to a Google Sheet utilizing some Google App script that will take some answers from a survey, attach an uploaded file, and send an email to a specific person. I have been able to figure out the part where I collect the data in a Google Sheet and send an email, but the part where I take the uploaded file and have it as an attachment in the email is stumping me.
Currently, my code to send the email looks like this:
GmailApp.sendEmail(Recipient,subject,'',{htmlBody: htmlText},);
But looking at the documentation on sendEmail, it looks like I want to add more to that Options part, right? The so if I am defining a variable for this, I need to use getFileById, but the file ID will be different with each upload. Furthermore, I might need to attach multiple files.
I have created a test Google Form here and I have attached it to a Google Sheet here. You can see the Google App Script here. You can check the email being sent/received successfully by looking at formtesting4#mailinator.com as specified in the code.
Is that possible with what I am trying to do?
You can refer to this sample script:
function emailMe() {
const ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const info = ss.getDataRange().getValues();
info.forEach((entry,a) => {
// Identify whether notification has been sent
if (entry[4] === '') {
// Collect entries
var Recipient = "your#email.com"
var subject = 'Roster Scheduler Update';
Timestamp = entry[0];
Name = entry[1];
Roster = entry[2];
attachment = "TEST";
var attachmentBlobs = [];
//Get the blob of all attachments available
if(entry[3]){
var attachments = entry[3].split(', ');
attachments.forEach(url => {
var fileId = url.replace('https://drive.google.com/open?id=','');
Logger.log(fileId);
var file = DriveApp.getFileById(fileId);
attachmentBlobs.push(file.getBlob());
});
}
let body = '';
// Generate email
var html = HtmlService.createTemplateFromFile("email.html");
var htmlText = html.evaluate().getContent();
// Send email
GmailApp.sendEmail(Recipient, subject, body, {htmlBody: htmlText, attachments: attachmentBlobs});
// Email confidence
const check = 'Sent';
ss.getRange(a + 1,5).setValue(check);
}
});
}
Changes done:
Get the blob file of all the uploaded attachments using File.getBlob(). You can get the file id from the attachment's url link and use DriveApp.getFileById(id)
Include body in the GmailApp.sendEmail() to fix email content issue
Include attachments as an option in the GmailApp.sendEmail(recipient, subject, body, options)
Output:
Sample1: 3 attachments
Sample2: 1 attachment

Get file from Google Drive based of Google Form info submission

I have created a Google Form containing two fields (First Name, Last Name)
I have PDF files in Google Drive/specific folder, PDF files named as "First Name"+"Last Name"
I want to get PDF file from my Google Drive based on form submission and get the URL to be sent by email.
I need the way to get PDF file based on form user submission.
I have written the below code which shall send the PDF as email attachment in place of the URL of PDF. I hope this code can help you. This code is a very basic code which can be further advanced as per your needs. Please let me know if you need any further help.
function pdfextractor() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // Get active spreadsheet.
var lastrow = ss.getLastRow();
var sheetName = ss.getRange("B" + lastrow).getValue() + " " + ss.getRange("C" + lastrow).getValue(); //considering format 'FirstName LastName' stored in column B & C of spreasheet generated by submission of google forms.
var pdfName = sheetName + ".pdf";
ss.getRange("D" + lastrow).setValue(pdfName);
var files = DriveApp.getFilesByName(pdfName);
var body = "This is a test email";
var subject = "PDF File "
var email = "admin#gmail.com"
while (files.hasNext()) {
var file = files.next();
}
GmailApp.sendEmail(email, subject, body, {
attachments: [file]
});
}
You can also change the email of each mail you want to send if stored with the sheet.
One way to do it is to create trigger that fires when the form is submitted. Based on this event, you can get the responses from the form submission, use them to search the file in Drive and send it attached to an email.
Here's an example that you can adapt to build what you need:
function onSubmit(e) {
// Get submitted responses
let itemResponses = e.response.getItemResponses();
// Get form answers (assume the form has three question in this order: First Name, Last Name, Email)
let firstName = itemResponses[0].getResponse();
let lastName = itemResponses[1].getResponse();
let email = itemResponses[2].getResponse();
// Get file (first file found with specified name)
let searchResult = DriveApp.searchFiles(`title contains \'${firstName+lastName}\'`);
let respondentFile = searchResult.next();
if (!respondentFile) throw 'File not found';
// Send email with respondent's file
MailApp.sendEmail(email, 'Your PDF File', 'Your PDF file is attached.', {
name: 'Automatic Emailer Script',
attachments: [respondentFile.getAs(MimeType.PDF)]
});
}

Send File by File ID in Google Apps Script

I am using Google Sheets to store the list of file names in Google Drive, their respective File ID. I am using another sheet in the same workbook to record email addresses and file names that I want to send those email addresses.
I have a Sheet named Data with the following columns
File Name - Files stored on Google Drive
File ID - File ID of the file derived from the share link
I have another Sheet named Request with the following columns
File Name
Email Address
I want to fetch the File mentioned as the File Name mentioned in the Request sheet by looking up the corresponding File ID from the Data sheet for that file name. Once the file is fetched, I want to send that file as an attachment to the email address mentioned in the Request sheet. I want to do this for each row in the Request sheet.
I have created an HTML file named DocTemplate to constitute the body of the email.
I have written the below code in the script editor of Google Sheets. On running it, a mail is triggered but it does not contain the attachment nor does it include the content of the HTML file. The body of the mail just reads [object Object]
What am I doing wrong?
function sendfile(){
var request = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Request");
var data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data");
var Avals = request.getRange("A1:A").getValues();
var requestlastrow = Avals.filter(String).length;
var Avalsu = data.getRange("A1:A").getValues();
var datalastrow = Avalsu.filter(String).length;
for (var i=2;i<= requestlastrow;i++) {
var control = request.getRange(i,6).getValue();
if(control != 1){
var FilenameRequest = request.getRange(i,1).getValue();
for (var j=2;j<= datalastrow;j++) {
var FilenameData = upload.getRange(j,1).getValue();
if(FilenameRequest == FilenameData) {
/// to get the File ID
var FileID = data.getRange(j,2).getValue();
var file = DriveApp.getFileById(FileID);
/// to form the email
var values = request.getRange(i,1,1,2).getValues();
var rec = values[0];
var client =
{
email: rec[1],
name: rec[0]
};
client.subject = 'Request Filename:' + client.name;
var template = HtmlService
.createTemplateFromFile("DocTemplate.html");
template.client = client;
var message = template.evaluate().getContent();
MailApp.sendEmail(client.email,client.subject,{
htmlBody: message,
attachments: [file.getAs(MimeType.PDF)]
});
request.getRange(i,6).setValue("1");
}
}
}
}
}
Since this is not a reproducible example I can only assume that the rest of the code works except for this :
MailApp.sendEmail(client.email,client.subject,{
htmlBody: message,
attachments: [file.getAs(MimeType.PDF)]
});
It should also contain the message argument :
MailApp.sendEmail(client.email,client.subject,message,{
htmlBody: message,
attachments: [file.getAs(MimeType.PDF)]
});

How to export spreadsheet header and last row value to csv file using Google apps script

I'm new here and try to seek some expertise to help to create a google apps script.
I have a spreadsheet and want to export the header and the new added row value to csv file and save it into my local c drive and send an alert email with column B value as a subject.
eg. spreadsheets has 14 columns and I would like to export start from column 2 to csv with values like: "column2 value; column3 value; column4 value; column5 value; column6 value; .....column14 value "
Below is my description workflow :
So everytime when people filled up the value in the google forms and press submit, i will received a new row value in a google sheet. Then i will export the header and the latest row value to csv file into my local c drive and send an alert email with column B value as a subject.
Much appreciated if some expertise can help me on this. Thank you so much. :)
Excel sample.xlsx
See if this helps you:
We'll assume you have the spreadsheet configured as follows:
You've a sheet for submission called Responses
You've a helper sheet needed for the script called Temp which has
the same headers in the first row than the Responses sheet
In the illustrated example below, you want to save as CSV file the headers (Orange) along with the last row submitted (Green)
When you access the script you'll change the following:
The Spreadsheet ID of the whole document
The ID of the tab Temp (numbers found after edit#gid=)
The email address of the recipient
Code:
// Example: https://docs.google.com/spreadsheets/d/1kXaTto1ktqX0XNKQ035897FGX5tV75o7wuYHiNCOqEFfI/edit#gid=1269457815
// In this link the ID of the Spreadsheet is everything after /d/
// which is: 1kXaTto1ktqX0XNKQ035897FGX5tV75o7wuYHiNCOqEFfI
// THE ID of the sheet Temp would be something like: 1269457815
// ---------- Menu ----------
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('CSV File')
.addItem('Step 1: Email CSV', 'EmailRange')
.addItem('Step 2: Save CSV file', 'showurl')
.addToUi();
}
// Choose how do want to export the: csv,pdf,xlsx
EXPORT_TYPE="csv";
function EmailRange() {
// Enter Sheet ID in between ""
var sheetId = "ID GOES HERE";
var ss = SpreadsheetApp.openById(sheetId);
var sheet=ss.getSheetByName("Responses");
// You can set up the headers beforehand
var temp = ss.getSheetByName("Temp");
//Copy range onto Temp sheet
var rangeToCopy = sheet.getRange("A"+(ss.getLastRow())+":N"+(ss.getLastRow()));
// It will erase any previous data
rangeToCopy.copyTo(temp.getRange(2, 1));
// Temporarily hide the sheet
ss.getSheetByName('Responses').hideSheet()
//Authentification
var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
var url="https://docs.google.com/spreadsheets/d/"+ss.getId()+"/export?format="+EXPORT_TYPE;
//Fetch URL of active spreadsheet
var fetch=UrlFetchApp.fetch(url,params);
//Get content as blob
var blob=fetch.getBlob();
var mimetype;
if(EXPORT_TYPE=="pdf"){
mimetype="application/pdf";
}else if(EXPORT_TYPE=="csv"){
mimetype="text/csv";
}else if(EXPORT_TYPE=="xlsx"){
mimetype="application/xlsx";
}else{
return;
}
// OP: send an alert email with column B value as a subject
var subject = sheet.getRange("B"+(ss.getLastRow()));
var timestamp = sheet.getRange("A"+(ss.getLastRow()));
var Title = subject.getValues();
var signature = timestamp.getValues();
//Change Email Recipient underneath
GmailApp.sendEmail('s.nabil#arrowad.sch.sa',
'Job ID: '+Title,
'Hi there,' + '\n\n' + 'A new entry has been submitted, please find the details in the attached CSV file.' + '\n\n' + 'Submitted on: '+signature,
{
attachments: [{
fileName: Title + "."+EXPORT_TYPE,
content: blob.getBytes(),
mimeType: mimetype
}]
});
//Reshow Response sheet
ss.getSheetByName('Responses').showSheet()
}
function showurl() {
// Enter Spreadsheet ID after d/ and the TAB ID of Temp after gid=
var htmlOutput = HtmlService
.createHtmlOutput('Click here My File to download')
.setWidth(250) //optional
.setHeight(50); //optional
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Download CSV File');
}
STEP 1: Sending an email to the defined recipient in the script with the subject being the value of the last row in column B, and the signature the submission date & time, like this:
The CSV file will be attached to the email:
STEP 2: From the CSV File Menu which is created when opening the spreadsheet:
Save file to your Local desktop:

How to get ID value of Google Drive file for input to Google Apps Script

I am writing a Google Apps script to send a file from Google Drive to a list of email addresses saved in a Google Spreadsheet.
Since I will be sending a different file every time I use the script, I have my script set up to take the file ID as text input from the user. The only way I've seen to get the ID directly from Drive is to right-click on the file, select "Get Link", copy it to the clipboard, paste it into my form and erase the bits that aren't the ID. I'm writing to ask if anyone knows a better way. I'm also open to comments suggesting a better program design.
function sendEmails() {
var id = "gibberish"; //email spreadsheet
SpreadsheetApp.openById(id);
var sheet = SpreadsheetApp.getActiveSheet();
Logger.log(sheet.getName());
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 2);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
//Get subject line from user
var ui = SpreadsheetApp.getUi();
var response = ui.prompt('Enter subject: ', ui.ButtonSet.OK_CANCEL);
var subject;
// Process the user's response. TODO- error checking
if (response.getSelectedButton() == ui.Button.OK) {
subject = response.getResponseText();
} else {
Logger.log('The user either canceled or clicked the close button in the dialog\'s title bar.');
subject = "No subject";
}
//get id for attachment file
var ui2 = SpreadsheetApp.getUi();
var response2 = ui2.prompt('Enter Drive id for attachment: ', ui.ButtonSet.OK_CANCEL); //TODO- error checking
var attachmentID;
var file = null;
if (response2.getSelectedButton() == ui.Button.OK) {
attachmentID = response2.getResponseText();
file = DriveApp.getFileById(attachmentID);
Logger.log('The user entered %s', response2.getResponseText());
} else {
Logger.log('The user either canceled or clicked the close button in the dialog\'s title bar.');
}
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = "Time Sheet attached. \n\n -Jessica";
if (file != null) { //TODO- or if file is right file
MailApp.sendEmail(emailAddress, subject, message, {attachments: [file]});
} else {
Logger.log("No file was attached. Email not sent.");
}
}
}
This isn't mine, we've all passed it around this forum quite a bit.
this one works because it gets what you want regardless of if the person pastes in the id or the url:
function getIdFromUrl(url) { return url.match(/[-\w]{25,}/); }
so you don't need to be picky about erasing the rest of the url yourself.
I did something similar in my Copy Folder script.
Basically, I parsed the form input in javascript to select only the folder ID. With this code, you can actually pass in the "Sharing ID" (retrieved by the Right-click and "Get Link" method), the folder URL (retrieved by the browser address bar when you are inside the folder in Google Drive), or just the folder ID. The javascript parses the input and replaces the form entry with just the folder ID, so that your Google Script can retrieve this form data normally.
You can view the source code for the project, but here is the relevant part. In my web app, this is located in the JavaScript.html file.
// Regular expression - find string beginning with "id="
// http://www.w3schools.com/jsref/jsref_regexp_source.asp
var regex = /id=/;
// NOTE: pretty sure you could just make a string variable = "id=" instead of regex, but I didn't want to mess up my script
// Set a temporary variable to the value passed into the "folderId" field
var fId = thisForm.folderId.value;
// Get the index of the string at which the folderId starts
var idStart = fId.search(regex);
var foldersStart = fId.search("folders");
if (idStart > 0) {
// Slice the string starting 3 indices after "id=", which means that it takes away "id=" and leaves the rest
fId = fId.slice(idStart+3);
} else if (foldersStart > 0) {
fId = fId.slice(foldersStart + 8);
}
// Find the ampersand in the remaining string, which is the delimiter between the folderId and the sharing privileges
var amp = fId.indexOf("&");
// Slice the string up to the ampersand
if (amp > 0) {
fId = fId.slice(0,amp);
}
// Set the folderId element within thisForm (retrieved from doGet) to the new, sliced fId variable
thisForm.folderId.value = fId;