Roilan Salinas
Mic Product Blog
Published in
5 min readMay 11, 2016

--

Creating and Sending Reusable Emails with React

A couple weeks ago, I was tasked with coding emails. Oh, great… emails. I didn’t want to spend the next couple weeks coding tables for hours every day. There had to be a better way.

My savior was react-html-email. It allows us to finally make reusable, component-based emails. The days of copying and pasting giant chunks of HTML into email service providers (ESPs) are over. Just enter your component inside `renderEmail` and the module will render it out.

import React from 'react';
import { Email, Item, A, renderEmail } from 'react-html-email';
const InlineLink = () => (
<Email title='link'>
<Item>
<A style={{ paddingLeft: 10 }}>Click me!</A>
</Item>
</Email>
);
renderEmail(<InlineLink />); // minified HTML string

One of best things about this module is that it has a validator. When we want to render our components, they go through the validator and if there are any errors or warnings, it lets us know which email clients it’s warning or failing for.

Warnings from the component above:

It has no special fluff. It returns a simple minified HTML string.

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html><head><meta http-equiv=”Content-Type” content=”text/html; charset=utf-8"/><meta name=”viewport” content=”width=device-width, initial-scale=1.0"/><title>link</title></head><body style=”width:100%;margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;”><table width=”100%” height=”100%” cellpadding=”0" cellspacing=”0"><tbody><tr><td><table width=”600" cellpadding=”0" cellspacing=”0"><tbody><tr><td><a target=”_blank” style=”text-decoration:underline;padding-left:10px;”>Click me!</a></td></tr></tbody></table></td></tr></tbody></table></body></html>

There are two more issues to deal with. First, ESPs like MailChimp have their own HTML attributes like “mc:edit” that govern how the HTML is rendered in that ESP’s GUI. Second, copying and pasting HTML is time consuming and prone to human error.

For the first problem, since these attributes are ESP-specific, we can’t pass them through our components. So I created a new module, Mailchimpify, to solve that problem for MailChimp specifically. It’s my first open source module around emails! It transforms any HTML string with `data-mc-edit` attributes to Mailchimp’s `mc:edit`.

For the second problem — copying and pasting HTML into an ESP — we need something to carry our emails to Mailchimp. Courier to the rescue. Courier streamlines our email process by sending custom, dynamic emails from the server: This module integrates with any email platform and allows you to bypass Mailchimp’s GUI to send emails.

You just pass it an object of your templates. It works whether you’re rendering from the server, compiling locally to test or sending email directly to users.

import courier from 'courier-js';
import React from 'react';
import { Email, Item, Span } from 'react-html-email';
const styles = {
text: {
paddingLeft: 10
}
};
const MyLinkComponent = ({ href }) => (
<Email title='link'>
<Item>
<Span data-mc-edit="article_content" style={styles.text}>
<A href={href}>We're hiring!</A>
</Span>
</Item>
</Email>
);
const allTemplates = {
myTemplate: {
template: MyLinkComponent,
fileName: 'linkcomponent'
}
};
const templateProps = {
href: 'http://mic.com/jobs'
};

const { render, compile, mailchimp } = courier({ allTemplates });
const mailchimpConfig = {
key: 'somekey',
datacenter: 'dc'
};
const mailchimpOpts = {
campaign: { }, // Mailchimp campaign details
templateId: '', // Mailchimp template id
templateData: {
name: 'My Link Component Template', // template name on Mailchimp
html: render('myTemplate', templateProps) // html string from our template
}
};
// render is a wrapper around `renderEmail` with provides Mailchimpify and pretty HTML
render('myTemplate', templateProps); // renders html string from 'myTemplate'’s template with your template props.
compile('myTemplate', templateProps, __dirname); // creates a `linkcomponent.html` file from your component on the current directory.const { init } = mailchimp(mailchimpConfig, mailchimpOpts);// updates Mailchimp template, creates new campaign, updates campaign content and sends itinit()
.then(() => console.log(‘done sending campaign’))
.catch((error) => console.log(error));

HTML rendered:

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

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"
/>
<title>link</title>
</head>

<body style="width:100%;margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;">
<table width="100%" height="100%" cellpadding="0" cellspacing="0" align="left"
valign="top">
<tbody>
<tr>
<td align="center" valign="top">
<table width="600" align="center" cellpadding="0" cellspacing="0" valign="top">
<tbody>
<tr>
<td><span mc:edit="article_content" style="font-family:sans-serif;font-size:14px;line-height:14px;color:#000;padding-left:10px;"><a href="http://mic.com/jobs" target="_blank" style="text-decoration:underline;">We&#x27;re hiring!</a></span>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</body>

</html>

At Mic, we often send push notifications to our users with breaking news and special reports through a custom push CMS we call PAM (push alert manager). We currently send these notifications to our iOS app users and via web push, and wanted to syndicate them to email.

Part of the issue is not everyone has an iPhone or is in front of their browsers to get those push notifications. Having someone edit these emails also raises some concerns: room for human error and time consuming. Courier helps us solve this issue by integrating with our push alert manager and allowing us delivering custom emails straight to our users.

While creating this module, there are a few learnings.

Creating emails is (and now was) a rite of passage for new engineers at Mic. I had a vision to change the direction of how we created emails. You’ll have visions too. Make an impact with those visions.

Choose to create an impact on whatever you do. If you feel like it “sucks”, that’s a great time to make an impact and change it going forward. Make it suck less for you and the next person.

Enjoy it. Seriously, I just wanted to facepalm (and probably did) when I was told “you’re going to spend X time doing emails”. I had to make it more enjoyable and sane for myself. You can too.

Contribute. Prior to creating Courier and diving into emails, I always wanted to contribute to open source. I would look at repos for modules I’ve used and it seemed way too complicated. What could I even contribute? Where do I start? It came down to a simple feature I needed in react-html-email. I needed to pass `data-` attributes down the components to transform the Mailchimp data attributes.

Also, huge shoutout to Max Goodman (@chromakode). He’s awesome and incredibly open to ideas for react-html-email. Feel free to read our discussion around this and what lead to my first open source pull request and module.

--

--