Google Apps Script is one of the best hidden features of Gmail.
Did you ever want just a bit more flexibility from a filter? Maybe the ability to remove a label, or match on a header, or just decide the order they are applied in.
Apps Script can do all that and then some. They are simple JavaScript programs with access to the Gmail API that run as cron jobs on Google servers. They are free and don't require a GCP account. They can even send emails.
One could build some pretty complete bots by giving them their own Gmail account, but here I just wanted to mark Gerrit CL threads as read when I was the last to act on them.
I know I could just write a bot in Go using the APIs, but then I'd have to take care of deployment, and authentication, and it's just not worth it anymore. Apps Script are point and click.
This is a "Technical note" post, if you want to only follow a subset of this blog check out the tags.
Setting one up
For setting up a script I'll point you to one of Benjojo's projects, who told me about this feature. It has screenshots and everything.
Come back when you have it running. You can use this minimal script as a first program just to trigger permissions:
function ProcessInbox() {
GmailApp.getInboxUnreadCount();
}
There's no deployment or authentication effort beyond setting the schedule and clicking through the OAuth dialog.
Let's get serious
The IDE at scripts.google.com makes an attempt at tracking types for autocompletion, but it doesn't even cross forEach
or function boundaries. Not enough to make tolerable a language that has 1K points controversial StackOverflow answers on how to iterate an array.
And anyway I want to use my editor and git, like a proper homo sapiens, so let's see how to develop scripts locally with clasp and TypeScript. BTW, TypeScript is awesome.
Start by installing clasp, and don't skip the part about enabling the Apps Script API. Do a clasp login
, too.
Then in a new folder create a .clasp.json
file with this content:
{
"scriptID": "1...",
"rootDir": "built"
}
You'll find the scriptID
in the scripts.google.com URL, before the /edit
part. We use built
as the rootDir
so that we can put our TypeScript source outside of it.
Just once run clasp pull
to populate the built/appsscript.json
file. clasp push
will upload to our Script the content of built
which we will generate soon.
Create a TypeScript config file tsconfig.json
file like this (most things are preferences, but notice the target
, lib
and outDir
):
{
"compilerOptions": {
"outDir": "./built",
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitThis": true,
"noEmitOnError": true,
"target": "ES3",
"lib": ["ES2015"]
},
"include": [
"./src/**/*"
]
}
Then put some TypeScript code in src/Code.ts
and run tsc --pretty
to generate JavaScript in built
!
And here's the kicker: running npm install --save @types/google-apps-script
will make type definitions for the Gmail API available to TypeScript, so an editor like Visual Studio Code will come with proper autocompletion out of the box.
This is getting a bit too hip, so we add an old-fashioned Makefile
:
.PHONY: build deploy
build:
npm install --silent
tsc --pretty
deploy: build
clasp push
And sprinkle .gitignore
to taste. I like to exclude the generated JavaScript (but not the JSON metadata) and the node_modules
as we have a package-lock.json
:
/built/*.js
/node_modules
Now you can develop in TypeScript inside src
, with full types and autocompletion support, and deploy to your Apps Script with make deploy
. Google will run the Script every 5 minutes (if you followed Ben's instructions).
For more yak shaving, follow me on Twitter.