Google Scripts API - autoUpdateForwarding Not Applying - google-apps-script

As Domain Admin for the company I work at we'd like to set the forwarding addresses of staff as they leave the company to ensure any important correspondence isn't missed.
I've used the Google Apps OAuth2 Library successfully so far, but come across a snag. The following code is meant to forward emails from the address apitest#example.com to newaddress#example.com .
function setupForwarding() {
var service = getOAuthService();
service.reset();
try {
if (service.hasAccess()) {
var header = {
Authorization: 'Bearer ' + service.getAccessToken(),
}
var url = "https://www.googleapis.com/gmail/v1/users/apitest#example.com/settings/autoForwarding";
var response = UrlFetchApp.fetch(url, {
headers: header,
method: 'put',
enabled: true,
emailAddress: 'newaddress#example.com',
disposition: 'trash'
});
Logger.log(response.getContentText());
}
} catch (e) {
Logger.log(e.message);
}
}
The access token provided appears to work with other queries provided by UrlFetchApp such as using it to return the currently authorised forwarding addresses recorded on the account (which does include newaddress#example.com) and doesn't report any access priviledge errors. The response returns only the following
{ "enabled" : false }
And does not apply any forwarding. Would someone be able to help me identify the problem? I feel I might be passing the parameters to the HTTP request incorrectly but I'm still learning my way around that system and no other questions I found seemed to help.
Ozzie

I worked this out and it was simpler than I thought; so sharing the answer here in case anyone has a similar issue.
var response = UrlFetchApp.fetch(url, {
headers: header,
method: 'put',
contentType : 'application/json',
payload: '{ "enabled" : "true" , "emailAddress" : "newaddress#example.com" , "disposition" : "trash" }'
});
Is the functional way to do this; the request was expecting a separate payload and declared content type both.

Related

create an invoice stripe using google app script

Hi I followed this documentation regarding on creating an invoice on stripe
it says here that The ID of the customer who will be billed.
so I created a test customer manually on stripe and now I tried this code
function testDataInvoices()
{
var url = "https://api.stripe.com/v1/invoices";
var params = {
method: "post",
headers: {Authorization: "Basic " + Utilities.base64Encode("sk_testXXXXX:")},
payload:
{
customer: "cus_JLKM93Pc6j2mxB",
}
};
var res = UrlFetchApp.fetch(url, params);
Logger.log(res.getContentText())
}
but I am getting this error
Exception: Request failed for https://api.stripe.com returned code 400. Truncated server response: {
"error": {
"code": "invoice_no_customer_line_items",
Can someone please enlighten me about this stripe I really just new to this API and their API is just only for node.js
#TRIED
I tried following this link
and change my code to this
function testDataInvoices()
{
var url = "https://api.stripe.com/v1/invoices";
var params = {
method: "post",
headers: {Authorization: "Basic " + Utilities.base64Encode("sk_test_XXXXXX:")},
payload:
{
"email": "paul.kevin#senren.page",
"payment_settings": 'pm_1FWS6ZClCIKljWvsVCvkdyWg',
"invoice_settings[default_payment_method]":'pm_1FWS6ZClCIKljWvsVCvkdyWg'
}
};
var res = UrlFetchApp.fetch(url, params);
Logger.log(res.getContentText())
}
and got this error
A few things:
I'm not familiar with Google App Scripts — are you sure it's safe to store a secret key in such a script and you don't need an actual backend server instead? That key has to be kept private since it can be used to do anything on your Stripe account.
In the first case, you get an error because to issue an Invoice, you have to first call /v1/invoiceitems to add some items to the customer. Then when you call /v1/invoices, which will pull those in to charge for them: https://stripe.com/docs/invoicing/integration#create-invoice-code
in the second case you get an error because those are not valid parameters for that endpoint(if you check the link you posted, those parameters are for /v1/customers, not /v1/invoices).
I'd suggest following https://stripe.com/docs/invoicing/integration .

Google Apps Script UrlFetchApp GET to a node.js endpoint results in an empty body

I am using Google Apps Script to make a UrlFetchApp call to a node.js API endpoint. I own both the Google Apps Script code and node.js code & endpoint, so I can watch what is happening.
When I use Postman, it works. But when I use GAS UrlFetchApp, it doesn't work, as req.body in node is empty { }. I even looked at the code that Postman creates for JavaScript Fetch and try to nearly duplicate it, except for things I know GAS' UrlFetchApp needs. I've done quite a few UrlFetchApp calls with GAS to various external endpoints. So, I'm not new, but can't figure this one out.
Here is my Google Apps Script code:
var url = 'https://xxxxxxxxxxx.azurewebsites.net/api/account';
var data = {
"email": address,
"apiKey": 'xxxxxxxxxxxxxxxxxxx'
}
var payLoadInfo = JSON.stringify(data);
var options = {
"method": "GET",
"headers": {'Content-Type': 'application/json'},
// 'Content-Type': 'application/json',
// "contentType": 'application/json',
redirect: 'follow',
"muteHttpExceptions": true,
"body": payLoadInfo,
// "payload": JSON.stringify(data)
// payload: payLoadInfo
};
var response = UrlFetchApp.fetch(url, options);
The commented out parts of "options" are several different ways I've tried to get it to work. I know in the past that I've usually used "payload" instead of "body" like I am this time (Postman suggested it). When I use "payload", it fails completely, not even getting to my node code. I also tried putting the apiKey in the header.
Here is the node.js API endpoint code:
router.get("/account", async (req, res) => {
var apiKey = process.env.API_KEY;
console.log('apiKey = ' + apiKey);
console.log('req.body = ' + JSON.stringify(req.body, null, 2));
console.log('req.body.apiKey = ' + req.body.apiKey);
if (req.body.apiKey != apiKey) {
console.log('apiKey is not equal');
res.status(401).send({ error: "You are not authorized." });
} else {
process the request...
}
When I use "payload" in "options" I get a 500, and the server code never executes.
When I use "body" in "options", I see the server code execute, but the console.log('req.body = ' + JSON.stringify(req.body, null, 2)), just comes back with an empty object {}, and then since req.body.apiKey != apiKey, it consoles "apiKey is not equal" and sends a 401. When using Postman, the req.body object consoles fine, showing the email & apiKey.
No matter what combinations of things I put into options, it fails either with 500 or 401. However, Postman works great with pretty much the same parameters, headers, etc.
Here is what Postman shows for the code:
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Cookie", "ARRAffinity=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ARRAffinitySameSite=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
var raw = JSON.stringify({"email":"xxxxxxxxxxxxxxxxx#gmail.com","apiKey":"xxxxxxxxxxxxxxxx"});
var requestOptions = {
method: 'GET',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
I even tried including the cookie and "redirect: follow", but none works.
What am I missing?
I got it to work, thanks to help from #Tanaike (see comments above).
It seems that unlike normal "fetch" in node.js, URLFetchApp in Google Apps Script will not send a body along with a GET.
I still used GET, but changed to sending the param in the URL and the apiKey in the header.

Apps Script - UrlFetchApp.fetch {url, method: "GET"} to a gzip gets failed with code 406

I'm on a multi months quest here. Any help would be much appreciated!
I'm trying to connect via API on App Store Connect using UrlFetchApp.fetch(). After having struggled in the desert to generate the correct JWT for authentification on GAS, I now face harsh reality: the server answer (content-type and content-encoding) is not JSON but GZIP.
Code 406 message:
"Truncated server response: The provided Accept header is not supported for this request. Requested: application/json Allowed: application/a-gzip"
Is there a way to still get access to the file?
Here is the part of the code doing the call only (JWT signature code for authentification is above -> "sJWT")
var url = "https://api.appstoreconnect.apple.com/v1/financeReports?filter[regionCode]=ZZ&filter[reportDate]=2019-11&filter[reportType]=FINANCIAL&filter[vendorNumber]=xxx"
var response = UrlFetchApp.fetch(url, { method : "GET", headers : { "Authorization" : "Bearer "+sJWT }});
Many thanks!
How about this answer? Please think of this as just one of several possible answers.
Modification points:
When I saw the official document, it is required to use application/a-gzip for Accept in the request headers.
And also, in this case, the response returns the content of gzip. So it is required to decompress the content.
When above points are reflected to your script, how about the following modification?
Modified script:
var url = "https://api.appstoreconnect.apple.com/v1/financeReports?filter[regionCode]=ZZ&filter[reportDate]=2019-11&filter[reportType]=FINANCIAL&filter[vendorNumber]=xxx"
var response = UrlFetchApp.fetch(url, {
method: "GET",
headers: {
"Authorization": "Bearer " + sJWT,
"Accept": "application/a-gzip" // Added
}
});
var res = Utilities.ungzip(response.getBlob()); // Added
Note:
Above modified script supposes that the values of your URL and sJWT are correct for using the API.
References:
Download Finance Reports
fetch(url, params)
ungzip(blob)
406 Not Acceptable
Unfortunately, I cannot test above script. I apologize for this. So if above modified script didn't resolve your issue, I apologize.
Try changing the blob content type to "application/x-gzip":
var url = "https://api.appstoreconnect.apple.com/v1/financeReports?filter[regionCode]=ZZ&filter[reportDate]=2019-11&filter[reportType]=FINANCIAL&filter[vendorNumber]=xxx"
var response = UrlFetchApp.fetch(url, {
method: "GET",
headers: {
"Authorization": "Bearer " + sJWT,
"Accept": "application/a-gzip"
}
});
var res = Utilities.ungzip(response.getBlob().setContentType("application/x-gzip")); // Changed

Easy way to Post HTTPS JSON data (header+body) using Node.js

After reading multiple internet posts related to "JSON POST commands" in NodeJS I'm now totally lost! Have tried to create an easy script to send data to a device Restful API interface using https. Without any luck...
JSON string needs to contain: a Header incl. (Basic)Auth Token & Body
content something similar like:
'{"address":address,"address6":"","comment":"","duids":[],"hostnames":[],"interface":""};
Hoping that someone has a good example available or can point me into right direction again.
You can use in-built module https to make a REST API call, the request signature is as follows:
https.request(url[, options][, callback])
In your case, you can try following code:
var options = {
host: 'host-name',
port: 443,
path: 'api-path',
method: 'POST',
// authentication headers
headers: {
'Authorization': 'Basic ' + new Buffer(username + ':' + passw).toString('base64')
}
};
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
I had the exact same issue just few days ago, and I've ended up creating a super tiny module called json-post.
const jsonPOST = require('json-post');
// or import jsonPOST from 'json-post'
jsonPOST(
'https://whatever:5000/seriously',
// your JSON data as object
{hello: 'world'},
// optionally any extra needed header
{'Authorization': 'Basic ' +
new Buffer(username + ':' + passw).toString('base64')}
).then(
console.info,
console.error
);
The dance is similar to the one shown in the previous reply but it's simplified in various ways. It works well for GitHub OAuth and others services too.
I always use request library whenever I need to do HTTP request in nodejs.
var request = require('request');
request({
method: 'POST',
uri: 'http://myuri.com',
headers: {
'Content-Type' : 'application/json',
'AnotherHeader' : 'anotherValue'
},
json: myjsonobj
}, (err, response, body) => {
// handler here
})
there are other ways of making the request as well like request.post() refer here

Correct syntax for Google API PATCH request using UrlFetchApp for HTTPS Request

I'm trying to use UrlFetchApp.fetch(url) method in Apps Script to PATCH a groups resource using the Google Groups Settings API.
The code below allows me to GET the groups properties, but I'm unable to figure out the syntax for a PATCH request.
function doSomething (accessToken) {
var options = {
method: "GET",
headers: {
authorization: "Bearer " + accessToken
},
};
var result = UrlFetchApp.fetch("https://www.googleapis.com/groups/v1/groups/test_group_5#student.vis.ac.at", options);
return HtmlService.createHtmlOutput (result.getContentText());
}
A PATCH request needs a Header Override. You actually need to use a PUT request, and then override it to a PATCH request.
var payload = "{\"" + PropertyOne + "\":\"" + "Proptery Value" + "\"}";
Logger.log('payload: ' + payload);
var options = {"method" : "put", "headers": {"X-HTTP-Method-Override": "PATCH"}, "payload" : payload};
if (payload.length > 2) {
UrlFetchApp.fetch("https://www.googleapis.com/groups/v1/groups/test_group_5#student.vis.ac.at", options );
};
The code above won't be exactly what you want, and might not be error free, but the structure of it should be what you need. I'm sure the payload isn't configured correctly, because I don't know what the format is. It looks like the documentation calls it Patch body with an object.
Google Documentation - Group Settings API Patch
Key words: "Apps Script", patch