Apps Script to get the users signature - google-apps-script

I have created an apps script that will do a simple mail merge using contact details to create a new email draft. It works as expected, but I would like to use the current user's signature in the template.
Documentation on this is dated and incomplete. I created the code below from what I have found, but have had to make a total guess as to what it needs because I can't find the official documentation.
var params;
params = {method:"post",
contentType: "application/json",
headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions:true
};
var resp = UrlFetchApp.fetch("https://apps-apis.google.com/a/feeds/emailsettings/2.0/{domain}/me/signature", params);
var rCode = resp.getResponseCode();
var rText = resp.getContentText();
This is the response:
rCode = 400
rText = Invalid request URI
What is the correct request URI? Is there a new API for this?

Gmail signatures are now accessible from the gmail API. I added a one liner below to get the signature of the current user. I used list instead of get because a user may send email as a different user by default then their logged in account. So I list all accounts and filter out the default one.
https://developers.google.com/gmail/api/v1/reference/users/settings/sendAs
var signature = Gmail.Users.Settings.SendAs.list("me").sendAs.filter(function(account){if(account.isDefault){return true}})[0].signature;

Related

OAuth2 access token coming back as Null in Google App Script

Apologies if this is a silly question, I am very new to programming in general and I have never worked with OAuth before.
I am currently trying to build a Google App Script which interacts with an external service and authenticates using OAuth2.
I am having a lot of trouble with OAuth2... for starters, I'm not sure I am using the correct library for this. I am going off the one recommended by Google for ads script - https://developers.google.com/google-ads/scripts/docs/examples/oauth20-library
I know there is another popular one available in GitHub https://github.com/googleworkspace/apps-script-oauth2
I was not able to use it because everything comes out as 'is not a function', no matter how I add the library, manually or through the built-in feature.
I started building the API call, based on the first library and I had some partial success, I started getting back a 500 error message and I realized my accessToken is null.
function SHICall(){
var tokenUrl = "X/token";
const scriptProperties = PropertiesService.getScriptProperties();
var clientId = scriptProperties.getProperty('CLIENT_ID');
var clientSecret = scriptProperties.getProperty('SECRET');
var opt_scope = "CustomerAPI.Public";
// Access token is obtained and cached.
const authUrlFetch = OAuth2.withClientCredentials(tokenUrl, clientId, clientSecret, opt_scope);
const url = "X";
Logger.log(authUrlFetch);
var options = {
headers: { 'Content-Type': "application/json", 'Accept': "application/json"},
muteHttpExceptions: true,
method: "GET",
contentType: "application/json",
validateHttpsCertificates: false,
};
// Use access token in each request
const response = authUrlFetch.fetch(url, options);
// ... use response
Logger.log(response);
}
Any clue why the token is coming back as null? I based my API Call on google's documentation again https://developers.google.com/google-ads/scripts/docs/features/third-party-apis#oauth_2

Can Google Sites API still be authorized?

I tested it in the Google OAuth 2.0 Playground and it looked like I could return info from the site, but when I set up the OAuth2 code from Github, I can't seem to do a UrlFetchApp request as I get
the error returned code 403. Truncated server response: Not authorized to access this feed
I am not sure if this is because it is not enabled in the API console, but I can't find it there or under Advanced Google Services.
This is the section of code I am falling down at:
var service = getService();
if (service.hasAccess()) {
Logger.log("initial xml has access "service.hasAccess());
var headers = {
"Authorization": "Bearer " + service.getAccessToken()
};
var MyAttachmentsURL = 'https://sites.google.com/feeds/content/[DOMAIN]/[SITE NAME]?kind=attachment';
var response = UrlFetchApp.fetch(MyAttachmentsURL, headers);
};
The script from Github worked for me and I authorized when the message came up. This is what is in my scope tab:
7 OAuth Scopes required by the script:
https://sites.google.com/feeds
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/script.container.ui
https://www.googleapis.com/auth/script.external_request
https://www.googleapis.com/auth/script.scriptapp
https://www.googleapis.com/auth/spreadsheets
https://www.googleapis.com/auth/userinfo.email
According to the Protocol Guide's "Authorizing requests with OAuth 2.0" You must activate the Google Sites API in the API Console if you can see that option (Step 2).
The only other issue I can see is the requiring to specify a version as GData-Version: 1.4.
So your code would change to something like this:
var service = getService();
if (service.hasAccess()) {
Logger.log("initial xml has access "service.hasAccess());
var headers = {
"GData-Version": "1.4",
"Authorization": "Bearer " + service.getAccessToken()
};
var MyAttachmentsURL = 'https://sites.google.com/feeds/content/[DOMAIN]/[SITE NAME]?kind=attachment';
var response = UrlFetchApp.fetch(MyAttachmentsURL, headers);
};
As long as the scope is mentioned in the code, it doesn't need to be passed, so that wasn't the issue. This was one of many variations I had been trying and I blame missing the post method on it being the wee hours. This code works (for now).
var service = getService();
if (service.hasAccess()) {
Logger.log("initial xml has access "+service.hasAccess());
var headers = {
// "GData-Version" : "1.4",
"Authorization" : "Bearer "+service.token_.access_token
};
var params = {"headers": headers, 'method':'get', 'muteHttpExceptions':true};
var MyAttachmentsURL = 'https://sites.google.com/feeds/content/[DOMAIN]/[SITE NAME]?kind=attachment';
var response = UrlFetchApp.fetch(MyAttachmentsURL, params);
};
It appears that "GData-Version" : "1.4" is returned in the response header so is not needed in the request. What is needed is the access token and although all the other API's seem to be able to make use of .getAccessToken, I had to amend this to .token_.access_token - this may be just for Google Sites.
I appreciate those who had a look at this and thank you Chris for responding.

How to retrieve gmail signature with google apps script

I've created a script in google apps script which reads the contents of a google doc into a draft message in gmail. It doesn't, however, append the user's signature.
So my plan would be to retrieve the signature, and then append to the contents of the google doc, and then put into a draft message.
I see that there is information for retrieving a users gmail signature here: https://developers.google.com/admin-sdk/email-settings/#manage_signature_settings, but I am am having trouble trying to implement it in my existing script.
How should I proceed? (current script follows)
function doGet() {
createDraft()
return HtmlService.createHtmlOutput('<b>Your catering email template can now be found in your Drafts folder!</b>');
}
function createDraft() {
var forScope = GmailApp.getInboxUnreadCount(); // needed for auth scope
var doc = DocumentApp.openById('1fsRMxtLx3IBEYvmVy9W8uHLw3Uf2OIh4L7ZSxpkixbY');
var body = doc.getBody();
var mbody = body.getText();
var raw =
'Subject: Catering Proposal\r\n' +
'Content-Type: multipart/alternative; boundary=1234567890123456789012345678\r\n' + '\r\n' +
mbody + '\r\n' +
'--1234567890123456789012345678--\n';
var draftBody = Utilities.base64Encode(raw);
Logger.log(draftBody);
var params = {method:"post",
contentType: "application/json",
headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions:true,
payload:JSON.stringify({
"message": {
"raw": draftBody
}
})
};
var resp = UrlFetchApp.fetch("https://www.googleapis.com/gmail/v1/users/me/drafts", params);
Logger.log(resp.getContentText());
}
I greatly appreciate any help that can be provided!
The user signature is handled by a separate API, not by the Gmail API.
You need to add the scope for this first :
https://apps-apis.google.com/a/feeds/emailsettings/2.0/
and then use GET to retrieve the signature
domain =gmail.com, for example
user = my.user, or whatever
https://apps-apis.google.com/a/feeds/emailsettings/2.0/domain/user/signature
There is an easier way to do it now covered in this post:
Apps Script to get the users signature
Basically:
var signature = Gmail.Users.Settings.SendAs.list("me").sendAs.filter(function(account){if(account.isDefault){return true}})[0].signature;

UrlFetch from Google Sheet exportLink['application/pdf'] not returning PDF data

I create and send a periodic email as an update from a Google Sheet. For various client reasons this is done 3 ways, as a link to the Sheet, and as attachments (PDF and XLSX).
This was working 'til recently. The XSLX attachment still works, but the PDF is no longer sent as a response to a UrlFetch to the file.exportLinks('application/pdf') url. No matter what the request headers it always returns as Content-Type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Did something else undocumented change that I am missing here?
function exportAsPDF(spreadsheetId) {
spreadsheetId = spreadsheetId || 'SECRET_ID';
var file = Drive.Files.get(spreadsheetId),
url = file.exportLinks['application/pdf'];
url += '&format=pdf&size=7&fzr=true&portrait=true&fitw=true&gid=0&gridlines=false&printtitle=false&sheetnames=false&pagenum=UNDEFINED&attachment=true'
var token = ScriptApp.getOAuthToken(),
response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var headers = response.getAllHeaders(); // revealing content-type returned isn't pdf
var pdfBlob = response.getBlob().getAs('application/pdf');
var pdfString = pdfBlob.getDataAsString(); // this naturally throws an error
return response.getBlob(); // this returns to the send mail script
}
I'm able to get PDFs using the utility from Convert all sheets to PDF with Google Apps Script.
That working script modifies the spreadsheet's edit URL into an export URL, which looks like:
https://docs.google.com/spreadsheets/d/<%SS-ID%>/export?exportFormat=pdf...
The advanced Drive service gives an export URL formatted like:
https://docs.google.com/spreadsheets/export?id=<%SS-ID%>&exportFormat=pdf...
I'd expect the URL provided by exportLinks to be more reliable than the hack in the working script. Apparently, it's not.
This has been raised as Issue 5114. Star it to receive updates.

bad request with UrlFetchApp

Looking for some help connecting to this service and returning the xml.
Here are the instructions (from here):
The state of the inputs and relays can be monitored by sending a
request to port 80 (or port specified in setup) for the XML page
state.xml. The relays can be controlled by sending GET requests to the
same page on port 80 (or port specified in setup). This can be
demonstrated by entering commands into the URL line of a web browser.
Request the current state: http://"ip address"/state.xml
...
If the control password is enabled in the WebRelay-DualTM unit and
the state.xml page is requested through a browser, the browser will
prompt the user for the password. If the XML request is sent from
another application and not a browser, the html request will need to
contain the password encoded using the base 64 encoding scheme. The
html request header without the password looks like this:
GET /state.xml?relay1State=1&noReply=1 HTTP/1.1 (Ends with two \r\n)
The html request header with the password looks like this:
GET /state.xml?relay1State=1&noReply=1 HTTP/1.1(\r\n here)
Authorization: Basic bm9uZTp3ZWJyZWxheQ== (Ends with two \r\n)
where bm9uZTp3ZWJyZWxheQ== is the base 64 encoded version of the
user name and password none:webrelay
Code:
function webRelay(){
//working url http://75.65.130.27/state.xml
var url = 'http://75.65.130.27/';
var params = encodeURIComponent('state.xml');
Logger.log(params);
var headers = {
"Authorization" : "Basic" + Utilities.base64Encode('none:webrelay')
};
var options =
{
"method" : "get",
"headers" : headers
};
var state = UrlFetchApp.fetch(url+params, options);
Logger.log('1: '+state);
Logger.log(parse(state));
}
function parse(txt) {
var doc = Xml.parse(txt, true);
}
Any help is much appreciated.
There are a couple of coding errors that you can easily take care of:
In the Authorization header you need a space after "Basic".
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
urlFetchApp.fetch() returns an HTTP Response object, so you need to extract the contents for parsing.
var result = UrlFetchApp.fetch(url, options);
var state = result.getContentText();
You aren't returning anything from your parse() function.
You should check result.getResponseCode() after .fetch(), and handle errors before proceeding with parsing.
That said, I keep getting Bad request: http://75.65.130.27/state.xml errors, so something is still not right. This is an HTTP 400 response, and google's servers don't return anything to the script debugger to dig into it. You should check the username & password, although I'd expect a 401-Unauthorized response if they were wrong. I tried including a payload of relay1State=2, and got the same Bad request result. If you can capture the HTTP Request hitting your server, there may be a clue to what is malformed. This could also be the result of a firewall.
Once that's sorted, this tutorial should help with the XML Parsing.
Here's my edit of your code:
function webRelay(){
var url = 'http://75.65.130.27/state.xml';
var username = "none";
var password = "webrelay";
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
// Getting "bad request" here - check the username & password
var result = UrlFetchApp.fetch(url, options);
var state=result.getContentText();
// You should check state.getResponseCode()
Logger.log('1: '+state);
Logger.log(parse(state));
}
function parse(txt) {
var doc = Xml.parse(txt, true);
return doc; // Return results
}