Create your email template with Angular Universal

Douglas Liu
Sohoffice
Published in
5 min readJan 7, 2019

If you happen to have an Angular application and wanted to create emails. Here’s a way to allow you to use the same frontend skills, share the same stylesheets and maybe some page components when creating emails.

Photo by Marius Christensen on Unsplash

The gotchas of emails

Emails are slightly different from browser pages. This is especially true when talking about framework like Angular, which uses a lot of javascripts. Most emails client, do not like javascripts. If you ever wanted your email to work with gmail, do not use javascript.

Email clients also do not like stylesheets, no matter it’s an <style> tag in the head, or an external stylesheet. There’re chances it won’t be loaded. The best strategy when creating emails is: embed the styles on element tag.

But it’s a very tedious and boring task if we do it manually.

This is why I wrote this article. I wanted to elaborate a workflow that allow you to continue developing with the already very familiar frontend framework, Angular, but also allow the emails to be displayed correctly on Gmail and other email clients.

Proposed workflow

Diagram generated by planetuml

I’ll discuss how in the below.

1. Create an sub application for emails

Technically this is not really necessary. You may be able to add email pages into your primary application. But creating a sub application is a clearer way to manage the codes IMHO. It’s easy to create sub application with angular cli.

ng generate application foo-email --routing

In this article we’ll continue to use ‘foo-email’ to refer to your email sub application.

2. Make the foo-email application universal

Just universalize the same you would do to your primary application, check this to see how.

In this article, we’ll use ‘foo-email-server’ to refer to the angular universalized email application.

3. Share stylesheets

This is optional, but I guess you most likely wanted it.

Modify your angular.json so that the primary styles are used by the foo-email application.

"foo-email": {
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"styles": [
"src/foo-web-theme.scss",
"src/styles.scss",
"projects/foo-email/src/styles.css"
],
...
}

You may be intrigued to share assets, unfortunately assets must exist under the respective project root.

4. Create some email templates

Just use any angular components to create email templates. There’re something that you should know, but I’ll discuss them later.

For the moment, we’ll create an email verification template in the location of /email/verification.

You can test the result with ng serve, just remember to use the right project.

ng serve --ssl --project foo-email

5. Install angular-universalize-email

This is a small command line utility to automate the above workflow in one go. Install it with npm.

npm install angular-universalize-email --save-dev

After installation, you should have an executable angular-universalize-email under node_modules/.bin/.

You may execute it explicitly as ./node_modules/.bin/angular-universalize-email or create script in package.json.

6. Create scripts in package.json

You’ll want to have the following 2 scripts in your package.json.

"scripts": {
...
"build:email": "ng build --extract-css --project foo-email && ng run foo-email:server",
"gen:email": "angular-universalize-email -a ./dist/foo-email -A ./dist/foo-email-server -o tmp '/email/verification'"
}

The build:email script will build your foo-email application. Please note the --extract-css flag. This is mandatory, otherwise angular will build the styles as a JS file. You may also use --prod flag, although it also enables the — extract-css flag, but I wouldn’t recommend you to do so. Production mode is significantly slower to build, thanks to tree shaking and other technology, the built JS will be much smaller.

But we’re not using those JS any way. So, please don’t use --prod flag, it’s not very useful in our scenario.

The above command will generate an email-verification.html file under tmpdirectory. Depending on your server technology, you may want to change to a different location or the filename. Please see the below for an example to generate for play-framework.

angular-universalize-email generates one URL for each invocation. If you have many templates, it may be wise to create a shell scripts to handle them all at once.

7. Build the emails

Use the below command to build the emails.

npm run build:email
npm run gen:email

Build for play framework

Play framework is a scala/java full-stack server framework. It integrates a lot of components that is handy for server-side development. Scala is a JVM language that enjoy cleaner API, syntax sugars and functional designs. The seamless integration of scala and java offers an attractive alternative to java developer. You can even develop your server application with half java and half scala.

In play-framework, emails are not very different from a server rendered html page. The template looks like HTML with some variable substitutions. However the biggest difference is, the templates will be compiled into a function (actually a java class under the hood). As a result, in the beginning of the template, we’ll have to declare the function signature.

For example, our email verification template may require the below parameters.

@(url: String)(implicit data: io.BasicEmailData)

Since the template will be compiled into java classes, the filename must follow java convention. (i.e. no special characters, such as - or /)

To address the above points, we’ll instruct angular-universalize-email to prepend the function signature and change the output filename.

angular-universalize-email \
-a ./dist/foo-email \
-A ./dist/foo-email-server \
-o ../my/directory/to/play/framework/templates \
-p '{camel}.scala.html' \
--prepend '@(url: String)(implicit data: io.BasicEmailData)' \
'/email/verification'

The above command will send the output to the specified directory where the email templates should exist for play-framework. It will also have one line prepended to the html. So the output will be similar to the below:

@(url: String)(implicit data: io.BasicEmailData)<html>
...

The -p flag allow us to specify the pattern of output filename. The URL used to generate the template (/email/verification in this case), will be converted using camel conversion and substitute into the pattern. The resulting filename would be emailVerification.scala.html.

Conclusion

Use the techniques discussed above, the email templates can be developed with angular. You can also spin up test angular server, so you can see the results in local browser before actually producing an email. The generation of emails template is automated, even for server side technology.

Best practices

1. Use CSS class name selector

For example, if you wanted to use mat-toolbar of angular material. Use the CSS selector as the below:

<div class="mat-toolbar"> ... </div>

The typically use of <mat-toolbar> will not be accepted by Gmail, the tag will be silently removed, so is the styles.

This is no longer required. angular-universalize-email now converts all non-standard tags into <div />

2. Add a hidden tag in the very beginning of the page

Gmail will use the first several sentences of your email as preview in the listing. However, we may have to add the logo, brand and other thing in the beginning of the email but do not want these to become the preview text.

Just add a hidden tag with whatever text you want to display before anything else.

Did you learn something new? If so please:

clap 👏 button below️ so more people can see this

--

--

Douglas Liu
Sohoffice

Problem solver. Found love in Scala, Java, Angular and more …