Ian Jones
Ian Jones

Reputation: 1509

Send fully-formed HTML email

I'm trying to send a fully-formed and compliant HTML email via meteor, which should include the doctype and html tags:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

I've followed this solution: Using dynamic HTML templates in Meteor emails

Which works for the most part, but Meteor cannot handle the doctype and html, throwing this error:

While building the application:
email/client/templates/receipt.html:2: Unexpected Doctype
...l1-transitional.dtd"> <html xmlns="http:/...
^

I guess Meteor wants to wrap its own tags, but how do I override this?

Upvotes: 1

Views: 774

Answers (2)

Michel Floyd
Michel Floyd

Reputation: 20226

Although dynamic templates are one possible solution, SSR (Server-Side-Rendering) really makes email management easy. I've got my app setup so that the boilerplate headers come from one template whereas the body contents of the email come from a second one. This makes all my email templates really simple and allows me to centrally control the look and feel of all emails from my app:

In server/config.js I define:

Accounts.getTemplate = function(templatePath){ 
  return Assets.getText('email.html')+Assets.getText(templatePath)+"</body></html>";
};

Where email.html is the boilerplate template that includes things like the <!DOCTYPE html... preamble. Note that I'm appending "</body></html>" after the merge of the boilerplate template with the specific template so that every specific template doesn't need to close out the doc. It just makes the HTML in the specific template cleaner and the templates DRY. email.html and all my specific templates live in the /private subdirectory.

When I need to send an email I use SSR:

SSR.compileTemplate('myTemplateName',Accounts.getTemplate('myTemplateName.html'));
var html = SSR.render("myTemplateName",{ key1: value1, key2: value2, ... });
Email.send( {from: sender, to: recipient, subject: subject, html: html});

Upvotes: 1

Ian Jones
Ian Jones

Reputation: 1509

Meteor Blaze doesn't like rendering HTML or DOCTYPE, but you can trick it to render the opening and closing tags to wrap a template like this:

var dataContext = {
    htmlHead: '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">',
    htmlFoot: '</html>'
}

var html = Blaze.toHTMLWithData(Template.email, dataContext);

Notice the lack of a new line after the doctype, I found this was necessary to avoid a compilation error, although I can't verify this is a reproducible caveat.

And within your template just specify the variables with triple brackets:

{{{htmlHead}}}
...
{{{htmlFoot}}}

This produces a fully formed output ready for sending with Email.send

Credit to Meteor Hacks for a related solution which sparked this idea.

Upvotes: 3

Related Questions