I cannot send Gmail by google-apps-script code - google-apps-script

function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
if( sheet.getSheetName() != 'Sheet1' ) {
return 0;
}
var selectedCell = ss.getActiveCell();
if( selectedCell.getColumn() == 1) {
var dateTimeCell = selectedCell.offset(0, 2);
dateTimeCell.setValue('auto');
GmailApp.sendEmail('12345#gmail.com', selectedCell.getRow(), 'hello')
}
if I modify column A and run script, Gmail sent.
but if I modify column A only (don't run code), then Gmail not sent.
'auto' is inserted in both case. I suspect only GmailApp.sendEmail is not working.
why?

Do you have a trigger set up for it? The function you have only shows a simple trigger onEdit() which cannot send emails. See Restrictions here.

Vytautas is right. It says that:
They cannot access services that require authorization. For example, a simple trigger cannot send an email because the Gmail service requires authorization, but a simple trigger can translate a phrase with the Language service, which is anonymous.

Related

How to use onEdit function to trigger an email

I'm very new to script writing, but I'm trying to set up a script to send an email once a certain cell (A4) is populated within a certain sheet.
The trouble I'm having is getting the script to trigger - I understand that running it when not in the spreadsheet generates an error, I get no error message, but no email appears to be sent using this code:
function onEdit(e) {
var name = SpreadsheetApp.getActiveSpreadsheet().getName();
var cell = e.range.getA1Notation();
var spreadSheet = e.source;
var sheet = spreadSheet.getSheetByName('Scanned');
var range = getRange('A4');
var column = e.range.getColumn();
var row = e.range.getRow();
if(sheet == 'Scanned' && column == 1 && row == 4)
MailApp.sendEmail('joey#gmail.com', 'Tipping Notification: '+(name), 'Notification email body '+(name));
}
An onEdit trigger always requires a 'manual' edit of the spreadsheet. If the spreadsheet(cell) is populated by a formula, it will not fire the onEdit trigger.
Also, in order to send emails, you'll have to use an installable onEdit trigger. Simple onEdit triggers cannot access services that require authorization.
There are some restrictions for using simple trigger, One is simple trigger cannot access services that require authorization. For example, a simple trigger cannot send an email because the Gmail service requires authorization.
In order to use services that requires authorization, you need to create an Installable trigger. See this link on how to create Installable Trigger.
Also, getSheetByName() returns a Sheet Object and not the name of the edited Sheet. This causes your code to skip sending email.
Try this:
Code:
function onEditA4(e) {
var editedSheet = e.range.getSheet().getName();
var editedCell = e.range.getA1Notation();
var name = e.source.getName();
if(editedSheet == 'Scanned' && editedCell == "A4")
MailApp.sendEmail('insert email here', 'Tipping Notification: '+(name), 'Notification email body '+(name));
}
Example Trigger:

Google App Script to trigger on cell value change

I am a newbie and have been using a simple App Script to send out emails with triggers onEdit and onChange. However, my Worksheet has over ten sheets and any edits/changes (done by me or by computations) in any of the sheets sends out an email, causing unintended spam! To avoid this, if I could use some code that sends the email based only on ANY CHANGE to a specific cell's value, in a specific sheet, my problem would be solved. My outgoing email message is short and the whole message is in just ONE cell (C2). If I can add a line of code which monitors for ANY change in that cell C2, and sends out an email if there is a change, that's it! I'd be done. My Script is as follows:
function sendEmail(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet1=ss.getSheetByName('Email');
var emailAddress = sheet1.getRange(2,1).getValue();
var subject = sheet1.getRange(2,2).getValue();
var message = sheet1.getRange(2,3).getValue();
MailApp.sendEmail(emailAddress, subject, message);
}
Answer:
You can do this with an onEdit() and a conditional.
Code Example:
function onEdit(e) {
const specificSheet = "Email" // for example
const specificCell = "C2" // for example
let sheetCheck = (e.range.getSheet().getName() == specificSheet)
let cellCheck = (e.range.getA1Notation() == specificCell)
if (!(sheetCheck && cellCheck)) {
return
}
else {
sendEmail()
}
}
Rundown of this function:
Defines the sheet and A1 notation of the specific cell to check
Gets the Sheet and the A1 notation of the cell which was just edited
Returns if either the Sheet or the Cell are not the defined specific cell (using De Morgan's law)
Runs sendEmail() if the cell and Sheet are correct
References:
Event Objects | Apps Script | Google Developers
Simple Triggers | Apps Script | Google Developers
De Morgan's laws - Wikipedia
Working from the answer, this is how it ended up for me since I had several ranges to check:
function onEdit(e){
if(wasEdited(e, range1)){ // e.g. range1 = "Sheet1!A5"
// handle range1 change
}
if(wasEdited(e, range2)){ // e.g. range2 = "Sheet1!A7"
// handle range2 change
}
}
function wasEdited(e, range){
let tab = getTabFromA1Range(range)
let cell = getRangeFromA1Range(range)
return e.range.getSheet().getName() == tab && e.range.getA1Notation() == cell
}
function getTabFromA1Range(a1Range){
return a1Range.substring(0, a1Range.indexOf("!"))
}
function getRangeFromA1Range(a1Range){
return a1Range.substring(a1Range.indexOf("!")+1)
}
On further research, the following solution seems to work the best:
function sendEmail(){
Utilities.sleep(30000);
var ss=SpreadsheetApp.getActiveSpreadsheet();
var data=ss.getActiveSheet().getActiveCell().getA1Notation();
var sheetname = ss.getActiveSheet().getName();
var sheet1=ss.getSheetByName('Email');
var emailAddress = sheet1.getRange(2,1).getValue();
var subject = sheet1.getRange(2,2).getValue();
var message = sheet1.getRange(2,3).getValue();
if(data.indexOf('A:C')!=-1.23456789) {
MailApp.sendEmail(emailAddress, subject, message);
}
};
The key seems to be the "if statement" on line 10. Please note the time delay of half a minute I added to the script. This is because without it, on the trigger activating, the previous email was going out instead of the current one. Obviously my app has a slight delay in syncing and the trigger fired before all the current data got populated in the relevant cell!

How to send email using data of a row whose particular column is just edited in Google Apps Script?

I want to automate my work of sending email.
For this i created google apps script, but it is not working.
my goal is : if i update column I of any row to "Yes" than email must be send to email id of that row only by adding their username and password. and if possible email status will also change to "email sent on date"
This is my table
Code:-
function onEdit(e) {
var ss= SpreadsheetApp.getActiveSpreadsheet();
var range = e.Range;
if(range.getColumn()== 9 && e.getValue()=="Yes")
{
var celladdress = 'E'+ e.getRowIndex();
var emailid= ss.getRange(celladdress).getValue();
var sub = 'π‘ͺπ’“π’†π’…π’†π’π’•π’Šπ’‚π’π’” - π’“π’†π’ˆ';
var uname = ss.getRange('G'+ e.getRowIndex()).getValue();
var pass = ss.getRange('H'+ e.getRowIndex()).getValue();
var b = "Your details are as follows: \n Username :" +uname+ "\n Password : "+pass+ "\nThis is for your information please. \nThanks and Regards";
MailApp.sendEmail(emailid, sub, b);
}
}
Solution
You had a few mistakes in your script like using e.getValue() instad of range.getValue(), I have corrected these mistakes.
Moreover and most importantly, to be able to send emails using triggers you need to use installable triggers as simple ones do have restrictions as the MailApp service requires authorization. Here you can find more information about this.
To create an installable trigger ( if you have not already do so ), go to your script editor and then to Edit->Current Project Triggers and the trigger pannel Add Trigger. Select your function (onEdit) and set the event type to on edit.
This is your piece of code with the typos corrected:
function onEdit(e) {
var ss= SpreadsheetApp.getActiveSpreadsheet();
var range = e.range;
if(range.getColumn()== 9 && range.getValue()=="Yes")
{
var celladdress = 'E'+ range.getRow();
var emailid= ss.getRange(celladdress).getValue();
var sub = 'Credentials-reg';
var uname = ss.getRange('G'+ range.getRow()).getValue();
var pass = ss.getRange('H'+ range.getRow()).getValue();
var b = "Your details are as follows: \n Username :" +uname+ "\n Password : "+pass+ "\nThis is for your information please. \nThanks and Regards";
GmailApp.sendEmail(emailid, sub, b);
}
}
I hope this has helped you. Let me know if you need anything else or if you did not understood something. :)

var userMail = e.user.getEmail(); on edit google sheets not pulling email

I was using the following script on a google sheet that worked for months, but now around 1:30 PM Thursday 3/5/2020 it stopped working and pulling the user emails. I tried changing it to the second attempt, saved, and edited the cell, but nothing happened.
(Note: I cannot share the file due to regulations.)
What was working before:
function onEdit(e) {
var rg = e.range;
if (rg.getSheet().getName() == "Call Log" && rg.columnStart == 13) {
var nextCell = rg.offset(0, -3);
if (nextCell.getValue() == '') {
var userMail = e.user.getEmail();
nextCell.setValue(userMail);
}
}
}
My second attempt:
function onEdit(e) {
var rg = e.range;
if (rg.getSheet().getName() == "Call Log" && rg.columnStart == 24) {
var nextCell = rg.offset(0, 3);
if (nextCell.getValue() == '') {
var email = Session.getActiveUser().getEmail();
Logger.log(email);
nextCell.setValue(userMail);
}
}
}
onEdit Event Object clearly states the following:
If security policies do not allow access to the user's identity, User.getEmail() returns a blank string. The circumstances in which the email address is available vary: for example, the user's email address is not available in any context that allows a script to run without that user's authorization, like a simple onOpen(e) or onEdit(e) trigger, a custom function in Google Sheets, or a web app deployed to "execute as me" (that is, authorized by the developer instead of the user). However, these restrictions generally do not apply if the developer runs the script themselves or belongs to the same G Suite domain as the user.
Lara,
Honestly, I've never worked with google sheet functions. But it looks like their API is pretty straightforward. Based on the error
TypeError: Cannot read property 'range' of undefined (line 2, file
"Code")
I can assume that your function doesn't consume any values. You should retrieve the range from another object. I found this article very good to start with. It looks like you first have to get your sheet using var sheet = SpreadsheetApp.getActiveSheet(); and then carefully read API documentation.
Most likely you will end up with something like:
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange();
if (sheet.getName() === "Call Log" && range.getColumn() === 24) {
var nextCell = range.offset(0, 3);
if (nextCell.getValue() === '') {
var email = Session.getActiveUser().getEmail();
Logger.log(email);
nextCell.setValue(email);
}
}
}
But I can't test this solution. Please, give it a try or update this in the way you wish.

Google sheets - User/Email stamp triggered ON EDIT works only with OWNER account - how to enable user/email stamps for all editors?

I need a solution to enable all editors to leave their name stamps after they make changes in a sheet. I was able to come up with script code which does work ONLY FOR OWNER.
I tried to authorize the script by running the script manually from editors accounts - the app has the authorization but even though it doesn't work for Editors.
Norbert Wagner: "However authorizing from the script editor did not work for me. But as soon as I added a menu in the document and executed the function from there, I got an authorization request in the document. From then on also the onEdit function works, for all users. I did this as the documents owner though. " -
maybe this is the solution? But how can I run the onEdit from the
document? Simple edit doesn't work, but how about this menu? Is there
a way to execute ALL SCRIPTS AND FORCE AUTHORIZATION from document level?
function onEdit(e) {
// Your sheet params
var sheetName = "Arkusz1";
var dateModifiedColumnIndex = 3;
var dateModifiedColumnLetter = 'C';
var range = e.range; // range just edited
var sheet = range.getSheet();
if (sheet.getName() !== sheetName) {
return;
}
// If the column isn't our modified date column
if (range.getColumn() != dateModifiedColumnIndex) {
var row = range.getRow();
var user = Session.getActiveUser().getEmail();
user = String(user);
user = user.replace('#gmail.com', '');
var dateModifiedRange = sheet.getRange(dateModifiedColumnLetter + row.toString());
dateModifiedRange.setValue(user);
};
};
This function works only when using owner account.
Even after Editor has authorised script manually from script editor - the onEdit user stamp function doesn't trigger.
Below is another function which I used for testing. When I run it manually from editors account IT WORKS - it saves editor's name in A1.
function USERNAME(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0]; // this will assign the first sheet
var cell = sheet.getRange('A1');
var d = new Date();
d.setHours(d.getHours() +1);
var user = Session.getActiveUser().getEmail();
user = String(user);
user = user.replace('#gmail.com', '');
cell.setValue(user);
}
In fact you have to use installable trigger.
Rename your function onEdit(e) with another name for example customFunction(e)
Then you setup an installable trigger using this function :
function createTrigger(){
ScriptApp.newTrigger('customFunction')
.forSpreadsheet(SpreadsheetApp.openById('YOU_SHEET_ID'))
.onEdit()
.create();
}
Or you can setup the trigger manually by going to 'Edit >> Current project's triggers >> Click on + button (bottom right)'
By this way trigger will run each time there is an Edit no matter the user.
StΓ©phane