如何使用 Gmail API、OAuth2 for Apps 脚本和域范围委派为 G Suite 域中的用户设置电子邮件签名
How to use the Gmail API, OAuth2 for Apps Script, and Domain-Wide Delegation to set email signatures for users in a G Suite domain
这是我之前发布的 question/answer 的跟进(), but I'm creating a new question since the Email Settings API 已被弃用,现在的过程有很大不同。
作为 G Suite 域的管理员,您如何使用 Gmail API 通过 Google Apps 脚本以编程方式设置域中用户的电子邮件签名?
此方法使用 Gmail API、OAuth2 for Apps 脚本库和 "Domain-wide Delegation of Authority",这是 G Suite 管理员代表用户进行 API 调用的一种方式在他们的领域内。
第 1 步:确保 OAuth2 For Apps Script 库已添加到您的项目中。
第 2 步: 设置 "Domain-Wide Delegation of Authority." 有一个页面 here 解释了如何为驱动器 API 做这件事,但它很漂亮对于任何 Google API,包括 Gmail API,都大同小异。按照该页面上的步骤进行操作,直至并包括 "Delegate domain-wide authority to your service account" 步骤。
第3步:下面的代码包括如何在前面的步骤完成后设置签名:
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);
}
请注意:不需要使用 maxSetSignatureAttempts
和 currentSetSignatureAttempts
变量的 do-while 循环。我添加它是因为如果您在创建 Google 帐户并分配 G Suite 许可证后立即尝试设置签名,有时 Gmail API returns 会出现错误,就好像用户不是'尚未创建。如果出现错误,do-while 循环基本上会等待 3 秒,然后重试,最多 x 次。如果您为现有用户设置签名,则不应出现该问题。还有,本来我就是固定的10秒sleep,但是大部分时候不需要那么久,但其他时候还是会失败。所以这个循环比固定的睡眠量要好。
这是我之前发布的 question/answer 的跟进(
作为 G Suite 域的管理员,您如何使用 Gmail API 通过 Google Apps 脚本以编程方式设置域中用户的电子邮件签名?
此方法使用 Gmail API、OAuth2 for Apps 脚本库和 "Domain-wide Delegation of Authority",这是 G Suite 管理员代表用户进行 API 调用的一种方式在他们的领域内。
第 1 步:确保 OAuth2 For Apps Script 库已添加到您的项目中。
第 2 步: 设置 "Domain-Wide Delegation of Authority." 有一个页面 here 解释了如何为驱动器 API 做这件事,但它很漂亮对于任何 Google API,包括 Gmail API,都大同小异。按照该页面上的步骤进行操作,直至并包括 "Delegate domain-wide authority to your service account" 步骤。
第3步:下面的代码包括如何在前面的步骤完成后设置签名:
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);
}
请注意:不需要使用 maxSetSignatureAttempts
和 currentSetSignatureAttempts
变量的 do-while 循环。我添加它是因为如果您在创建 Google 帐户并分配 G Suite 许可证后立即尝试设置签名,有时 Gmail API returns 会出现错误,就好像用户不是'尚未创建。如果出现错误,do-while 循环基本上会等待 3 秒,然后重试,最多 x 次。如果您为现有用户设置签名,则不应出现该问题。还有,本来我就是固定的10秒sleep,但是大部分时候不需要那么久,但其他时候还是会失败。所以这个循环比固定的睡眠量要好。