REST request to update GMAIL signature with Domain validation - rest

I've created the below code with some help to access any user's signature on my domain in order to standardize the signature across users. Currently, When I specify method 'PATCH' in the URLFetch parameters, All I get is the sendAs resource of the email I sent, including the old signature. If I specify the PUT method, it removes the signature, but will not set the signature I specified onto the account. Could someone help me see what I am doing wrong?
////////////////////////////////////////////////////FUNCTION SET SIGNATURE////////////////////////////////////////////////////////////////////////
/**
* Authorizes and makes a request to the GMail API.
*/
function setSignature(user)
{
var user = 'me#mydomain.com';
var newSig = '<b>This is my new Signature!</b>';
var service = getService(user);
if (service.hasAccess()) {
var url = 'https://www.googleapis.com/gmail/v1/users/'+user+'/settings/sendAs/'+user;
var payload =
{
"sendAsEmail" : user,
"displayName" : AdminDirectory.Users.get(user).name.fullName,
"type" : "patch",
"replyToAddress" : user,
"signature": newSig
};
var options =
{
"method" : "PUT",
"payload" : payload,
"muteHttpExceptions": true,
"contentType": "ctAPPLICATION_JSON",
"headers": {Authorization: 'Bearer ' + service.getAccessToken()}
};
var response = UrlFetchApp.fetch(url, options);
Logger.log(response.getContentText());
} else {
Logger.log(service.getLastError());
}
}
////////////////////////////////////////////////////FUNCTION VIEW SIGNATURE////////////////////////////////////////////////////////////////////////
function viewSignature(user) { var user = USER_EMAIL;
var service = getService(user);
Logger.log(service.hasAccess());
if (service.hasAccess()) {
var url = 'https://www.googleapis.com/gmail/v1/users/'+user+'/settings/sendAs';
var response = UrlFetchApp.fetch(url, {
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
}
});
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
} else {
Logger.log(service.getLastError());
}
}
////////////////////////////////////////////////////FUNCTION RESET//////////////////////////////////////////////////////////////////////////////////////
/**
* Reset the authorization state, so that it can be re-tested.
*/
function reset() {
var service = getService();
service.reset();
}
///////////////////////////////////////////////////////////FUNCTION GET SERVICE////////////////////////////////////////////////////////////////////////
/**
* Configures the service.
*/
function getService(user) {
return OAuth2.createService('Gmail:' + user)
// Set the endpoint URL.
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
// Set the private key and issuer.
.setPrivateKey(PRIVATE_KEY)
.setIssuer(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(user)
// 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('https://www.googleapis.com/auth/gmail.settings.basic', 'https://www.googleapis.com/auth/gmail.settings.sharing');
}
////////////////////////////////////////////////////FUNCTION CLEAR SIGNATURE////////////////////////////////////////////////////////////////////////
function clearService(){
OAuth2.createService('drive')
.setPropertyStore(PropertiesService.getUserProperties())
.reset();
}
NOTE: OAuth2 Credentials are stored in Constant variables in a separate file, but I have verified that the credentials return valid data.
Thanks,

My apps works, problem is contentType.
Try:
var formData = {'sendAsEmail':user,'type':'patch','signature': newSig}
var options =
{
'method' : 'put',
'muteHttpExceptions': true,
'contentType': 'application/json',
'headers': {Authorization: 'Bearer ' + service.getAccessToken()},
'payload': JSON.stringify(formData)
};

Related

Flutter qraphQl issue with setting requesting data from body of api

I am trying to connect to an graphQl api that uses the token as the password in the Basic auth section of the header. I have tried using flutter_graphql but as I only get the token back after the user logs in. I have managed to get logged in using:
String username = "";
String password = token;
String basicAuth = 'Basic' + base64Encode(utf8.encode("$username:$password"));
String projects = "query Projects{Projects{id name}}";
Uri newUri = Uri.parse("$link");
var newResponse = await http.post(newUri, headers: {
"Authorization": basicAuth,
"Content-Type": "application/graphql"
}, body: //I need to get projects here.
);
var newNonJsonData = newResponse.body;
group("Testing the graph ql data after logging in: ", () {
test("Logged in", () {
expect(newResponse.statusCode, 200);
});
test("getting the data from the api", () {
print("non json return:" + newNonJsonData);
});
});
I have tried to set the body as
jsonEncode({
'query' : prjects
})
but the moment I request the data it asks to log in.
Please could someone help!!!

How to use the Gmail API, OAuth2 for Apps Script, and Domain-Wide Delegation to set email signatures for users' alias in a G Suite domain

This is a continuation of this question: 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
It showed a way to set a signature for another account, using Oauth2, Apps Script, and domain wide delegation.
However, it was not working for me when I have this scenario: I have a domain alias in our G-Suite account where myuser#aliasdomain.com is an alias for myuser#maindomain.com. I want to set a signature for myuser#aliasdomain.com. The example from the prior question only did myuser#maindomain.com.
Is it possible?
I tried this (modified from prior question's example code):
var credentials = {
"type": "service_account",
"project_id": "project-id-4606494xxxxxxxxx3",
"private_key_id": "8481966716a20fe34615daxxxxxxxxa",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXbOAiODt\n-----END PRIVATE KEY-----\n",
"client_email": "xxxxxxxxxxxx#project-id-46064949xxxxxxxxxxxx.iam.gserviceaccount.com",
"client_id": "112076306220190xxxxxxxxxx",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/xxxxxxxxxxxx%40project-id-4606494951xxxxxxxxxxxxxx.iam.gserviceaccount.com"
}
function setSignatureTest() {
var loginEmail = 'myuser#maindomain.com';
var sendAsEmail = 'myuser#aliasdomain.com';
var signature = 'test for awesome signature';
var test = setSignature(loginEmail, sendAsEmail, signature);
Logger.log('test result: ' + test);
}
function setSignature(loginEmail, sendAsEmail, signature) {
Logger.log('starting setSignature');
var signatureSetSuccessfully = false;
var service = getDomainWideDelegationService('Gmail: ', 'https://www.googleapis.com/auth/gmail.settings.basic', loginEmail);
if (!service.hasAccess()) {
Logger.log('failed to authenticate as user ' + loginEmail);
Logger.log(service.getLastError());
signatureSetSuccessfully = service.getLastError();
return signatureSetSuccessfully;
} else Logger.log('successfully authenticated as user ' + loginEmail);
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 loginEmailForUrl = encodeURIComponent(loginEmail);
var sendAsEmailForUrl = encodeURIComponent(sendAsEmail);
var url = 'https://www.googleapis.com/gmail/v1/users/' + loginEmailForUrl + '/settings/sendAs/' + sendAsEmailForUrl;
var maxSetSignatureAttempts = 10;
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;
}
function getDomainWideDelegationService(serviceName, scope, email) {
Logger.log('starting getDomainWideDelegationService for email: ' + email);
return OAuth2.createService(serviceName + email)
// Set the endpoint URL.
.setTokenUrl(credentials.token_uri)
// Set the private key and issuer.
.setPrivateKey(credentials.private_key)
.setIssuer(credentials.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);
}
It works as I have loginEmail and sendAsEmail set to the loginEmail, but not when set to the one for the domain alias.
I'd appreciate any ideas/help.
Thanks.

Twilio IP Messaging user not found

I'm trying to add a users identity to a channel using the REST API using instructions here: https://www.twilio.com/docs/api/ip-messaging/rest/members#action-create
I'm posting to the /Channels/channelId/Members endpoint - I'm certain my request is structured correctly.
I get an error back from Twilio IP Messaging saying:
{"code": 50200, "message": "User not found", "more_info": "https://www.twilio.com/docs/errors/50200", "status": 400}
My understanding was that we can provide our own identity when we want to add someone to a Channel. How can I 'register' the user (with an email) before adding them to the Channel?
EDIT - The code:
var _getRequestBaseUrl = function() {
return 'https://' +
process.env.TWILIO_ACCOUNT_SID + ':' +
process.env.TWILIO_AUTH_TOKEN + '#' +
TWILIO_BASE + 'Services/' +
process.env.TWILIO_IPM_SERVICE_SID + '/';
};
var addMemberToChannel = function(memberIdentity, channelId) {
var options = {
url: _getRequestBaseUrl() + 'Channels/' + channelId + '/Members',
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
form: {
Identity: memberIdentity,
},
};
request(options, function(error, response, body) {
if (error) {
// Getting the error here
}
// do stuff with response.
});
};
addMemberToChannel('test1#example.com', <validChannelId>);
Twilio developer evangelist here.
In order to add a user to be a member of a channel, you do indeed need to register them first. Check out the documentation for creating a user in IP Messaging.
With your code you'd need a function like:
var createUser = function(memberIdentity) {
var options = {
url: _getRequestBaseUrl() + 'Users',
method:'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
form: {
Identity: memberIdentity,
}
};
request(options, function(error, response, body) {
if (error) {
// User couldn't be created
}
// do stuff with user.
});
}
Could I also suggest you take a look at the Twilio helper library for Node.js. It handles the creation of URLs like you're doing for you. The code looks cleaner too, you can create a user with the helper library like this:
var accountSid = 'ACCOUNT_SID';
var authToken = 'AUTH_TOKEN';
var IpMessagingClient = require('twilio').IpMessagingClient;
var client = new IpMessagingClient(accountSid, authToken);
var service = client.services('SERVICE_SID');
service.users.create({
identity: 'IDENTITY'
}).then(function(response) {
console.log(response);
}).fail(function(error) {
console.log(error);
});
Let me know if this helps at all.

Making POST Requests in Backbone.js

I have a RESTful server, which accepts url encoded parameters.
In my case, making a post request to https:// my server:8443/test/auth
Set the request header as
Content-Type : application/x-www-form-urlencoded
and passing the parameters
username=myusername
password=mypassword
works and gives the desired response.
I want to achieve the same using Backbonejs. So, I have
Person = Backbone.Model.extend({
initialize: function() {
this.on('all', function(e) { console.log(this.get('name') + " event " + e );
});
},
urlRoot: "https:// my server:8443/test/authauth",
url : function(){
var base = this.urlRoot;
return base + ""
}
});
var person = new Person({ "username" : "myusername" , "password":"mypassword" });
person.save(null, {
beforeSend: function(xhr) {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}}
);
But, it says that no username and password attributes are not present. Waht is the correct way to pass the paramteres in url encoded form in Backbone.js
Thanks

X-CSRF-TOKEN validation failed in SAPUI5

I am calling a create service of SAP Net weaver Gateway from SAPUI5. I have written following code for getting CSRF but I am not able to get it. It asks me to enter the username and password as shown in the image.
Code:
function onSave()
{
useroDataModel = newsap.ui.model.odata.ODataModel("proxy/sap/opu/odata/sap/ZUI_GROUP1_CREATE");
empid = oTF2.getValue();
empname = oTF1.getValue();
empaddr = oTF.getValue();
empdoj = oDP.getValue();
uilogon();
useroDataModel.read("/zui_group1_createCollection(im_emp_id='"+empid+"')", null, null, true, fnSuccess, fnError);
useroDataModel.setHeaders({
"X-CSRF-Token": "Fetch" // auth
});
function fnSuccess(data,response)
{
//alert(response.headers['x-csrf-token']);
var header_xcsrf_token = response.headers['x-csrf-token'];
//alert(header_xcsrf_token);
var createrequestdata = {
im_emp_id : empid,
im_emp_name : empname(),
im_emp_addr : empaddr(),
im_emp_doj : empdoj()
};
useroDataModel.setHeaders({
"X-Requested-With": "XMLHttpRequest",
"Content-Type": "application/atom+xml",
"DataServiceVersion": "2.0",
"Accept": "application/atom+xml,application/atomsvc+xml,application/xml",
"X-CSRF-Token": header_xcsrf_token
});
useroDataModel.create("/zui_g2_createCollection", createrequestdata, null, fnS, fnE);
function fnS(response){
if(response.ex_status == "Entry Created.")
{
alert("Created.");
}
else
{
alert("Failed.");
}
}
function fnE(Error){
alert("error in create"+Error.message);
}
}
function fnError(oError)
{
alert("Error in read"+oError.message);
}
}
function uilogon()
{
var tok = "username" + ':' + "password";
var hash = btoa(tok);
auth = "Basic" + hash;
// alert(auth);
// Save to Local Storage
// $.sap.require("jquery.sap.storage");
// var UI5Storage = $.sap.storage(jQuery.sap.storage.Type.session);
// UI5Storage.remove("Auth");
// UI5Storage.put("Auth",auth);
useroDataModel.setHeaders({
//'Accept-Encoding': "gzip",
"Authorization" : auth});
// alert("dne");
}
I am able to fetch the CSRF-TOKEN in auth variable. But it asks me for following authentication in which asks me to enter the username and password of SAP NET WEAVER GATEWAY but if I enter the username and password through which I am logged in, it does not accept.
If you want to use your method of authentication you will need to authenticate prior to the ODataModel instantiation, you cant read the metadata let alone fetch a CSRF token unless authenticated, also you need to fetch the token prior to doing the POST.
Why not pass the username and password into the constructor of the ODataModel
var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl, bJSON, sUser, sPwd);
once authenticated if you are using binding functionality the CSRF security token will be read for you else if you want to use oModel.read you can do it manually
oModel.refreshSecurityToken()