How to send rich text emails with GmailApp? - google-apps-script

I’m trying to send a Google Doc, with all of its formatting, in an email.
function sendGoogleDocInEmail() {
var doc = DocumentApp.openById("example_Id");
var body = doc.getBody();
var text = body.getText();
GmailApp.sendEmail("emailaddress#gmail.com", "Hi", text);
This code works fine, but the email is sent as plain text.
I have descriptive hyperlink text pieces in the Google Doc, and they lose their hyperlinks when converted to plain text.
Is there any way I can keep all of the hypertext formatting when sending the email?
I’ve tried passing the body object to the method instead, but that just sends an email with DocumentBodySection in the body.
Thanks!

Trying using a combination of this script: https://stackoverflow.com/a/28503601/3520117
And then using the htmlBody parameter of the MailApp.sendEmail method.
Untested, but should work:
function emailGoogleDoc(){
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);
var email = person#domain.tld;
var subject = 'Subject line';
var body = "To view this email, please enable html in your email client.";
MailApp.sendEmail(
email, // recipient
subject, // subject
body, { // body
htmlBody: html // advanced options
}
);
}

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)

Sheets to Docs to Email

I have created a spreadsheet that contains quite a large amount of data.
The plan is to consolidate this data into a readable email to be sent out weekly, each specific row of data is its own email.
I tried going directly from sheets to email, but frankly it never quite looked right, plus the idea was to have a document template, where we could easily update the body without messing with code.
So I decided to write a email template in DOCS, set out a table, then have a script that copied the email template and updated the table with the row of data the script was looking at, then send it via email.
The code works great, but there is one little snag, the table never quite copies over to the email properly.
Below is are images of how the table is formatted in the email compared to the format in the template.
I just can not figure out how or why the format does not carry over.
I have also listed my code below, any help or advice on how I achieve the correct formatting would be appreciated.
UPDATE;
I have updated the question to show the code where we find the url of the document and convert to HTML,
var classArray=[];
//get html from Doc
var subject= row[30];
var forDriveScope = DriveApp.getStorageUsed(); //needed to get Drive Scope requested
var url = "https://docs.google.com/feeds/download/documents/export/Export?id="+newID+"&exportFormat=html";
var param = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions:true,
};
var html = UrlFetchApp.fetch(url,param).getContentText();
//docs uses css in the head, but gmail only takes it inline. need to move css inline.
//DOES NOT HANDLE HEADER CLASSES (eg h1, h2).
var headEnd = html.indexOf("</head>");
//get everything between <head> and </head>, remove quotes
var head = html.substring(html.indexOf("<head>")+6,headEnd).replace(/"/g,"");
//split on .c# with any positive integer amount of #s
var regex = /\.c\d{1,}/;
var classes = head.split(regex);
//get class info and put in an array index by class num. EG c4{size:small} will put "size:small" in classArray[4]
var totalLength = 0;
for(var i = 1; i < classes.length; i++){
//assume the first string (classes[0]) isn't a class definition
totalLength = totalLength + classes[i-1].length;
var cNum = head.substring(totalLength+2,head.indexOf("{",totalLength)); //totallength+2 chops off .c, so get what's between .c and {
totalLength = totalLength + 2 + cNum.length //add .c and the number of digits in the num
classArray[cNum] = classes[i].substring(1,classes[i].indexOf("}")); //put what's between .c#{ and } in classArray[#]
}
//now we have the class definitions, let's put it in the html
html = html.substring(headEnd+7,html.indexOf("</html>")); //get everything between <html> and </html>
var classMatch = /class=\"(c\d{1,} ){0,}(c\d{1,})\"/g
//matches class="c# c#..." where c#[space] occurs any number of times, even zero times, and c#[no space] occurs after it, exactly once
html = html.replace(classMatch,replacer); //replace class="c# c#..." with the definitions in classArray[#]
//make the e-mail!
GmailApp.sendEmail(row[31], subject, "HTML is not enabled in your email client. Sad face!", {
htmlBody: html,
});
function replacer(match){
var csOnly = match.substring(7,match.length-1); //class=" has 7 chars, remove the last "
var cs = csOnly.split(" "); //get each c#
var ret = "style=\""
for(var cCount = 0; cCount < cs.length; cCount++){
ret = ret + classArray[cs[cCount].substring(1)];
}
return ret+"\"";
}
})
}
The comments in the code says that Gmail can only use inline styling. That was true several years ago but currently Gmail allows to have a style tag inside a head tag. Considering this, the script could be much more simple that the one included in the question.
Below there is a script showing a sample that sends a Google Document content as the HTML body of an email message.
/**
* Get document as HTML
* Adapted from https://stackoverflow.com/a/28503601/1595451
*/
function getGoogleDocumentAsHTML(id) {
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();
return html;
}
/**
* Send the content of a Google Document as the HTML body of a email message
*/
function sendEmail(){
const url = /* add here the URL of your Google Document */;
const id = url.match(/[^\/]{44}/)[0];
const doc = getGoogleDocumentAsHTML(id);
const head = doc
.replace(/<meta[^>]+?>/g,'') // get rid of the meta tags
.match(/<head.+?<\/head>/)[0];
const body = doc.match(/<body[^>]+?>.+<\/body>/)[0];
const htmlBody = [head,body].join('\n');
MailApp.sendEmail({
to: /*add here the recipient email address */,
subject: /*add here the email subject */,
htmlBody: htmlBody
})
}
NOTE: You might want to clear the class of the body tag to avoid the margins set for it.

How to remove gridlines from the spreadsheet in google app script

I am trying to write a code in google app script that can mail me the spreadsheet and everything works well. Below is the code I am using.
function convSheetAndEmail(rng, email, subj)
{
var HTML = SheetConverter.convertRange2html(rng);
MailApp.sendEmail(email, subj, '', {htmlBody : HTML});
}
function doGet()
{
// or Specify a range like A1:D12, etc.
var dataRange = SpreadsheetApp.getActiveSpreadsheet().getDataRange()
var emailUser = 'xyz#gmail.com';
var subject = 'Test Email';
convSheetAndEmail(dataRange, emailUser, subject);
}
Now when I am receiving the mail from this script it looks like this
enter image description here
But I don't want to have these Gridlines in my mail. Please advice what I am missing.
Since your are using sheetConverter library. It returns an HTML code with border style element set to 1/1px. So you will have to explicitly replace all the occurrences of border tag in your HTML like so
function convSheetAndEmail(rng, email, subj)
{
var HTML = SheetConverter.convertRange2html(rng)
Logger.log(HTML)
HTML = HTML.replace(' border="1" ',' border="0" ')
HTML = HTML.replace(/border:1px/g,'border:0px')
Logger.log(HTML)
MailApp.sendEmail(email, subj, '', {htmlBody : HTML});
}
Reference:
String.replace()

Google App Script google doc to mail html

I am trying to send google doc content to email , but could not get it in html format, please help.
Mail is going through but it does not contain the font and colors.
Code Follows:
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();
var subject = "November 19 2015";
MailApp.sendEmail("xxxxxx#gmail.com", subject,"", {htmlBody:html, name:"Work Program", cc:"", replyTo:"xxxxx#gmail.com"});
}
Add this....
body { -webkit-print-color-adjust: exact; }
Reason for this solution is explained here

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;