How to retrieve gmail signature with google apps script - 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;

Related

Sending Google Doc email template as html format on Email

I've google docs template with logo and some images plus some text instructions, and I want to send it over email exactly how it appear in Google Docs, I know how to send plain text from google docs but can't figure out how to send templates with images.
Here is the code I am using currently :-
var body = doc.getBody().getText();
var message = body;
var subject = "subject line";
MailApp.sendEmail (user.primaryEmail, subject, message)
Updated script as suggested by Tanaike :-
function getDocAsHtml(docId){
var doc = DocumentApp.getActiveDocument()
var url = "https://docs.google.com/feeds/download/documents/export/Export?exportFormat=html&id=" + doc.getId();
var html = UrlFetchApp.fetch(url, { headers: { authorization: "Bearer " + ScriptApp.getOAuthToken() } }).getContentText();
var body = doc.getBody().getText();
var message = body;
var subject = "subject line";
MailApp.sendEmail('abc#xyz.com', subject, message, { htmlBody: html });
}
I believe your goal is as follows.
You want to send an email as the HTML body of the Google Document.
In this case, how about the following modification? From your showing script, I suppose that doc is the object of Document.
Modified script:
var url = "https://docs.google.com/feeds/download/documents/export/Export?exportFormat=html&id=" + doc.getId();
var html = UrlFetchApp.fetch(url, { headers: { authorization: "Bearer " + ScriptApp.getOAuthToken() } }).getContentText();
var body = doc.getBody().getText();
var message = body;
var subject = "subject line";
MailApp.sendEmail(user.primaryEmail, subject, message, { htmlBody: html });
// DriveApp.getFiles(); // This is used for automatically detecting the scope of Drive API.
When this script is run, the Google Document of doc is sent as the HTML body.
Note:
In this case, the mail client cannot show the HTML body, the text body of message is shown.
References:
fetch(url, params)
sendEmail(recipient, subject, body, options)

Apps Script to get the users signature

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;

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.

Get Google Document as HTML

I had a wild idea that I could build a website blog for an unsophisticated user friend using Google Drive Documents to back it. I was able to create a contentService that compiles a list of documents. However, I can't see a way to convert the document to HTML. I know that Google can render documents in a web page, so I wondered if it was possible to get a rendered version for use in my content service.
Is this possible?
You can try this code :
function getGoogleDocumentAsHTML(){
var id = DocumentApp.getActiveDocument().getId() ;
var forDriveScope = DriveApp.getStorageUsed(); //needed to get Drive Scope requested
var url = "https://docs.google.com/feeds/download/documents/export/Export?id="+id+"&exportFormat=html";
var param = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions:true,
};
var html = UrlFetchApp.fetch(url,param).getContentText();
Logger.log(html);
}
Node.js Solution
Using the Google APIs Node.js Client
Here's how you can get a google doc as html using google drive's node.js client library.
// import googleapis npm package
var google = require('googleapis');
// variables
var fileId = '<google drive doc file id>',
accessToken = '<oauth access token>';
// oauth setup
var OAuth2 = google.auth.OAuth2,
OAuth2Client = new OAuth2();
// set oauth credentials
OAuth2Client.setCredentials({access_token: accessToken});
// google drive setup
var drive = google.drive({version: 'v3', auth: OAuth2Client});
// download file as text/html
var buffers = [];
drive.files.export(
{
fileId: fileId,
mimeType: 'text/html'
}
)
.on('error', function(err) {
// handle error
})
.on('data', function(data) {
buffers.push(data); // data is a buffer
})
.on('end', function() {
var buffer = Buffer.concat(buffers),
googleDocAsHtml = buffer.toString();
console.log(googleDocAsHtml);
});
Take a look at the Google Drive V3 download docs for more languages and options.
Google docs currently has a function to do this.
Just download to zip(.html) and you can have a zip archive with html & image (if inserted)
I know this is not solution based on code, but its working :)
There is no direct method in GAS to get an HTML version of a doc and this is quite an old enhancement request but the workaround described originally by Henrique Abreu works pretty well, I use it all the time...
The only annoying thing in the authorization process that needs to be called from the script editor which makes it uneasy to use in a shared application (with "script unable" users) but this only happens once ;).
There is also a Library created by Romain Vialard that makes things (a bit) easier... and adds a few other interesting functions.
Here is a little snipped for the new version of goole AOuth following the idea posted by Enrique:
function exportAsHTML(){
var forDriveScope = DriveApp.getStorageUsed(); //needed to get Drive Scope requested
var docID = DocumentApp.getActiveDocument().getId();
var url = "https://docs.google.com/feeds/download/documents/export/Export?id="+docID+"&exportFormat=html";
var param = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions:true,
};
var html = UrlFetchApp.fetch(url,param).getContentText();
return html;
}
and then use the usual mailApp:
function mailer(){
var docbody = exportAsHTML();
MailApp.sendEmail({
to: "email#mail.com",
subject: "document emailer",
htmlBody: docbody });
}
Hope the new workaround helps
JD
You may use the solution here
/**
* Converts a file to HTML. The Advanced Drive service must be enabled to use
* this function.
*/
function convertToHtml(fileId) {
var file = Drive.Files.get(fileId);
var htmlExportLink = file.exportLinks['text/html'];
if (!htmlExportLink) {
throw 'File cannot be converted to HTML.';
}
var oAuthToken = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(htmlExportLink, {
headers:{
'Authorization': 'Bearer ' + oAuthToken
},
muteHttpExceptions: true
});
if (!response.getResponseCode() == 200) {
throw 'Error converting to HTML: ' + response.getContentText();
}
return response.getContentText();
}
Pass as fileId, the id of the google doc and to enable advanced drive services follow the instructions here.
I've had this problem as well. The HTML that the Document HTML Export spits out is really ugly, so this was my solution:
/**
* Takes in a Google Doc ID, gets that doc in HTML format, cleans up the markup, and returns the resulting HTML string.
*
* #param {string} the id of the google doc
* #param {boolean} [useCaching] enable or disable caching. default true.
* #return {string} the doc's body in html format
*/
function getContent(id, useCaching) {
if (!id) {
throw "Please call this API with a valid Google Doc ID";
}
if (useCaching == null) {
useCaching = true;
}
if (typeof useCaching != "boolean") {
throw "If you're going to specify useCaching, it must be boolean.";
}
var cache = CacheService.getScriptCache();
var cached = cache.get(id); // see if we have a cached version of our parsed html
if (cached && useCaching) {
var html = cached;
Logger.log("Pulling doc html from cache...");
} else {
Logger.log("Grabbing and parsing fresh html from the doc...");
try {
var doc = DriveApp.getFileById(id);
} catch (err) {
throw "Please call this API with a valid Google Doc ID. " + err.message;
}
var docName = doc.getName();
var forDriveScope = DriveApp.getStorageUsed(); // needed to get Drive Scope requested in ScriptApp.getOAuthToken();
var url = "https://docs.google.com/feeds/download/documents/export/Export?id=" + id + "&exportFormat=html";
var param = {
method: "get",
headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions:true,
};
var html = UrlFetchApp.fetch(url, param).getContentText();
// nuke the whole head section, including the stylesheet and meta tag
html = html.replace(/<head>.*<\/head>/, '');
// remove almost all html attributes
html = html.replace(/ (id|class|style|start|colspan|rowspan)="[^"]*"/g, '');
// remove all of the spans, as well as the outer html and body
html = html.replace(/<(span|\/span|body|\/body|html|\/html)>/g, '');
// clearly the superior way of denoting line breaks
html = html.replace(/<br>/g, '<br />');
cache.put(id, html, 900) // cache doc contents for 15 minutes, in case we get a lot of requests
}
Logger.log(html);
return html;
}
https://gist.github.com/leoherzog/cc229d14a89e6327336177bb07ac2980
Perhaps this would work for you...
function doGet() {
var blob = DriveApp.getFileById('myFileId').getAsHTML();
return HtmlService.createHtmlOutput(blob);
}

Google apps script to email google spreadsheet excel version [duplicate]

This question already has answers here:
Google app scripts: email a spreadsheet as excel
(2 answers)
Closed 2 years ago.
I would like to write an apps script to email an excel version of my Google Spreadsheet. I know I can save the spreadsheet as an Excel file. I am not sure if I can use the script to email the excel version out as an attachment. How can this be done?
After an answer on another recent post (Thomas van Latum), I tried the suggested doc api and get an interesting result... here is the test code I used and that is working nicely except the file is in xlsx format, not in xls but this is not necessarily an issue these days :
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
function test(){
var id = 'spreadsheet_ID'
var url = 'https://docs.google.com/feeds/';
var doc = UrlFetchApp.fetch(url+'download/spreadsheets/Export?key='+id+'&exportFormat=xls',
googleOAuth_('docs',url)).getBlob()
DocsList.createFile(doc).rename('newfile.xls')
}
note : if you don't rename it, its default name is Export.xlsx , it might be more usefull to get its ID to use it later...
so the last line could be like this instead :
var xlsfileID = DocsList.createFile(doc).getId()
EDIT : to trigger the authorization process, try a small function like this, run it from the script editor
function autorise(){
// function to call to authorize googleOauth
var id=SpreadsheetApp.getActiveSpreadsheet().getId();
var url = 'https://docs.google.com/feeds/';
var doc = UrlFetchApp.fetch(url+'download/documents/Export?exportFormat=html&format=html&id='+id,
googleOAuth_('docs',url)).getContentText();
}
As I spent about four hours of playing Rumpelstiltskin because none of the typically very old code snippets for the old Spreadsheet versions and the old OAUTH you can find when googling "google docs script send excel attachment" or similar (i.e. you want to take an existing Spreadsheet, convert it to Excel format and send it as email attachment) actually worked, I finally found the solution.
To create the actual attachment content, neither the supposed res.getContent() nor res.getBlob() nor res.getBytes alone worked. These hints are misleading!
The only thing that works for me is response.getBlob().getContent()!
Whole code :
function sendCurrentDocAsEmail() {
var driveService = getDriveService();
var ssID = SpreadsheetApp.getActiveSpreadsheet().getId();
var sheetName = SpreadsheetApp.getActiveSpreadsheet().getName();
var email = "recipient#demo.com"
var subject = "Here be Subjects";
var body = "Don't even think about learning how to code. It's wasted time.";
var file = Drive.Files.get(ssID );
var url = file.exportLinks[MimeType.MICROSOFT_EXCEL];
var response = UrlFetchApp.fetch(url, {
headers: {
Authorization: 'Bearer ' + driveService.getAccessToken()
}
});
var attachments = [{
fileName:sheetName+".xlsx",
content: response.getBlob().getBytes(), // this single line has cost me hours!
mimeType:"application//xls",
headers: {
Authorization: 'Bearer ' + driveService.getAccessToken()
}
}];
MailApp.sendEmail(email,subject ,body, {attachments:attachments});
}
Where getDriveService() is a function from Google's "OAuth2 for Apps Script" readme on https://github.com/googlesamples/apps-script-oauth2
The latest working version is below. Based on this example, i.e. similar as in previous answer but uses Google Service Account which does not require a human going by link to receive a token. You have to install Oath library from Google, the instructions are pretty clear.
var PRIVATE_KEY = 'xxx'
var CLIENT_EMAIL = 'xxx';
var USER_EMAIL=Session.getActiveUser().getEmail()
function getOathService() {
return OAuth2.createService('GoogleDrive:' + USER_EMAIL)
// 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_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('https://www.googleapis.com/auth/drive');
}
function sendEmail() {
var oathService = getOathService();
var ssID = SpreadsheetApp.getActiveSpreadsheet().getId();
var file = Drive.Files.get(ssID );
var url = file.exportLinks[MimeType.MICROSOFT_EXCEL];
var file = UrlFetchApp.fetch(url, {
headers: {
Authorization: 'Bearer ' + oathService.getAccessToken()
}
});
var attachments = [{
fileName:'xxx.xls',//TODO DATE
content: file.getBlob().getBytes(),
mimeType:"application//xls",
headers: {
Authorization: 'Bearer ' + oathService.getAccessToken()
}
}];
MailApp.sendEmail('email#domain.com', 'xxx', 'Hi,\n\nPlease see the last data in attachment',{attachments:attachments});
}
The one that worked for me:
var AUTH_TOKEN = "Enter your OAuth_Token";
ssID = SpreadsheetApp.getActiveSpreadsheet().getId();
var url = "http://spreadsheets.google.com/feeds/download/spreadsheets/Export?key="+ ssID + "&exportFormat=xls";
//Add &gid=x at the end of above url if you only want a particular sheet
var auth = "AuthSub token=\"" + AUTH_TOKEN + "\"";
var res = UrlFetchApp.fetch(url, {headers: {Authorization: auth}});
var attachments = [{fileName:"<Filename>.xls", content: res.getContent(),mimeType:"application/vnd.ms-excel"}];
MailApp.sendEmail("<recipient's email id>", "<email subject>", "<email body>", {attachments: attachments});
Get OAuth documentation & you token from here https://developers.google.com/accounts/docs/OAuth2
Use the following snippet of code after modifying it to suit your needs
var file = DocsList.getFileById(FILE_ID);
var attachment = file.getAs('application/vnd.ms-excel');
MailApp.sendEmail("abcd#example.com", "Subject", " Body" , {"fileName": "Your_file_name" , "mimeType" : "application/vnd.ms-excel" , "content":attachment.getBytes() } );
Note that this code is not tested, so please feel free to fix an error or two that might pop up