Reputation: 1231
The following script for the Gmail API (script.google.com) works without any problems when I run it manually, but when it's triggered by Google using a time-based trigger it fails.
function noSend(e) {
var drafts = GmailApp.getDrafts();
var callback = function(draft) {
function isMyEx(draft) {
var recipient = draft.getMessage().getTo();
var isTheirEmail = /nameofmyex/.test(recipient);
return isTheirEmail; };
if(isMyEx(draft)) {
draft.update('', '', '');
draft.deleteDraft();
} else { } };
drafts.forEach(callback); return;
};
Question: How can I debug this when the error doesn't occur when I run the script manually?
I.e. adding Logger.log()
doesn't help, because the only way I get to see its output is when I run the script manually -- but the script works without any problems when I run it manually.
The error in question, as far as I can tell from Google's website (I don't understand the layout) is:
TypeError: Function getMessage in Object [object Object] was not found
which doesn't make any sense to me, sine the only time the getMessage
method is called is by draft
in the function isMyEx
, which shouldn't have Object
as its prototype, but instead should have GmailDraft
as its prototype, which most definitely does have a getMessage
method.
My only guess so far is that it has something to do with function hoisting, whose rules I don't understand very well. But I've already played around with several ways of ordering the functions and where to define them -- all of them worked when I ran the script manually. Again, this failure is occurring only when the script is triggered automatically by Google, which confuses me to no end.
Related questions: Gmail API message.list from trigger
Function works only when launched manually (not when triggered) in Google Apps Script Form
Upvotes: 0
Views: 360
Reputation: 1231
This was incredibly stupid, but in case it might help someone else in the future (it won't, because this level of stupidity is probably not replicable but):
In the original version of my script, the function isMyEx
was declared in global scope* outside of doSend
more or less like the following:
function isMyEx(draft) {
var recipient = draft.getMessage().getTo();
var isTheirEmail = /nameofmyex/.test(recipient);
return isTheirEmail; };
function noSend(e) {
var drafts = GmailApp.getDrafts();
var callback = function(draft) {
if(isMyEx(draft)) {
draft.update('', '', '');
draft.deleteDraft();
} else { } };
drafts.forEach(callback); return;
};
Since isMyEx
was defined before noSend
, when I clicked the button to set a trigger for the script, the default function to be triggered was the one to be defined first isMyEx
. Which of course will throw the error that I described if it is called outside of doSend
, instead of as a callback within.
*This is probably considered bad practice. If so, please understand that I did it out of ignorance, not out of some malicious intent to spread bad coding practices to the visitors of this web site. In particular, please don't yell at me. I've already served my punishment for this bad coding practice, since it has already come back to bite me in the behind, see below.
Moral of the story: The triggers are not for the entire script. It is not only possible, but actually necessary to set a trigger for each function in the script individually. So if you don't bother to look at which function in the script you are setting the trigger for, don't be surprised like I was when you don't get the desired results.
I only figured this out because, after putting the definition of isMyEx
inside of noSend
(and then inside of callback
), when I clicked the trigger button of the script again, there was a red message below the trigger Selected function not found
. This didn't make sense to me at first, since I thought the trigger was for the entire script, but then I looked at the buttons more carefully and realized that it meant that the trigger was only trying to run the function isMyEx
, not the entire script file (which I guess would make sense for much larger scripts). Anyway, after moving isMyEx
from global scope, it made sense that the function could no longer be found.
Anyway, after I changed the trigger to be for noSend
instead of isMyEx
, everything works fine/perfectly with the automatic trigger, not just when I run the script manually.
Upvotes: 1