Function called from webapp does not send email - google-apps-script

I'm having a problem with Google Scripts.
I'm trying to do an open questionnaire that allows anonymous file uploads to a specific folder on my Google Drive, and afterwards sends me a notification email to my mail. It uploads the file fine, but the email is not sent.
In debugging mode, it sent the email.
Here is my code:
<form id="myForm">
<input type="text" name="myName" placeholder="Su Nombre..">
<input type="file" name="myFile">
<input type="submit" value="Subir Archivo"
onclick="this.value='subiendo..';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;">
</form>
And the Google Script file:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function uploadFiles(form) {
try {
var folder = DriveApp.getFolderById(/*folder id*/);
var blob = form.myFile;
var file = folder.createFile(blob);
file.setDescription("Subido Por " + form.myName);
// email
var asunto = "Testing attaching file";
var correo = /*my email address*/;
var options = {attachment : [form.MyFile]};
MailApp.sendEmail(correo, asunto, emailBody, options);
return "Archivo Subido Con Exito " + file.getUrl();
}
catch (error) {
return error.toString();
}
}

Related

Upload Image in google sheet cell using google apps script?

I am looking to upload an image into google sheet cell using a google apps script, I found a script that uploads image into Google Drive folder and then gets the image url into sheet that can be manipulated to get the image:
Here is the first function:
Code.gs
function addImage() {
var filename = 'Row';
var htmlTemp = HtmlService.createTemplateFromFile('Index');
htmlTemp.fName = filename;
htmlTemp.position = 2;
var html = htmlTemp.evaluate().setHeight(96).setWidth(415);
var ui = SpreadsheetApp.getUi();
ui.showModalDialog(html, 'Upload');
}
Following is the return function:
Code.gs
function upload(obj) {
//Retrieve the input data of the Form object.
var newFileName = obj.fname;
var rowNum = obj.position;
var blob = obj.file;
var upFile = DriveApp.getFolderById('[folderid]').createFile(blob).setName(newFileName);
var fileUrl = upFile.getUrl();
var urlCell = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getRange(rowNum,5);
urlCell.setValue('=HYPERLINK("' + fileUrl + '","View image")');
}
This is the html part:
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_center">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
</head>
<body>
<form id="myForm">
Please upload image below.<br /><br />
<input type="hidden" name="fname" id="fname" value="<?= fName ?>"/>
<input type="hidden" name="position" id="position" value="<?= position ?>"/>
<input type="file" name="file" id="file" accept="image/jpeg,.pdf" />
<input type="button" value="Submit" class="action" onclick="formData(this.parentNode)" />
<input type="button" value="Close" onclick="google.script.host.close()" />
</form>
<script>
//Disable the default submit action using “func1”
window.onload=func1;
function func1() {
document.getElementById('myForm').addEventListener('submit', function(event) {
event.preventDefault();
});
}
function formData(obj){
google.script.run.withSuccessHandler(closeIt).upload(obj);
}
function closeIt(e){
console.log(e);
google.script.host.close();
};
</script>
</body>
</html>
When I ran the addImage() function, a dialog box popped up in which I uploaded a jpeg image, but when I clicked on submit button, it did not do anything and stuck there, any help would be much appreciated. Thanks
Issue and workaround:
From [Fixed] Google Apps Script Web App HTML form file-input fields not in blob compatible format, in the current stage, when Web Apps is used, the file object in the form object can be parsed by google.script.run. But, unfortunately, it seems that when a dialog and sidebar are used, this cannot be parsed. So, in the current stage, as the current workaround, it is required to parse the file object on the Javascript side. When this is reflected in your script, how about the following modification?
Google Apps Script side: Code.gs
Please `upload as follows.
function upload(obj, rowNum) {
var newFileName = obj[2];
var blob = Utilities.newBlob(...obj);
var upFile = DriveApp.getFolderById('[folderid]').createFile(blob).setName(newFileName);
var fileUrl = upFile.getUrl();
var urlCell = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getRange(rowNum, 5);
urlCell.setValue('=HYPERLINK("' + fileUrl + '","View image")');
return "Done.";
}
HTML & Javascript side: Index.html
Please formData as follows.
function formData(obj) {
const file = obj.file.files[0];
const fr = new FileReader();
fr.readAsArrayBuffer(file);
fr.onload = f =>
google.script.run.withSuccessHandler(closeIt).upload([[...new Int8Array(f.target.result)], file.type, obj.fname.value], obj.position.value);
}

Only the else condition works in my google apps script Twilio Fax sending web app

I'm having an issue with my If statement.
Basically I set up a fax app with Twilio and Google apps script.
I give the user a choice to upload a document or send out one that stored on my Google drive.
If I upload a file it works. But if I check the checkbox to send a pre-set document, which I'm trying to accomplish by using the If statement it doesn't send.
I troubleshooted, and found that the If statements is getting a TRUE and FALSE value.
I think the problem is that when there is no file passed into the function it doesn't work. The thing is I'm avoiding the file by the If statement so why is it not working.
Below is my HTML file and server side apps script.
Any suggestions?
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function uploadFiles(blob, name, number, test) {
//get destination number
var num = number;
var prefix = "+1";
var removeDashes = num.replace(/-/g,"");
var fullNumber = prefix + removeDashes;
var output;
if (test){
output = "APPLICATION SENT!";
}else{
output = "FAX SENT!";
}
var url;
if (test) {
var appl = DriveApp.getFileById('xxxxxxxxx');
var appurl = appl.getDownloadUrl();
url = appurl;
} else {
var folder = DriveApp.getFolderById('xxxxxxxxxxx');
var blob = blob.split(",");
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'application/pdf');
var fileName = blob.setName(name).getName();
var file = folder.createFile(blob);
//allow access to Twilio
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
//get file url
var id = file.getId();
var getfile = DriveApp.getFileById(id);
var getnewurl = getfile.getDownloadUrl();
var url = getnewurl;
}
//send fax
var faxUrl = "https://fax.twilio.com/v1/Faxes";
var payload = {
"From" : "+1888888888",
"To": fullNumber,
"MediaUrl" : url,
"Method" : "POST",
};
var options = {
"method" : "post",
"payload" : payload
};
options.headers = {
"Authorization" : "Basic " + Utilities.base64Encode("ACxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxx")
};
UrlFetchApp.fetch(faxUrl, options);
return "succes" + output;
}
Here is the HTML file: (I removed the <style> in order to shorten)
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
function upload() {
var file = document.getElementsByName('myFile')[0].files[0];
var number = document.getElementsByName('Pnumber')[0].value;
var test = document.getElementsByName("entered")[0].checked;
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
google.script.run.withSuccessHandler(fileUploaded).uploadFiles(content, file.name, number, test);
return false;
}
reader.readAsDataURL(file);
}
function fileUploaded(status) {
document.getElementById("myForm").reset();
document.getElementById('output').innerHTML = status;
}
</script>
</head>
<body>
<div align="center">
<h1 align="center" style="color:darkblue">FAX APP</h1>
<h2 align="center">SEND OUTGOING FAX</h2>
<hr>
<form id="myForm" align="center">
<label for="pdf">Choose a PDF file to upload -- <b>OR</b>-- Check "SEND APPLICATION" </label>
<br>
<input id="pdf" type="file" name="myFile" >
<br><br>
<input type="checkbox" style="width:25px ; height:25px" name="entered">
<label for="entered" style="font-size:30px" > SEND APPLICATION</label>
<br><br>
<label for="phonenumber">Enter Destination Number</label>
<br>
<input id="phonenumber" type="text" name="Pnumber" placeholder="Phone Number" >
<br>
<input type="submit" value="SEND FAX" onclick="upload()" >
</form>
<p><b>FAX DELIVERY STATUS:</b></p>
<div id="output"align="center"><b></b></div>
<br>
<a href="https://drive.google.com/drive/folders/xxxxxxxxxxxxxxxxxxx?usp=sharing"
target="_blank">SENT FAX DOCUMENTS</a>
</div>
</body>
</html>
BELOW IS THE NOW WORKING CODE OF GOOGLE SCRIPT SIDE AND HTML
THANKS TO #Tanaike's HELP
CURRENT GOOGLE SCRIPT SIDE CODE:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function uploadFiles(blob, name, number, test) {
//get destination number
var num = number;
var prefix = "+1";
var removeDashes = num.replace(/-/g,"");
var fullNumber = prefix + removeDashes;
var output;
if (test){
output = "APPLICATION SENT!";
}else{
output = "FAX SENT!";
}
var url;
if (test) {
var appl = DriveApp.getFileById('xxxxxxxxxxxxxxxxxxxxxxx');
var appurl = appl.getDownloadUrl();
url = appurl;
} else {
var folder = DriveApp.getFolderById('xxxxxxxxxxxxxxxxxxxxxxxxxxx');
var blob = blob.split(",");
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'application/pdf', name);
var file = folder.createFile(blob);
//allow access to Twilio
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
//get file url
var id = file.getId();
var getfile = DriveApp.getFileById(id);
var getnewurl = getfile.getDownloadUrl();
url = getnewurl;
}
//send fax
var faxUrl = "https://fax.twilio.com/v1/Faxes";
var payload = {
"From" : "+188888888888",
"To": fullNumber,
"MediaUrl" : url,
"Method" : "POST",
};
var options = {
"method" : "post",
"payload" : payload
};
options.headers = {
"Authorization" : "Basic " + Utilities.base64Encode("ACxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxx")
};
UrlFetchApp.fetch(faxUrl, options);
return "Success - " + output;
}
CURRENT HTML SIDE CODE:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
function upload() {
var file = document.getElementsByName('myFile')[0].files[0];
var number = document.getElementsByName('Pnumber')[0].value;
var test = document.getElementsByName("entered")[0].checked;
if(!test){
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
google.script.run.withSuccessHandler(fileUploaded).uploadFiles(content, file.name, number, null);
return false;
}
reader.readAsDataURL(file);
}else{
google.script.run.withSuccessHandler(fileUploaded).uploadFiles(null, null, number, test);
return false;
}
}
function fileUploaded(status) {
document.getElementById("myForm").reset();
document.getElementById('output').innerHTML = status;
}
</script>
</head>
<body>
<div align="center">
<h1 align="center" style="color:darkblue">FAX APP</h1>
<h2 align="center">SEND OUTGOING FAX</h2>
<hr>
<form id="myForm" align="center">
<label for="pdf">Choose a PDF file to upload -- <b>OR</b>-- Check "SEND APPLICATION" </label>
<br>
<input id="pdf" type="file" name="myFile" >
<br><br>
<input type="checkbox" style="width:25px ; height:25px" name="entered">
<label for="entered" style="font-size:30px" > SEND APPLICATION</label>
<br><br>
<label for="phonenumber">Enter Destination Number</label>
<br>
<input id="phonenumber" type="text" name="Pnumber" placeholder="Phone Number" >
<br>
<input type="submit" value="SEND FAX" onclick="upload()" >
</form>
<p><b>FAX DELIVERY STATUS:</b></p>
<div id="output"align="center"><b></b></div>
<br>
<a href="https://drive.google.com/drive/folders/xxxxxxxxxxxxxxxx?usp=sharing"
target="_blank">SENT FAX DOCUMENTS</a>
</div>
</body>
</html>
I believe your goal as follows.
You want to remove the error when SEND APPLICATION is checked without selecting a file.
Modification points:
When the file is not selected, an error occurs at FileReader because file is undefined. I think that this might be the reason of your issue.
In this case, I would like to propose the function upload() at Javascript side as follows.
if (file && !test) {}else{} is used. By this,
When the file is selected AND SEND APPLICATION is not checked, the selected file is used.
When the file is not selected OR SEND APPLICATION is checked, the file of var appl = DriveApp.getFileById('xxxxxxxxx') is used.
About this, please modify the if statement for your actual situation.
Modified script:
When your script is modified, please modify upload() at Javascript side as follows.
function upload() {
var file = document.getElementsByName('myFile')[0].files[0];
var number = document.getElementsByName('Pnumber')[0].value;
var test = document.getElementsByName("entered")[0].checked;
// I modified below script.
if (file && !test) {
var reader = new FileReader();
reader.onload = function(e) {
var content = reader.result;
google.script.run.withSuccessHandler(fileUploaded).uploadFiles(content, file.name, number, test);
return false;
}
reader.readAsDataURL(file);
} else {
google.script.run.withSuccessHandler(fileUploaded).uploadFiles(null, null, number, test);
}
}
In this modification, Google Apps Script side is not modified.
Added:
I think that your current issue is due to that you changed Google Apps Script from the script in the initial question. In the current script, name is removed at Google Apps Script and Javascript. By this, an error occurs at createFile. Please use name as follows.
From:
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'application/pdf');
To:
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'application/pdf', "sample");
In this case, the filename is a temploral. So you can use various name like "sample", "temp" and so on.
And when you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps. Please be careful this.
And in your current script, if (!test) { is used. In this case, when the button is cliced without selecting file and cheking the checkbox, an error occrurs. Please be careful this.

How would I go about displaying HTML of a user-inputted URL using Google Apps Script?

I can't seem to get the HTML portion of the webapp and the code.gs portion to communicate with each other. Here is my code so far:
Code.gs:
function doGet() {
//var url = Browser.inputBox('Enter URL', Browser.Buttons.OK);
return HtmlService.createHtmlOutputFromFile('search');
}
function sbox(url) {
//var url = form.url;
var response = UrlFetchApp.fetch(url);
return HtmlService.createHtmlOutput(response);
}
search.html:
<form>
URL:
<input type="text" id="url" name="url" value=""><br>
<input type="button" onClick="formSubmit()" value="Search1" />
<script>
function formSubmit() {
var url = document.getElementById("url").value;
google.script.run.sbox(url);
}
</script>
</form>
function formSubmit() {
var url = document.getElementById("url").value;
google.script.run.withSuccessHandler(closeIt).sbox(url);
}
function closeIt(){
google.script.host.close()
};
However, instead of sending url to code.gs, you can just use window.open(url, "_self");
and open the window from the javascript as the apps script won't be able to do it.

how to put inline image in automated mail from Google sheet

I want to send mail with an inline image instead of as an attachment through google sheet. Please help
the script is as below:
function emailSummary() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sh = ss.getSheetByName("Hitesh")
var file = DriveApp.getFileById('1T8QA_WsXQkZZGwmBSN13iPV7rM8xGG_GtYy6T1eug-c')
var gmail = 'hitesh.gtg#Gmail.com';
var html = '<png>'
MailApp.sendEmail("hitesh.gtg#gmail.com", "sunject", "Dear Sir,\n\n Forwarding herewith Monthly Summaryw \n\n Regards \n Hitesh ", {
//email address, subject, message
name: 'Hitesh', //file name
attachments: [file.getAs(MimeType.PDF)] //file to attach
});
}
You can pass HTML to the .sendMail() function. This link to the official documentation includes an example for inline images!
// This code fetches the Google and YouTube logos, inlines them in an email
// and sends the email
function inlineImage() {
var googleLogoUrl = "http://www.google.com/intl/en_com/images/srpr/logo3w.png";
var googleLogoBlob = UrlFetchApp
.fetch(googleLogoUrl)
.getBlob()
.setName("googleLogoBlob");
//You can also get these images from your drive to attach them.
var imgBlob = DriveApp.getFileById("<DRIVE_FILE_ID_OF_PICTURE>")
.getBlob()
.setName("imgBlob");
MailApp.sendEmail({
to: "recipient#example.com",
subject: "Logos",
htmlBody: "inline Google Logo<img src='cid:googleLogo'> images! <br>" +
"img from drive: <img src='cid:driveImg'>"
inlineImages:
{
googleLogo: googleLogoBlob,
driveImg: imgBlob
}
});
}
Emailing Images from your Google Drive
You can use the htmlBody parameter in GmailApp.sendMail(). However, if you want to avoid having to store the image in a URL that is publicly accessible. You can do something like this.
This is a portion of my JavaScript:
function sendImgMsg() {
var fileId=$('#mediaSel').val();//This is the fileId where the image is store. In my image converter script I keep all of this images in the same folder.
google.script.run
.withSuccessHandler(function(fObj){
var msg=$('#emsg').val();//This is the contents of a textarea
var hl='<p>' + msg + '</p><br /><strong>File Name:</strong> '+ fObj.name + '<img src="'+ fObj.uri +'" title="' + fObj.filetype + '" />';
$('#email').css('display','none');
google.script.run.sendImageMessage(hl);//This is the code that sends the email
})
.getSelectedFile(fileId);
}
This is a portion of my html:
<div id="email">
<textarea id="emsg" cols="40" rows="4"></textarea>
<br /><input type="button" value="Send" onClick="sendImgMsg()" />
</div>
This is a portion of my code.gs:
function getSelectedFile(fileId){
var file=DriveApp.getFileById(fileId);
var dataURI=file.getBlob().getDataAsString();
var s=dataURI.split(',')[0];
var mediaType=s.slice(s.indexOf(':')+1,s.indexOf('/'));
var fileType=s.slice(s.indexOf('/')+1,s.indexOf(';'));
var fObj={name:file.getName(),uri:dataURI ,type:mediaType,filetype:fileType};
return fObj;
}
function sendImageMessage(hl) {
GmailApp.sendEmail('recipient', 'ImageInAnEmail', null ,{htmlBody: hl});
}
This is the code that converts external images to imageURI's:
function convImageUrl(url){
var blob=UrlFetchApp.fetch(url).getBlob();
var b64Url='data:' + blob.getContentType() + ';base64,' + Utilities.base64Encode(blob.getBytes());
return b64Url;
}
The above is a part of a script that I use for converting images to imageURI's so that I can store and access them on my Google Drive.

Create spreadsheet alongside file upload with Google App Script

I'm having a surprisingly hard time finding basic examples of setting something like this up. I'm pouring through the documentation, but the basic functions simply will not work. Could really use some advice.
I have file upload working thanks to another tutorial, but I would like to create a spreadsheet as well (or simply OPEN the spreadsheet if it already exists) to store additional info such as the name of the uploader, a URL of the file, etc. No dice!
SERVER.GS:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function uploadFiles(form) {
try {
var ss = SpreadsheetApp.create("TEST123");
var sheet = ss.getSheets()[0];
// Appends a new row with 2 columns to the bottom of the
// spreadsheet containing the values in the array
sheet.appendRow(["Jackson Jones", "jJones#email.com"]);
var dropbox = "Student Files";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var blob = form.myFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
return "File uploaded successfully " + file.getUrl();
} catch (error) {
return error.toString();
}
}
FORM.HTML:
<form id="myForm">
<input type="text" name="myName" placeholder="Your full name...">
<input type="file" name="myFile">
<input type="submit" value="Upload File"
onclick="this.value='Uploading..';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;">
</form>
<div id="output"></div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
Of course eventually I would use form.myName and such to populate the spreadsheet, but I can't even get their example code to run.
It looks like you have some problems with your form syntax. Here is a version that will do what you are after -- it a modified version of the code tutorial present the Apps Script HTMLService documentation.
Note I am using IDs to identify the drop folder and log spreadsheet for convenience (note that more than one file/folder can have the same name in Drive, so use of IDs is generally preferable to finding files by name).
Code.gs:
var dropBoxId = "012345679abcdefg"; // Drive ID of 'dropbox' folder
var logSheetId = "abcdefghijklmnopqrstu123"; // Drive ID of log spreadsheet
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('InputForm.html');
}
function uploadFiles(formObject) {
try {
// Create a file in Drive from the one provided in the form
var folder = DriveApp.getFolderById(dropBoxId);
var blob = formObject.myFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + formObject.myName);
// Open the log and record the new file name, URL and name from form
var ss = SpreadsheetApp.openById(logSheetId);
var sheet = ss.getSheets()[0];
sheet.appendRow([file.getName(), file.getUrl(), formObject.myName]);
// Return the new file Drive URL so it can be put in the web app output
return file.getUrl();
} catch (error) {
return error.toString();
}
}
InputForm.html:
<form id="myForm">
<input type="text" name="myName" placeholder="Your full name..."/>
<input name="myFile" type="file" />
<input type="button" value="Submit"
onclick="google.script.run
.withSuccessHandler(updateUrl)
.withFailureHandler(onFailure)
.uploadFiles(this.parentNode)" />
</form>
<div id="output"></div>
<script>
function updateUrl(url) {
var div = document.getElementById('output');
div.innerHTML = 'Got it!';
}
function onFailure(error) {
alert(error.message);
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
5 Suggestion to Ryan Roth's Script:
1. "Timestamp" column is not created when somebody fills out form.
2. "required" field attribute not working.
3. The uploaded file should be submitted to google drive with folder created with uploader's name.
4. After submitting the form, the fields doesn't not refresh leaving the entered data as it is.
5. The standalone app is not embeddable in website.
If anyone have the updated script please do share below.