Professional Documents
Culture Documents
Log in
Create account
3
Like
1
Unicorn
3
Save
There are a number of Google Suite Domain signature software applications out
there, but we have fairly straightforward requirements and wanted to create a cost-
free solution. Previously we used Signature Satori but for our simple needs, this
was overkill.
be consistent
contain tracking URLs for Google Analytics
optionally contain a job title
optionally contain a direct dial
optionally contain an additional message, for part time staff
Additionally we have a number of service accounts which we do not want to include a
signature on, as they have account names like "Impression Accounts".
Things to set up
The permissions required by this script span outside of the usual permissions a
Google Script requires, so there's a few bits you'll need to set up in advance.
Gmail API
Admin SDK
Configure a Service Account under "Credentials" and save the output file
2. OAuth 2.0
OAuth 2.0 can be added to Google Scripts via the Resources > Libraries dialog. Just
so these instructions do not get outdated, please read the originals here on
GitHub.
Scopes:
https://apps-apis.google.com/a/feeds/emailsettings/2.0/
https://www.googleapis.com/auth/gmail.settings.basic
https://www.googleapis.com/auth/gmail.settings.sharing
5. Optionally set up you additional Google User Admin fields
As mentioned above, our requirements here is that we show additional signature
settings, such as job title, working hours, Google Voice numbers. Your usage may
vary, but as we all know it's easy to strip back from a code sample than add to it.
So this code includes all of the above.
To add additional fields (called "custom user attributes" in Google speak), read
this help article.
We have the following fields set up under the new category "Email signature":
Show_job_title_in_signature (Yes/No)
Working_Hours_Description (Text)
Custom user attribute settings inside Google Admin
There are two files; the first should be pasted over your Code.gs file. The second
code snippet should be added to a new HTML file in the project. Head to File > New
> HTML File to add this. Name it signature.html.
Code.gs
var accountsToIgnore = [
'ignore-me@example.com',
'noreply@example.com'
];
var auth = {
"private_key": "-----BEGIN PRIVATE KEY-----\nABCDE\n-----END PRIVATE KEY-----\n",
"client_email": "name@project-id-XXX.iam.gserviceaccount.com",
"client_id": "INSERT_CLIENT_ID_HERE"
};
function go() {
var pageToken;
var page;
do {
page = AdminDirectory.Users.list({
domain: 'example.com',
orderBy: 'familyName',
maxResults: 250,
pageToken: pageToken,
projection: 'full',
// query: "email=your.email@example.com"
});
if (page.users) {
page.users.forEach( function (user){
if (accountsToIgnore.indexOf(user.primaryEmail) == -1) {
if (typeof
user.customSchemas.Email_signature.Show_job_title_in_signature !== 'undefined' &&
user.customSchemas.Email_signature.Show_job_title_in_signature == false) {
userData.showJobTitle = false;
}
if (typeof
user.customSchemas.Email_signature.Working_Hours_Description !== 'undefined' &&
user.customSchemas.Email_signature.Working_Hours_Description != "") {
userData.workingHours = "<br /><br
/><i>"+user.customSchemas.Email_signature.Working_Hours_Description+"</i><br />";
}
}
}
if (user.hasOwnProperty('organizations') &&
user.organizations[0].hasOwnProperty('title') && typeof user.organizations[0].title
!== "undefined" && userData.showJobTitle == true) {
userData.jobTitle = user.organizations[0].title+"<br />";
}
var sigAPIUrl =
Utilities.formatString('https://www.googleapis.com/gmail/v1/users/%s/settings/
sendAs/%s',userData.email, userData.email);
} else {
Logger.log('No users found.');
}
pageToken = page.nextPageToken;
} while (pageToken);
}
function getOAuthService(userId) {
return OAuth2.createService("Signature Setter "+userId)
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
.setPrivateKey(auth.private_key)
.setIssuer(auth.client_email)
.setPropertyStore(PropertiesService.getScriptProperties())
.setSubject(userId)
.setParam('access_type', 'offline')
.setScope('https://www.googleapis.com/auth/gmail.settings.basic
https://www.googleapis.com/auth/gmail.settings.sharing');
}
signature.html
<br />
<b style='font-size:small'>{firstName} {lastName}</b><br />
{jobTitle}Impression<br />
<a href='http://www.impression.co.uk/?
utm_source=personalemail&utm_medium=email&utm_campaign=EmailSig&utm_con
tent={firstName}-{lastName}' rel='nofollow'><img alt='Impression' height='66'
src='https://www.google.com/a/impression.co.uk/images/logo.gif' width='160'
/></a><br />
<br />
T: 01158 242 212 {directNumber}<br />
E: {email}<br />
W: <a href='https://www.impression.co.uk/?
utm_source=personalemail&utm_medium=email&utm_campaign=EmailSig&utm_con
tent={firstName}-{lastName}' rel='nofollow'>www.impression.co.uk</a><br />
<br />
Specialists in <a href='https://www.impression.co.uk/digital-marketing/seo/?
utm_source=personalemail&utm_medium=email&utm_campaign=EmailSig&utm_con
tent={firstName}-{lastName}' rel='nofollow'>SEO</a>, <a
href='https://www.impression.co.uk/digital-marketing/ppc/?
utm_source=personalemail&utm_medium=email&utm_campaign=EmailSig&utm_con
tent={firstName}-{lastName}' rel='nofollow'>PPC</a>, <a
href='https://www.impression.co.uk/digital-marketing/digital-pr/?
utm_source=personalemail&utm_medium=email&utm_campaign=EmailSig&utm_con
tent={firstName}-{lastName}' rel='nofollow'>Digital PR</a> & <a
href='https://www.impression.co.uk/digital-marketing/analytics/?
utm_source=personalemail&utm_medium=email&utm_campaign=EmailSig&utm_con
tent={firstName}-{lastName}' rel='nofollow'>Analytics</a>{workingHours}
By looking through the signature.html file you'll see plenty of placeholder values
that we're using, like "{lastName}", embedded between our signature.
This aspect is one that you'll definitely want to customise to fit your own needs.
Here's what our signature looks like:
8. Testing
When testing, see the commented "query" line. Use this to query specific accounts,
like your own, which comes in handy for live testing this solution.
Bear in in mind that your browser will not show a new email signature until you
fully refresh all open Gmail windows.
9. Scheduling
Once created, it's worth thinking about using a daily trigger to ensure consistency
is maintained across your business over time. We run the "go" script on a timer
trigger, once nightly.
Thank you
I hope this is enough to get you started on your own custom signature adventures.
Please hit me up on twitter @aarondicks if you have any specific questions!
Discussion (3)
Subscribe
pic
Add to the discussion
cdwarak profile image
Dwarakanath Cheyyur
•
Aug 10 '21
Hi Aaron
1
like
Like
Reply
Do you have any other Docs or any tip of how to implement OAuth ?
I'm trying your code but I don't find out how to implement the auth part. I was
looking for some example about it in the Gmail API and Workspace API but didn't
have luck.
1
like
Like
Reply
Hi, sorry, I've just seen this comment. I've since updated the domain-wide oauth
delegation step above to include what I think you might have been missing.
Apologies for the inconvenience. Thanks, Aaron
1
like
Like
Reply
Code of Conduct • Report abuse
🌱 DEV runs on 100% open source code known as Forem.
Read next
rmion profile image
Leonardo's Monorail
Robert Mion - Aug 11
Impression
Follow
Trending on DEV Community 👩💻👨💻
Michael Tharrington profile image
What was your win this week?
#discuss #weeklyretro
Ben Halpern profile image
Meme Monday 🌴
#discuss #watercooler #jokes
Sloan profile image
What would you do if you had a year off between jobs?
#anonymous #discuss #career #watercooler
var accountsToIgnore = [
'ignore-me@example.com',
'noreply@example.com'
];
var auth = {
"private_key": "-----BEGIN PRIVATE KEY-----\nABCDE\n-----END PRIVATE KEY-----\n",
"client_email": "name@project-id-XXX.iam.gserviceaccount.com",
"client_id": "INSERT_CLIENT_ID_HERE"
};
function go() {
var pageToken;
var page;
do {
page = AdminDirectory.Users.list({
domain: 'example.com',
orderBy: 'familyName',
maxResults: 250,
pageToken: pageToken,
projection: 'full',
// query: "email=your.email@example.com"
});
if (page.users) {
page.users.forEach( function (user){
if (accountsToIgnore.indexOf(user.primaryEmail) == -1) {
if (typeof
user.customSchemas.Email_signature.Show_job_title_in_signature !== 'undefined' &&
user.customSchemas.Email_signature.Show_job_title_in_signature == false) {
userData.showJobTitle = false;
}
if (typeof
user.customSchemas.Email_signature.Working_Hours_Description !== 'undefined' &&
user.customSchemas.Email_signature.Working_Hours_Description != "") {
userData.workingHours = "<br /><br
/><i>"+user.customSchemas.Email_signature.Working_Hours_Description+"</i><br />";
}
}
}
if (user.hasOwnProperty('organizations') &&
user.organizations[0].hasOwnProperty('title') && typeof user.organizations[0].title
!== "undefined" && userData.showJobTitle == true) {
userData.jobTitle = user.organizations[0].title+"<br />";
}
var sigAPIUrl =
Utilities.formatString('https://www.googleapis.com/gmail/v1/users/%s/settings/
sendAs/%s',userData.email, userData.email);
} else {
Logger.log('No users found.');
}
pageToken = page.nextPageToken;
} while (pageToken);
}
function getOAuthService(userId) {
return OAuth2.createService("Signature Setter "+userId)
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
.setPrivateKey(auth.private_key)
.setIssuer(auth.client_email)
.setPropertyStore(PropertiesService.getScriptProperties())
.setSubject(userId)
.setParam('access_type', 'offline')
.setScope('https://www.googleapis.com/auth/gmail.settings.basic
https://www.googleapis.com/auth/gmail.settings.sharing');
}
DEV Community 👩💻👨💻 — A constructive and inclusive social network for software
developers. With you every step of your journey.
Built on Forem — the open source software that powers DEV and other inclusive
communities.
Made with love and Ruby on Rails. DEV Community 👩💻👨💻 © 2016 - 2022.