title: Google Apps Script - Convert HTML with styling to PDF and attach to an email - Create a PDF blob from HTML
body: <p>I would like the HTML from a Google Apps Script form, to get two different styles,  one for the body of the email and another for the PDF file.</p>
  
  <p>Current code:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>function doGet(request) {
    return HtmlService.createTemplateFromFile('index')
        .evaluate();//not all caps but it has to match the name of the file and it doesn't - Change to PAGE
  }
  
  function include(filename) {
    return HtmlService.createHtmlOutputFromFile(filename)
        .getContent();
  }
  
  
  /****** SHEET ****/
  function userClicked(userInfo){
      var url = "https://docs.google.com/spreadsheets/your-sheet-ID";
      var ss = SpreadsheetApp.openByUrl(url);
      var ws = ss.getSheetByName("Data");
      ws.appendRow([userInfo.name, userInfo.email, userInfo.comment, new Date()]);
  
  }
  
  
  function submitData(form) {
    var subject='New Feedback';
    var body=Utilities.formatString('name: %s &lt;br /&gt;email: %s&lt;br /&gt;Comment: %s', form.name,form.email,form.comment);
    
  /*** FOR HTML EMAIL **/
  
      var htmlTemplate = HtmlService.createTemplateFromFile("PDF-page.html");
      htmlTemplate.name = form.name;
      htmlTemplate.email = form.email;
      var htmlBody = htmlTemplate.evaluate().getContent();
  
  /*** CREATE PDF ***/
    
    var folderId = "your-folder-ID"; // Please set the folder ID.  // Added
    var blob = Utilities.newBlob(htmlBody, MimeType.HTML, form.name).getAs(MimeType.PDF);  // Added - PDF from html email - coment line for serve PDF from document template 
    var file = DriveApp.getFolderById(folderId).createFile(blob);  // Added
  
  //****email****//  
    var aliases = GmailApp.getAliases()
     Logger.log(aliases); //returns the list of aliases you own
     Logger.log(aliases[0]); //returns the alias located at position 0 of the aliases array
  
    GmailApp.sendEmail('your-email@email.email','New registration from:', 'object', {'from': aliases[0],subject: subject, htmlBody: body, attachments: [blob]});  // Modified
    
    
    return Utilities.formatString('name: %s &lt;br /&gt;Email: %s&lt;br /&gt;Comment: %s&lt;br /&gt;PDF: &lt;a target="_blank" href="%s"&gt;see your PDF file&lt;/a&gt;', form.name,form.email,form.comment,file.getUrl());
  }</code></pre>
  </div>
  </div>
  </p>
  
  <p>For a more complete view of the application, refer to this other post of mine:</p>
  
  <p><a href="https://stackoverflow.com/questions/59654994/google-app-script-settimeout-function-problem">Google App Script setTimeout Function problem</a></p>
  
  <hr>
  
  <p>In the to two sections following</p>
  
  <p>it returns the Gmail basic style, through  <strong>var = body</strong></p>
  
  <ul>
  <li><p>Showing the fields edited in the form:</p>
  
  <p>name: example name</p>
  
  <p>email: example email</p>
  
  <p>comment: example comment</p></li>
  </ul>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var body=Utilities.formatString('name: %s &lt;br /&gt;email: %s&lt;br /&gt;Comment: %s', form.name,form.email,form.comment);
  
  /****************************************************************************/
  
  GmailApp.sendEmail('your-email@email.email','New registration from:', 'object', {'from': aliases[0],subject: subject, htmlBody: body, attachments: [blob]});</code></pre>
  </div>
  </div>
  </p>
  
  <p>while in the section following</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var htmlTemplate = HtmlService.createTemplateFromFile("PDF-page.html");
      htmlTemplate.name = form.name;
      htmlTemplate.email = form.email;
      var htmlBody = htmlTemplate.evaluate().getContent();
  
  /*** CREATE PDF ***/
    
    var folderId = "your-folder-ID"; // Please set the folder ID.  // Added
  
    var blob = Utilities.newBlob(htmlBody, MimeType.HTML, form.name).getAs(MimeType.PDF);</code></pre>
  </div>
  </div>
  </p>
  
  <p>and this file PDF-page.html</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;base target="_top"&gt; 
    &lt;/head&gt;
    &lt;body&gt;
      &lt;p&gt;Dear &lt;?= name ?&gt; &lt;?= email ?&gt;,&lt;/p&gt;
      &lt;p&gt;Thanks for your interest, we'll get back to you shortly&lt;/p&gt;
      &lt;p&gt;Kind Regards,&lt;br&gt;Web App&lt;/p&gt;
  
    &lt;/body&gt;
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>it returns the page style from the page "PDF-page.html", through var = htmlBody</p>
  
  <ul>
  <li><p>Showing the fields edited in the form:</p>
  
  <p>Dear example name example email</p>
  
  <p>Thanks for your interest, we'll get back to you shortly</p>
  
  <p>Kind Regards</p>
  
  <p>Web App</p></li>
  </ul>
  
  <p>I know I edit the script like this:</p>
  
  <p>from:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>GmailApp.sendEmail('your-email@email.email','New registration from:', 'object', {'from': aliases[0],subject: subject, htmlBody: body, attachments: [blob]});</code></pre>
  </div>
  </div>
  </p>
  
  <p>to:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>GmailApp.sendEmail('your-email@email.email','New registration from:', 'object', {'from': aliases[0],subject: subject, htmlBody: HtmlBody, attachments: [blob]});</code></pre>
  </div>
  </div>
  </p>
  
  <p>and enable the script to make the PDF file from the templates document as follows:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>//  PDF FROM DOCUMENT TEMPLATE //  
    var templateDocumentId = "your-document-ID"; // Please set the file ID of the template Google Document
    var docId = DriveApp.getFileById(templateDocumentId).makeCopy("temp").getId();
    var doc = DocumentApp.openById(docId);
    doc.getBody().replaceText("{{name}}", form.name).replaceText("{{email}}", form.email).replaceText("{{comment}}", form.comment); // Modified
    doc.saveAndClose();
    var blob = doc.getBlob().setName(form.name);
    DriveApp.getFileById(docId).setTrashed(true);
  
  
  //  var blob = Utilities.newBlob(htmlBody, MimeType.HTML, form.name).getAs(MimeType.PDF);</code></pre>
  </div>
  </div>
  </p>
  
  <p>I get the result.</p>
  
  <p>That is, I get separate control for building and formatting email / PDF</p>
  
  <blockquote>
    <p><strong>QUESTION:</strong></p>
  </blockquote>
  
  <p>So I wish I could control the style, formatting, and function separately</p>
  
  <p>GmailApp.sendEmail</p>
  
  <p>as an example: email-page.html</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;base target="_top"&gt; 
    &lt;/head&gt;
    &lt;body&gt;
      &lt;p&gt;Name: &lt;?= name ?&gt; &lt;?= email ?&gt;,&lt;/p&gt;
      &lt;p&gt;Email. &lt;?= email ?&gt;,&lt;/p&gt;
      &lt;p&gt;Comment&lt;?= comment ?&gt;,&lt;/p&gt;
      &lt;p&gt;This is email page&lt;/p&gt;
  
  
    &lt;/body&gt;
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>that for</p>
  
  <p>PDF-page.html (that I already have)</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;base target="_top"&gt; 
    &lt;/head&gt;
    &lt;body&gt;
      &lt;p&gt;Dear &lt;?= name ?&gt; &lt;?= email ?&gt;,&lt;/p&gt;
      &lt;p&gt;Thanks for your interest, we'll get back to you shortly&lt;/p&gt;
      &lt;p&gt;Kind Regards,&lt;br&gt;Web App&lt;/p&gt;
  
    &lt;/body&gt;
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>I hope I have clearly explained my problem, please ask me for further clarification.</p>
  
  <p>Thanks in advance for your attention.</p>
  
  <hr>
  
  <blockquote>
    <p><strong>Solution!</strong></p>
  </blockquote>
  
  <p>Well I found the solution to my problem and thought I'd share it below. In order to serve two different Html files, one to create the emal file in Html and the other the Html PDF file, I used 2 HtmlServices, rewritten my script as follows:</p>
  
  <pre><code>function doGet(request) {
    return HtmlService.createTemplateFromFile('index')
        .evaluate();//not all caps but it has to match the name of the file and it doesn't - Change to PAGE
  }
  
  function include(filename) {
    return HtmlService.createHtmlOutputFromFile(filename)
        .getContent();
  }
  
  
  
  function userClicked(userInfo){
      var url = "https://docs.google.com/spreadsheets/d/your-spreadsheet-ID";
      var ss = SpreadsheetApp.openByUrl(url);
      var ws = ss.getSheetByName("Data");
      ws.appendRow([userInfo.name, userInfo.email, userInfo.comment, new Date()]);
  
  }
  
  
  function submitData(form) {
    var subject='New Feedback';
    var body = Utilities.formatString('name: %s &lt;br /&gt;Email: %s&lt;br /&gt;Comment: %s', form.name,form.email,form.comment);
  
  /*** FOR HTML PDF **/
    var htmlTemplate = HtmlService.createTemplateFromFile("PDF-page.html");
      htmlTemplate.name = form.name;
      htmlTemplate.email = form.email;
      var pdf_html = htmlTemplate.evaluate().getContent();
  
  /*** FOR HTML EMAIL **/ 
    //image logo in email html from my google drive acount
    var ImageBlob = DriveApp
                        .getFileById('your-image-ID') //change from your image-ID google drive acount
                        .getBlob()
                        .setName("ImageBlob");    
    var htmlTemplate = HtmlService.createTemplateFromFile("EMAIL-page.html");
      htmlTemplate.name = form.name;
      htmlTemplate.email = form.email;
      var email_html = htmlTemplate.evaluate().getContent();
  
  
  /*** CREATE PDF ***/
  
    var folderId = "your-folder-ID"; // Please set the folder ID
    var blob = Utilities.newBlob(pdf_html, MimeType.HTML, form.name).getAs(MimeType.PDF); 
    var file = DriveApp.getFolderById(folderId).createFile(blob);
  
  //**** send email ****//  
    var aliases = GmailApp.getAliases()
     Logger.log(aliases); //returns the list of aliases you own
     Logger.log(aliases[0]); //returns the alias located at position 0 of the aliases array
     var userName = form.name;
    GmailApp.sendEmail('my-email@email.email','New Registration from:  ' +userName, '', {'from': aliases[0], htmlBody: email_html, inlineImages: {image: ImageBlob}, attachments: [blob]});
  
  
    return Utilities.formatString('name: %s &lt;br /&gt;Email: %s&lt;br /&gt;Comment: %s&lt;br /&gt;PDF: &lt;a target="_blank" href="%s"&gt;see your PDF file&lt;/a&gt;', form.name,form.email,form.comment,file.getUrl());
  }
  </code></pre>
  
  <p>to serve the two distinct Html pages I changed the script as follows:</p>
  
  <p>FROM</p>
  
  <pre><code>/*** FOR HTML EMAIL **/
  
      var htmlTemplate = HtmlService.createTemplateFromFile("PDF-page.html");
      htmlTemplate.name = form.name;
      htmlTemplate.email = form.email;
      var htmlBody = htmlTemplate.evaluate().getContent();
  </code></pre>
  
  <p>TO</p>
  
  <pre><code>/*** FOR HTML PDF **/
    var htmlTemplate = HtmlService.createTemplateFromFile("PDF-page.html");
      htmlTemplate.name = form.name;
      htmlTemplate.email = form.email;
      var pdf_html = htmlTemplate.evaluate().getContent();
  
  /*** FOR HTML EMAIL **/ 
    //image logo in email html from my google drive acount
    var ImageBlob = DriveApp
                        .getFileById('your-image-ID') //change from your image-ID google drive acount
                        .getBlob()
                        .setName("ImageBlob");    
    var htmlTemplate = HtmlService.createTemplateFromFile("EMAIL-page.html");
      htmlTemplate.name = form.name;
      htmlTemplate.email = form.email;
      var email_html = htmlTemplate.evaluate().getContent();
  </code></pre>
  
  <p>FROM</p>
  
  <pre><code>//**** send email ****//  
    var aliases = GmailApp.getAliases()
     Logger.log(aliases); //returns the list of aliases you own
     Logger.log(aliases[0]); //returns the alias located at position 0 of the aliases array
     var userName = form.name;
  GmailApp.sendEmail('your-email@email.email','New registration from:', 'object', {'from': aliases[0],subject: subject, htmlBody: body, attachments: [blob]});  // Modified
  </code></pre>
  
  <p>TO</p>
  
  <pre><code>//**** send email ****//  
    var aliases = GmailApp.getAliases()
     Logger.log(aliases); //returns the list of aliases you own
     Logger.log(aliases[0]); //returns the alias located at position 0 of the aliases array
     var userName = form.name;
    GmailApp.sendEmail('my-email@email.email','New Registration from:  ' +userName, '', {'from': aliases[0], htmlBody: email_html, inlineImages: {image: ImageBlob}, attachments: [blob]});
  </code></pre>
  
  <p>how to create the new HTML pages with their respective CSS style pages, here they are:</p>
  
  <p>file <strong>EMAIL-Page.html</strong></p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;base target="_top"&gt;
  &lt;?!= include("css-email");?&gt;
    &lt;/head&gt;
    &lt;body&gt;
  &lt;p class="image-logo"&gt;&lt;img src='cid:image' width="150" height="56"&gt;&lt;/p&gt;
     &lt;h2 class="title-email"&gt;EMAIL Template HTML,&lt;/h2&gt;
      &lt;p class="text-email"&gt;Dear &lt;?= name ?&gt; &lt;?= email ?&gt;,&lt;/p&gt;
      &lt;p class="text-email"&gt;Thanks for your interest, we'll get back to you shortly&lt;/p&gt;
      &lt;p class="text-email"&gt;Kind Regards,&lt;br&gt;Web App&lt;/p&gt;
  
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>file <strong>css-email-html</strong></p>
  
  <pre><code>&lt;style&gt;
  
  .title-email {
    text-left: center;
    margin-right: 550px;
    background-color: aliceblue;
  
  }
  
  
  .text-email {
    color: #3b9f04;
  }
  </code></pre>
  
  <p>file <strong>PDF-page.html</strong></p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;base target="_top"&gt;
  &lt;?!= include("css-pdf");?&gt;
    &lt;/head&gt;
    &lt;body&gt;
    &lt;p class="image-logo"&gt;&lt;img src='cid:image' width="150" height="56"&gt;&lt;/p&gt;
    &lt;h2 class="title-pdf"&gt;PDF Template HTML,&lt;/h2&gt;
      &lt;p class="text-pdf"&gt;Name: &lt;?= name ?&gt;&lt;/p&gt;
      &lt;p class="text-pdf"&gt;Email: &lt;?= email ?&gt;,&lt;/p&gt;
  &lt;table&gt;
    &lt;tr&gt;
      &lt;th&gt;Table not inclued in EMAIL Html file&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Field not inclued in EMAIL Html file&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
  
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>file <strong>css-pdf.html</strong></p>
  
  <pre><code>&lt;style&gt;
  
  .title-pdf {
    text-align: center;
    margin-right: 50px;
    background-color: antiquewhite;
  
  }
  
  
  .text-pdf {
    color: red;
  }
  
  table {
    border-collapse: collapse;
    padding: 5px
  }
  
  table, th, td {
    border: 1px solid black;
    padding: 8px;
  }
  
  
  &lt;/style&gt;
  </code></pre>
  
  <p>and this is the result:</p>
  
  <p><strong>sending email</strong></p>
  
  <p><a href="https://i.stack.imgur.com/fwpMw.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/fwpMw.png" alt="enter image description here"></a></p>
  
  <hr>
  
  <p><strong>the attached pdf file</strong></p>
  
  <p><a href="https://i.stack.imgur.com/NNPzf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/NNPzf.png" alt="enter image description here"></a></p>
  
  <hr>
  
  <p>Now I still have a problem, I can't see the "logo" image in the PDF file.
  If you want to help me in this, I will be able to.
  Thanks in advance.</p>