Looking to attach a file (pdfName) from Google Drive to sendMail function in Apps Script. Currently not pulling with the code I have below. Everything else works perfectly. Just having trouble with the attach portion.
function send(formObj) {
var to = formObj.email;
var body = formObj.body;
var sheetName = "POTemplate";
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var poNo = sourceSheet.getRange("b2").getValue();
var pdfName = "Sample PO Hi Eric " + poNo;
var subject = poNo + " Good morning, Eric";
var attach = DriveApp.getFilesByName(pdfName);
MailApp.sendEmail(to, subject, body, {attachments:[attach]});
}
It looks like, according to the GAS Documentation on sendMail, the attachments argument requires a BlobSource[] (documentation). However getFilesByName() returns a FileIterator. You need to give MailApp any filetype that implements BlobSource.
So to clarify the main issue is that you are trying to give sendMail a list of files (in the form of FileIterator) instead of just one file.
So something like this should work:
function send(formObj) {
var to = formObj.email;
var body = formObj.body;
var sheetName = "POTemplate";
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var poNo = sourceSheet.getRange("b2").getValue();
var pdfName = "Sample PO Hi Eric " + poNo;
var subject = poNo + " Good morning, Eric";
var listOfFiles = DriveApp.getFilesByName(pdfName); //returns FileIterator of files that match name given.
if(listOfFiles.hasNext()){ //We should check if there is a file in there and die if not.
var file = listOfFiles.next(); //gets first file in list.
MailApp.sendEmail(to, subject, body, {attachments:[file]});
}else{
console.log("Error no file in listOfFiles. Email not sent.");
}
}
edit: I just did some testing and it looks like, for PDFs, the getBlob() is not necessary so I have removed it from my code!
Related
I'm using Apps Script to generate a document including responses from a Google form and store this in a new folder. I also enable the user submitting the form editor access based on the email they provide.
.addEditor(email);
This seems to work for Google domains or company domains using g-suite.
When the email is not Google based however, the script breaks.
'Invalid email: email#example.com'
Looking for a means of skipping past this error and having the script complete.
function autoFillGoogleDocFromForm(e) {
var Timestamp = e.values[0];
var email = e.values[1];
var file = DriveApp.getFileById('FILEID');
var folder = createfolder();
var copy = file.makeCopy(Name + ' - Document', folder);
var newId = copy.getId();
var doc = DocumentApp.openById(newId).addEditor(email);
var body = doc.getBody();
body.replaceText('{{Timestamp}}', Timestamp);
body.replaceText('{{Email}}', Email);
doc.saveAndClose();
}
Looking for a means of skipping past this error and having the script
complete.
If you are looking for a solution to skip the error, then you can always use try...catch:
function autoFillGoogleDocFromForm(e) {
var Timestamp = e.values[0];
var email = e.values[1];
var file = DriveApp.getFileById('FILEID');
var folder = createfolder();
var copy = file.makeCopy(Name + ' - Document', folder);
var newId = copy.getId();
try{
var doc = DocumentApp.openById(newId).addEditor(email);
}
catch(error){
var doc = DocumentApp.openById(newId);
}
var body = doc.getBody();
body.replaceText('{{Timestamp}}', Timestamp);
body.replaceText('{{Email}}', Email);
doc.saveAndClose();
}
This snippet will try to execute var doc = DocumentApp.openById(newId).addEditor(email);.
If the latter fails, then it will just open the document var doc = DocumentApp.openById(newId); and continue with the rest of the code.
A year ago with the help of another user I was able to use google app script to take the form responses and email a pdf (code below)
I now need to save the pdf to a specific folder
I also need to add a link to the saved pdf within the google sheet. Is this possible?
var docTemplate = "doc ID";
var docName = "Vehicle check with images";
function onFormSubmit(e) {
var replaceTextToImage = function(body, searchText, fileId) {
var width = 300; // Please set this.
var blob = DriveApp.getFileById(fileId).getBlob();
var r = body.findText(searchText).getElement();
r.asText().setText("");
var img = r.getParent().asParagraph().insertInlineImage(0, blob);
var w = img.getWidth();
var h = img.getHeight();
img.setWidth(width);
img.setHeight(width * h / w);
}
//Get information from form and set as variables
var email_address = "myemailaddress#here.com";
var vehicle_vrn = e.values[1];
var front_desc = e.values[2];
var front_image = e.values[3].split("=")[1];
var rear_desc = e.values[4];
var rear_image = e.values[5].split("=")[1];
var driver_desc = e.values[6];
var driver_image = e.values[7].split("=")[1];
var passenger_desc = e.values[8];
var passenger_image = e.values[9].split("=")[1];
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DriveApp.getFileById(docTemplate)
.makeCopy(docName+' for '+vehicle_vrn)
.getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document’s body section
var copyBody = copyDoc.getBody();
copyBody.replaceText('keyVrn', vehicle_vrn);
copyBody.replaceText('keyFrontdesc', front_desc);
replaceTextToImage(copyBody, 'keyFrontimage', front_image);
copyBody.replaceText('keyReardesc', rear_desc);
replaceTextToImage(copyBody, 'keyRearimage', rear_image);
copyBody.replaceText('keyDriversdesc', driver_desc);
replaceTextToImage(copyBody, 'keyDriversimage', driver_image);
copyBody.replaceText('keyPassdesc', passenger_desc);
replaceTextToImage(copyBody, 'keyPassimage', passenger_image);
copyDoc.saveAndClose();
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
var subject = "sample attachment file";
var body = "sample text: " + vehicle_vrn + "";
MailApp.sendEmail(email_address, subject, body, {htmlBody: body, attachments: pdf});
DriveApp.getFileById(copyId).setTrashed(true);
}```
I believe your goal as follows.
You want to save the PDF data to the specific folder as a file.
You want to retrieve the URL of the saved PDF file and put it to the specific column of the Spreadsheet.
Modification points:
In order to save the PDF data (in your case, it's a blob.) to the specific folder, you can use DriveApp.getFolderById("folderId").createFile(pdf).
In order to retrieve the URL of the created file, you can use getUrl().
In order to put the URL to the specific column of the Spreadsheet.
You want to put the value to the next column of the last row.
Modified script:
Please modify your script as follows. Before you use this modified script, please set the folder ID, Spreadsheet ID and sheet name.
From:
copyDoc.saveAndClose();
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
To:
copyDoc.saveAndClose();
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
var url = DriveApp.getFolderById("###folderId###").createFile(pdf).getUrl();
var sheet = SpreadsheetApp.openById("###spreadsheetId###").getSheetByName("###sheetName###");
sheet.getRange(sheet.getLastRow(), sheet.getLastColumn() + 1).setValue(url);
When you run the script, pdf is created to the folder ###folderId### as a file, and url is put to the next column of the last row of the sheet ###sheetName### on the Spreadsheet ###spreadsheetId###.
Note:
If you want to give the filename of PDF file, please modify as follows.
From
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
To
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf").setName("###filename###");
References:
getFolderById(id)
getUrl()
getRange(row, column)
I'm trying to modify a template document with pertinent information from a google form submission and then send an email with the filled in document as a word doc to the person who filled the form in. I can manage to update the template and I can even get as far as attaching it as a pdf, but it needs to be editable by the receiver so that isn't really an option. Here is my code:
//Set template variables
var docTemplate = "1_l4T-MVXYXWPvirgE9aE25hKOejTqf9AcfHCKRC67Fk";
var docName = "Editorial Briefing Form";
//Get pertinent info from form
function onFormSubmit(e) {
var timeStamp = e.values[1];
var RequestorName = e.values[2];
var Account = e.values[3];
var JobNumber = e.values[4];
var Files = e.values[6];
var StartDate = e.values[7];
var BudgetHours = e.values[8];
var ActualDeadline = e.values[10];
var Email = e.values[11];
// Get template and save a copy with a new name
var copyId = DriveApp.getFileById(docTemplate)
.makeCopy(docName+' for '+RequestorName)
.getId();
var copyDoc = DocumentApp.openById(copyId);
var copyBody = copyDoc.getActiveSection();
//replace tags with form info
copyBody.replaceText('keyAccount', Account);
copyBody.replaceText('keyJobNumber', JobNumber);
copyBody.replaceText('keyStartDate', StartDate);
copyBody.replaceText('keyRequestorName', RequestorName);
copyBody.replaceText('KeyFiles', Files);
copyBody.replaceText('KeyBudgetHours',BudgetHours);
copyBody.replaceText('KeyActualDeadline', ActualDeadline);
copyDoc.saveAndClose()
MailApp.sendEmail(Email, 'test', 'see attachment', {attachments:[copyDoc]});
}
The only thing I've seen online involves Google OAuth, but I have no idea about that.
Any help would be hugely appreciated.
Thanks
Tom
I just figured out something similar. I couldn't get it to work from onFormSubmit(e), but I set it to run as a trigger from spreadsheet on form submit, and then told it to grab the last row of data, because forms submit puts that data in the last row (unless you have another script sorting things). So, my code looked like this:
function FormSubmitEmail(){
var templateid = "your template id here";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var row = sheet.getLastRow();
var data = sheet.getRange(5,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
var today = Utilities.formatDate(new Date(), "CST", "MM/dd/yy");
var firstname = sheet.getRange("B"+row).getValues();
var lastname = sheet.getRange("C"+row).getValues();
var docname = (lastname+", "+firstname+" "+today);
var folder = DriveApp.getFolderById("I have mine saving a copy also to a folder, your folder ID here");
var docid = DriveApp.getFileById(templateid).makeCopy(docname, folder).getId();
Logger.log(docid);
var doc = DocumentApp.openById(docid);
var body = doc.getActiveSection();
body.replaceText("%DateCreated%",(sheet.getRange("A"+row).getValues()));
body.replaceText("%FirstName%",(sheet.getRange("B"+row).getValues()));
body.replaceText("%LastName%",(sheet.getRange("C"+row).getValues()));
body.replaceText("%EmailAddress%",(sheet.getRange("M"+row).getValues())); //etc.
doc.saveAndClose();
var message = "See attached, or find in folder: https://drive.google.com/drive/folders/[your folder id here]"; // Customize message
var emailTo = "email2#gmail.com, email1#gmail.com" // replace with your email
var subject = "A form has been submitted!."; // customize subject
var pdf = DriveApp.getFileById(docid).getAs('application/pdf').getBytes();
var attach = {fileName:'Autogenerated template.pdf',content:pdf, mimeType:'application/pdf'}; // customize file name: "Autogenerated template"
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
}
Changed to DriveApp still have same challenges and error message
var docTemplate = "1nBZvKTMk5b82tiNvMqG3obmbY-lBIpodrIjvH-_sf7g";
var DocName = "SpringHillDisciplineReport";
// When Form Gets submitted
function onFormSubmit(e) {
//Get information from form and set as variables
var email_address = "kroper#lexrich5.org, lweaver#lexrich5.org, eddavis#lexrich5.org";
var studentname = e.values[2];
var studentgrade = e.values[6];
var date = e.values[5];
var reportername = e.values[3];
var locationofincident = e.values[8];
var reasonforthereferral = e.values[9];
var presentactiontakenbyadministrator = e.values[13];
var infractioncode = e.values [10];
var additionalcomments = e.values[14];
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DriveApp.getFileById(docTemplate)
.makeCopy(DocName+' for '+ studentname)
.getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document’s body section
var copyBody = copyDoc.getActiveSection();
// Replace place holder keys,in our google doc template
copyBody.replaceText('keyStudentName', studentname);
copyBody.replaceText('keyDate', date);
copyBody.replaceText('keyStudentGrade', studentgrade);
copyBody.replaceText('keyLocationofIncident', locationofincident);
copyBody.replaceText('keyReasonfortheReferral',reasonforthereferral);
copyBody.replaceText('keyPresentActionTakenbyAdministrator',presentactiontakenbyadministrator);
copyBody.replaceText('keyAdditionalComments', additionalcomments);
// Save and close the temporary document
copyDoc.saveAndClose();
// Convert temporary document to PDF
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
// Attach PDF and send the email
var subject = "Discipline Referral Report";
var body = "Here is the Discipline Referral Report for " + studentname + "";
MailApp.sendEmail(email_address, subject, body, {htmlBody: body, attachments: pdf});
// Delete temp file
DriveApp.getFileById(copyId).setTrashed(true);
}
The DocsList service, which was deprecated in 2014, has been sunset and no longer functions. Users relying on DocsList should switch to DriveApp.
The two places in your code where you use DocsList should be updated for use with DriveApp
You cannot run this code from the code editor as it requires a submission from a form to work properly. You are receiving the error message that the value was undefined because there was no form submitted. The real problem is with DocsList
I am using a Google spreadsheet and wish to send multiple attachments to our customers, no matter how I format the code it is either rejected or only one attachment is sent, can anyone help with this please
function emailcustomer() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("email to customer")
var subject = sheet.getRange("B2").getValue()
var content = sheet.getRange("A12").getValue()
var doc1 = sheet.getRange("d28").getValue()
var doc2 = sheet.getRange("d29").getValue()
var file1 = DocsList.getFileById(doc1);
var file2 = DocsList.getFileById(doc2);
GmailApp.sendEmail("alex.shaw94#gmail.com",subject,content,{attachments:file1 file2});
}
you can try something like this :
var myFiles = [{fileName:"doc1", content:file1}, {fileName:"doc2", content:file2}]
GmailApp.sendEmail("alex.shaw94#gmail.com", subject,content, {attachments: myFiles});
Also, maybe this can help : https://developers.google.com/apps-script/class_gmailapp#sendEmail
You need to specify the mimetype of the attachment and then add it to your array:
var attachments = [];
attachments.push(file.getAs(MimeType.PDF));
GmailApp.sendEmail(email, subject, body,{
attachments: attachments,
});