0

I am using Google's HTML service to evaluate an HTML template and then sending the HTML it creates through Google's Mail App service as an e-mail. I have the following code to render the e-mail different for Microsoft Office clients:

<!--[if mso]><v:roundrect...v:roundrect><![end if]-->
<!--[if !mso]><td align='center'...</td><![endif]-->

My issue is that the HTML service evaluates the aforementioned code as commented out and the HTML that gets passed to the Mail App no longer has those lines of code in it.

I have been banging my head against the wall to figure out how to get Google's HTML service to not treat these as comments. Any thoughts?

Thanks!

2 Answers2

1

There is a round-about way to retain HTML comments after template evaluation, but it comes with its owns issues.

You first enclose the comments in your template in CDATA tags. See example below:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <![CDATA[<!-- This is a comment -->]]>
    <p>GET - Gmail Push Notification Endpoint</p>
  </body>
</html>

When evaluated you'll end up with the following:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    &lt;!-- This is a comment --&gt;
    <p>GET - Gmail Push Notification Endpoint</p>
  </body>
</html>

Notice that certain characters (the < and >) are encoded as html entities, so you need to convert these back somehow. Unfortunately, Javascript does not have a native way to do that, so you either have to write your own script to replace them or use an existing library. I do the later and leverage the he library. You can create a script file in your Apps Script project and drop that code in as a dependency or put it in it's own project and deploy it as a dedicated Apps Script library.

Now you can bring it all together as follows:

// create template
let template = HtmlService
    .createTemplateFromFile('template_with_comments_wrapped_in_CDATA_tags');

// add properties to template for evaluation
template.props = {...};

// get evaluated content as string
let evaluated = template
    .evaluate()
    .getContent();

// decode html entities
let decoded = he.decode(evaluated);

// return decoded as HtmlOutput
return HtmlService.createHtmlOutput().setContent(decoded); 

And there you go.

Enclosing content in a template with CDATA tags has a number of applications, it even allows you to use non-HTML content as templates, so you can use this technique to create templates for all sorts of content (JSON, RFC822, etc.). Its a good trick to have in your arsenal of tools.

TheAddonDepot
  • 8,408
  • 2
  • 20
  • 30
  • Thank you! I was going to see if I could use the XML Service to grab the document, insert the comment, and pass back to the HTML service. I went to Costo instead and came back to this wonderful solution! Not just a great solution for this problem, but as you pointed out, it has many potential use cases. Definitely something that should be in the bag of tricks for anyone leveraging App Script. – sempiternal1 Feb 12 '21 at 18:41
0

The reason why that is happening is because those are HTML comments indeed.

Check this reference to learn about how to comment in HTML.

To solve your problem, simply comment out your lines of code (i.e remove <!-- and -->):

[if mso]><v:roundrect...v:roundrect><![end if]
[if !mso]><td align='center'...</td><![end if]
Mateo Randwolf
  • 2,823
  • 1
  • 6
  • 17
  • Thanks for the response. Unfortunately, that won't work. It will render two buttons with the bracketed conditions treated as regular text. The [if] statements are Conditional Comments: https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/ms537512(v=vs.85)?redirectedfrom=MSDN This is related to: https://stackoverflow.com/questions/18254711/html-emails-fallback-for-mso-conditional Edit: I hit enter too soon. – sempiternal1 Feb 12 '21 at 14:35