Google Apps Script :To set signature block for users automatically in a Google Apps Domain :

Table of contents
Reading Time: < 1 minute

A signature block (often abbreviated as signature, sig block, sig file, .sig, dot sig, siggy, or just sig) is a block of text automatically appended at the bottom of an e-mail message. Information usually contained in a signature block includes the poster’s name, phone number and email address, along with other contact details if required, such as URLs for sites owned or favoured by the author.

We can set the signature manually in Setting -> General -> Signature in Goolge account. But if we want to set signature block Automatiically for users then we have to write some code.

Our requirement is that whenever a new user arrives, a script would run and set the default signature for that user and later user can change his signature by himself.

So for this, we will write a script at Admin account of a Google Apps Domain .

So after running this code, signature block of user will be set and user can view it here Setting -> General -> Signature.

Written by 

Rishi is a tech enthusiast with having around 10 years of experience who loves to solve complex problems with pure quality. He is a functional programmer and loves to learn new trending technologies. His leadership skill is well prooven and has delivered multiple distributed applications with high scalability and availability by keeping the Reactive principles in mind. He is well versed with Scala, Akka, Akka HTTP, Akka Streams, Java8, Reactive principles, Microservice architecture, Async programming, functional programming, distributed systems, AWS, docker.

23 thoughts on “Google Apps Script :To set signature block for users automatically in a Google Apps Domain :2 min read

  1. Thank you for this! I’ve successfully implemented it into my Google Apps Script that I run when setting up new employees, and it will save me a lot of time.

    Quick tips for anyone who wants to use this with a signature that contains HTML code:
    In your newUserSignatureString variable:
    – Replace any with >
    – Replace any ” (double-quotes) with "

    Otherwise you will get a “Reference is not allowed in prolog” error.

    Also, if you’re adding this to a Google Apps Script that creates the user using this function:

    UserManager.createUser()

    …and then you want to set the signature next, make sure to include a 5-second pause:

    Utilities.sleep(5000);

    …after creating the user but before attempting to set the signature. Otherwise you will get an errorCode=”1410″ FeatureUnavailableForUser.

    You may be able to make it shorter than 5 seconds, but I did 5 just to be safe.

  2. How do I get the consumerkey and consumersecret? Can’t find it anywhere in the developers console and don’t see a way to create them.

  3. Good evening Rishi,

    This script it fantastic and I’ve been using it for the last 2 years, however, as Alessio mentioned, it is no longer working as Google have deprecated oAuth. I would very much appreciate your assistance in updating this script to work with Google’s new authentication APIs?

  4. Hey Nick and Alessio, it’s Mike from the first comment.

    I, also, was confused as to how to upgrade all my scripts from OAuth 1 to 2, so I feel obligated to post my working solution here…

    First, you need to follow the steps to add this library to your Apps Script project:

    https://github.com/googlesamples/apps-script-oauth2

    This can be a little confusing at first, so let me know if you have any problems with it. To save you some confusion, I’ve included my working adaptation of the code needed to use their library below. So pretty much all you have to do is:

    – Add the Library to your project
    – Get your OAUTH2_PROJECT_KEY, OAUTH2_CLIENT_SECRET, and OAUTH2_CLIENT_ID from the Google Developers console
    – Set them as constants in your project

    After you have that set up, you use their library to create an OAuth 2 service that is needed when calling the Email Settings API:

    function beginNewEmployeeProcedures() {

    var emailSettingsOauth2Service = createOauth2Service(‘Email Settings API’,’https://apps-apis.google.com/a/feeds/emailsettings/2.0/’,’authCallbackForEmailSettingsApi’);
    if (!emailSettingsOauth2Service.hasAccess()) { startOauth2AuthFlow(‘Email Settings API’,emailSettingsOauth2Service); return; }

    setSignature(emailSettingsOauth2Service,’test@yourgoogleappsdomain.com’,’cool email signature’);

    }

    function setSignature(service,email,signature) {

    try {

    var username = email.split(“@”)[0];

    var xml = ” +
    ” +
    ”;

    var fetchArgs = {};
    fetchArgs.headers = {‘Authorization’: ‘Bearer ‘+ service.getAccessToken()};
    fetchArgs.method = “PUT”;
    fetchArgs.contentType = “application/atom+xml”;
    fetchArgs.payload = xml;
    fetchArgs.muteHttpExceptions = true;

    var url = ‘https://apps-apis.google.com/a/feeds/emailsettings/2.0/yourgoogleappsdomain.com/’ + username + ‘/signature’;

    UrlFetchApp.fetch(url, fetchArgs);

    } catch(e) {

    // failure notification email, etc

    }

    }

    function createOauth2Service(serviceName,scope,callbackFunctionName) {

    // Create a new service with the given name. The name will be used when
    // persisting the authorized token, so ensure it is unique within the
    // scope of the property store.
    var service = OAuth2.createService(serviceName)

    // Set the endpoint URLs, which are the same for all Google services.
    .setAuthorizationBaseUrl(‘https://accounts.google.com/o/oauth2/auth’)
    .setTokenUrl(‘https://accounts.google.com/o/oauth2/token’)

    // Set the client ID and secret, from the Google Developers Console.
    .setClientId(OAUTH2_CLIENT_ID)
    .setClientSecret(OAUTH2_CLIENT_SECRET)

    // Set the project key of the script using this library.
    .setProjectKey(OAUTH2_PROJECT_KEY)

    // Set the name of the callback function in the script referenced
    // above that should be invoked to complete the OAuth flow.
    .setCallbackFunction(callbackFunctionName)

    // Set the property store where authorized tokens should be persisted.
    .setPropertyStore(PropertiesService.getUserProperties())

    // Set the scopes to request (space-separated for Google services).
    .setScope(scope)

    // Below are Google-specific OAuth2 parameters.

    // Sets the login hint, which will prevent the account chooser screen
    // from being shown to users logged in with multiple accounts.
    .setParam(‘login_hint’, Session.getActiveUser().getEmail())

    // Requests offline access.
    .setParam(‘access_type’, ‘offline’)

    // Forces the approval prompt every time. This is useful for testing,
    // but not desirable in a production application.
    .setParam(‘approval_prompt’, ‘force’);

    return service;

    }

    function startOauth2AuthFlow(serviceName,service) {

    var authorizationUrl = service.getAuthorizationUrl();

    var template = HtmlService.createTemplate(
    ‘<a href="” target=”_blank”>’+
    ‘Click here to authorize this script to access the ‘ + serviceName + ‘‘ +
    ‘After closing the other tab, click the X in this window and start the script again.’);

    template.authorizationUrl = authorizationUrl;

    var page = template.evaluate();

    SpreadsheetApp.getUi().showModalDialog(page, ‘API Authorization’);

    }

    function authCallbackForEmailSettingsApi(request) {

    // this script is called by the auth screen when the user clicks the blue Accept button

    var oauth2Service = createOauth2Service(‘Email Settings API’,’https://apps-apis.google.com/a/feeds/emailsettings/2.0/’,’authCallbackForEmailSettingsApi’);

    var isAuthorized = oauth2Service.handleCallback(request);

    if (isAuthorized) {
    return HtmlService.createHtmlOutput(‘Success! You can close this tab.’);
    } else {
    return HtmlService.createHtmlOutput(‘Didn\’t work.’);
    }

    }

    That’s it!

    Also, I just want to mention that I had to create authCallbackForEmailSettingsApi() specifically as the auth callback for this script, because the auth callback doesn’t seem to be able to send parameters or variables back to Apps Script, yet the auth callback needs to include the service name, scope, and callback function name in order to call createOauth2Service() again. If anyone knows of a way to get those values back from the server without needing a specific auth callback function, let me know! Then we could make a generic auth callback function and it could be re-used for different calls to different APIs.

    1. Hey Mike, thanks very much for your response and for the code from your project, I’m going to have a look through it this evening and give it a try!

  5. @Mike Are you able to assist me with this. I’ve followed your instructions, I feel exactly, but cannot get my script to work. I’m stuck with the deprecated version. Would you be able to PM me? I would value your time, of course. Thank you,

      1. Cool, thanks Nick!

        Derek – let me know if you still have any trouble after looking through that.

    1. Hi Danilo,

      We figured out a great way to do this using the Gmail API and “Domain-wide Delegation”, which is a way for G Suite admins to make API calls on behalf of users within their domain. Basically, you need to “be” the user making the call to the API, so here’s how to do it automatically from a script as an admin without having to get the user themselves involved.

      Step 1: Make sure the OAuth2 For Apps Script (https://github.com/googlesamples/apps-script-oauth2) library is added to your project (details in previous post above).

      Step 2: Set up Domain-Wide Delegation. There’s a page here explaining how to do it for the Drive API, but it’s pretty much the same for any Google API. Follow the steps for everything on this page up to and including the “Delegate domain-wide authority to your service account” step. (https://developers.google.com/drive/v2/web/delegation)

      Also, they may have updated the Google API Console and some of the steps in this documentation might not have been updated to match, but it’s not hard to figure out the new way to do it. Let me know if you have any trouble.

      Step 3: The code below includes how to set the signature, and also how to use the Domain-Wide Delegation service account.

      Please note: the whole do/while look with the maxSetSignatureAttempts and currentSetSignatureAttempts variables is not necessary. I added it because we set signatures immediately after creating the Google account and assigning the G Suite license, and sometimes the API returns an error as if the user wasn’t created yet. That do/while loop basically waits 3 seconds if it gets an error, then tries again, up to 20 times. You wouldn’t have that issue if you’re setting signatures for existing users. Also, originally I just had a fixed 10-second sleep, but most of the time it didn’t need to take that long, and other times, it would still fail. So this loop is better than a fixed sleep amount.

      function setSignatureTest() {

      var email = ‘test@test.com’;

      var signature = ‘test signature’;

      var test = setSignature(email, signature);

      Logger.log(‘test result: ‘ + test);

      }

      function setSignature(email, signature) {

      Logger.log(‘starting setSignature’);

      var signatureSetSuccessfully = false;

      var service = getDomainWideDelegationService(‘Gmail: ‘, ‘https://www.googleapis.com/auth/gmail.settings.basic’, email);

      if (!service.hasAccess()) {

      Logger.log(‘failed to authenticate as user ‘ + email);

      Logger.log(service.getLastError());

      signatureSetSuccessfully = service.getLastError();

      return signatureSetSuccessfully;

      } else Logger.log(‘successfully authenticated as user ‘ + email);

      var username = email.split(“@”)[0];

      var resource = { signature: signature };

      var requestBody = {};
      requestBody.headers = {‘Authorization’: ‘Bearer ‘ + service.getAccessToken()};
      requestBody.contentType = “application/json”;
      requestBody.method = “PUT”;
      requestBody.payload = JSON.stringify(resource);
      requestBody.muteHttpExceptions = false;

      var emailForUrl = encodeURIComponent(email);

      var url = ‘https://www.googleapis.com/gmail/v1/users/me/settings/sendAs/’ + emailForUrl;

      var maxSetSignatureAttempts = 20;
      var currentSetSignatureAttempts = 0;

      do {

      try {

      currentSetSignatureAttempts++;

      Logger.log(‘currentSetSignatureAttempts: ‘ + currentSetSignatureAttempts);

      var setSignatureResponse = UrlFetchApp.fetch(url, requestBody);

      Logger.log(‘setSignatureResponse on successful attempt:’ + setSignatureResponse);

      signatureSetSuccessfully = true;

      break;

      } catch(e) {

      Logger.log(‘set signature failed attempt, waiting 3 seconds and re-trying’);

      Utilities.sleep(3000);

      }

      if (currentSetSignatureAttempts >= maxSetSignatureAttempts) {

      Logger.log(‘exceeded ‘ + maxSetSignatureAttempts + ‘ set signature attempts, deleting user and ending script’);

      throw new Error(‘Something went wrong when setting their email signature.’);

      }

      } while (!signatureSetSuccessfully);

      return signatureSetSuccessfully;

      }

      // these two things are included in the .JSON file that you download when creating the service account and service account key
      var OAUTH2_SERVICE_ACCOUNT_PRIVATE_KEY = ‘—–BEGIN PRIVATE KEY—–\nxxxxxxxxxxxxxxxxxxxxx\n—–END PRIVATE KEY—–\n’;
      var OAUTH2_SERVICE_ACCOUNT_CLIENT_EMAIL = ‘xxxxxxxxxxxxxxxxxxxxx.iam.gserviceaccount.com’;

      function getDomainWideDelegationService(serviceName, scope, email) {

      Logger.log(‘starting getDomainWideDelegationService for email: ‘ + email);

      return OAuth2.createService(serviceName + email)
      // Set the endpoint URL.
      .setTokenUrl(‘https://accounts.google.com/o/oauth2/token’)

      // Set the private key and issuer.
      .setPrivateKey(OAUTH2_SERVICE_ACCOUNT_PRIVATE_KEY)
      .setIssuer(OAUTH2_SERVICE_ACCOUNT_CLIENT_EMAIL)

      // Set the name of the user to impersonate. This will only work for
      // Google Apps for Work/EDU accounts whose admin has setup domain-wide
      // delegation:
      // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
      .setSubject(email)

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getScriptProperties())

      // Set the scope. This must match one of the scopes configured during the
      // setup of domain-wide delegation.
      .setScope(scope);

      }

    1. Hi Danilo,

      We figured out a great way to do this using the Gmail API and “Domain-wide Delegation”, which is a way for G Suite admins to make API calls on behalf of users within their domain. Basically, you need to “be” the user making the call to the API, so here’s how to do it automatically from a script.

      Step 1: Make sure the OAuth2 For Apps Script (https://github.com/googlesamples/apps-script-oauth2) library is added to your project (details in previous post above)

      Step 2: Set up Domain-Wide Delegation. There’s a page here explaining how to do it for the Drive API, but it’s pretty much the same for any Google API. Follow the steps for everything on this page up to and including the “Delegate domain-wide authority to your service account” step. (https://developers.google.com/drive/v2/web/delegation)

      Also, they may have updated the Google API Console and some of the steps in this documentation might not have been updated to match, but it’s not hard to figure out the new way to do it. Let me know if you have any trouble.

      Step 3: The code below includes how to set the signature, and also how to use the Domain-Wide Delegation service account.

      Please note: the whole do/while look with the maxSetSignatureAttempts and currentSetSignatureAttempts variables is not necessary. I added it because we set signatures immediately after creating the Google account and assigning the G Suite license, and sometimes the API returns an error as if the user wasn’t created yet. That do/while loop basically waits 3 seconds if it gets an error, then tries again, up to 20 times. You wouldn’t have that issue if you’re setting signatures for existing users. Also, originally I just had a fixed 10-second sleep, but most of the time it didn’t need to take that long, and other times, it would still fail. So this loop is better than a fixed sleep amount.

      function setSignatureTest() {

      var email = ‘test@test.com’;

      var signature = ‘test signature’;

      var test = setSignature(email, signature);

      Logger.log(‘test result: ‘ + test);

      }

      function setSignature(email, signature) {

      Logger.log(‘starting setSignature’);

      var signatureSetSuccessfully = false;

      var service = getDomainWideDelegationService(‘Gmail: ‘, ‘https://www.googleapis.com/auth/gmail.settings.basic’, email);

      if (!service.hasAccess()) {

      Logger.log(‘failed to authenticate as user ‘ + email);

      Logger.log(service.getLastError());

      signatureSetSuccessfully = service.getLastError();

      return signatureSetSuccessfully;

      } else Logger.log(‘successfully authenticated as user ‘ + email);

      var username = email.split(“@”)[0];

      var resource = { signature: signature };

      var requestBody = {};
      requestBody.headers = {‘Authorization’: ‘Bearer ‘ + service.getAccessToken()};
      requestBody.contentType = “application/json”;
      requestBody.method = “PUT”;
      requestBody.payload = JSON.stringify(resource);
      requestBody.muteHttpExceptions = false;

      var emailForUrl = encodeURIComponent(email);

      var url = ‘https://www.googleapis.com/gmail/v1/users/me/settings/sendAs/’ + emailForUrl;

      var maxSetSignatureAttempts = 20;
      var currentSetSignatureAttempts = 0;

      do {

      try {

      currentSetSignatureAttempts++;

      Logger.log(‘currentSetSignatureAttempts: ‘ + currentSetSignatureAttempts);

      var setSignatureResponse = UrlFetchApp.fetch(url, requestBody);

      Logger.log(‘setSignatureResponse on successful attempt:’ + setSignatureResponse);

      signatureSetSuccessfully = true;

      break;

      } catch(e) {

      Logger.log(‘set signature failed attempt, waiting 3 seconds and re-trying’);

      Utilities.sleep(3000);

      }

      if (currentSetSignatureAttempts >= maxSetSignatureAttempts) {

      Logger.log(‘exceeded ‘ + maxSetSignatureAttempts + ‘ set signature attempts, deleting user and ending script’);

      throw new Error(‘Something went wrong when setting their email signature.’);

      }

      } while (!signatureSetSuccessfully);

      return signatureSetSuccessfully;

      }

      // these two things are included in the .JSON file that you download when creating the service account and service account key
      var OAUTH2_SERVICE_ACCOUNT_PRIVATE_KEY = ‘—–BEGIN PRIVATE KEY—–\nxxxxxxxxxxxxxxxxxxxxx\n—–END PRIVATE KEY—–\n’;
      var OAUTH2_SERVICE_ACCOUNT_CLIENT_EMAIL = ‘xxxxxxxxxxxxxxxxxxxxx.iam.gserviceaccount.com’;

      function getDomainWideDelegationService(serviceName, scope, email) {

      Logger.log(‘starting getDomainWideDelegationService for email: ‘ + email);

      return OAuth2.createService(serviceName + email)
      // Set the endpoint URL.
      .setTokenUrl(‘https://accounts.google.com/o/oauth2/token’)

      // Set the private key and issuer.
      .setPrivateKey(OAUTH2_SERVICE_ACCOUNT_PRIVATE_KEY)
      .setIssuer(OAUTH2_SERVICE_ACCOUNT_CLIENT_EMAIL)

      // Set the name of the user to impersonate. This will only work for
      // Google Apps for Work/EDU accounts whose admin has setup domain-wide
      // delegation:
      // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
      .setSubject(email)

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getScriptProperties())

      // Set the scope. This must match one of the scopes configured during the
      // setup of domain-wide delegation.
      .setScope(scope);

      }

    2. Hi Danilo,

      We figured out a great way to do this using the Gmail API and “Domain-wide Delegation”, which is a way for G Suite admins to make API calls on behalf of users within their domain. Basically, you need to “be” the user making the call to the API, so here’s how to do it automatically from a script.

      Step 1: Make sure the OAuth2 For Apps Script (https://github.com/googlesamples/apps-script-oauth2) library is added to your project (details in previous post above)

      Step 2: Set up Domain-Wide Delegation. There’s a page here explaining how to do it for the Drive API, but it’s pretty much the same for any Google API. Follow the steps for everything on this page up to and including the “Delegate domain-wide authority to your service account” step. (https://developers.google.com/drive/v2/web/delegation)

      Also, they may have updated the Google API Console and some of the steps in this documentation might not have been updated to match, but it’s not hard to figure out the new way to do it. Let me know if you have any trouble.

      Step 3: The code below includes how to set the signature, and also how to use the Domain-Wide Delegation service account.

      Please note: the whole do/while look with the maxSetSignatureAttempts and currentSetSignatureAttempts variables is not necessary. I added it because we set signatures immediately after creating the Google account and assigning the G Suite license, and sometimes the API returns an error as if the user wasn’t created yet. That do/while loop basically waits 3 seconds if it gets an error, then tries again, up to 20 times. You wouldn’t have that issue if you’re setting signatures for existing users. Also, originally I just had a fixed 10-second sleep, but most of the time it didn’t need to take that long, and other times, it would still fail. So this loop is better than a fixed sleep amount.

      function setSignatureTest() {

      var email = ‘test@test.com’;

      var signature = ‘test signature’;

      var test = setSignature(email, signature);

      Logger.log(‘test result: ‘ + test);

      }

      // continued in next comment…

    1. I’m sorry for my absence. I’m going to see the code now and you’re sure to have my upvote. Thank you for your dedication.

    2. It works perfectly well! Thank you so much Mike. I have no reputation for commenting on stackoverflow yet, but I’ve left an upvote for you there, and you deserve so much more than that!

      1. Also, now that you’ve set up Domain-Wide Delegation of Authority, there’s so much more you can do as a G Suite admin with Apps Script. I’ve created an entire employee on-boarding/off-boarding process that involves hundreds of scripts, some of which use DWD to “impersonate” users when necessary for things like transferring ownership of Drive documents, creating and updating calendar events on another user’s behalf, and sending emails so they appear to come from a certain user. Just some inspiration for you.

Comments are closed.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading