Создание и отправка многоразовых писем с помощью React

Пару недель назад мне было поручено кодировать электронные письма. О, отлично… электронные письма. Я не хотел тратить следующие пару недель на кодирование таблиц по несколько часов каждый день. Должен был быть способ получше.

Моим спасителем стал response-html-email. Это позволяет нам, наконец, создавать многоразовые электронные письма на основе компонентов. Времена копирования и вставки гигантских кусков HTML в провайдеров услуг электронной почты (ESP) прошли. Просто введите свой компонент в renderEmail, и модуль его отрендерит.

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

Одна из лучших особенностей этого модуля - наличие валидатора. Когда мы хотим визуализировать наши компоненты, они проходят через валидатор, и если есть какие-либо ошибки или предупреждения, он позволяет нам узнать, для каких почтовых клиентов это предупреждение или сбой.

Предупреждения от компонента выше:

Особого ворса в нем нет. Он возвращает простую миниатюрную строку HTML.

<!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>

Есть еще две проблемы, которые нужно решить. Во-первых, у ESP, таких как MailChimp, есть свои собственные атрибуты HTML, такие как «mc: edit», которые определяют, как HTML отображается в графическом интерфейсе ESP. Во-вторых, копирование и вставка HTML требует много времени и подвержено человеческим ошибкам.

Что касается первой проблемы, поскольку эти атрибуты специфичны для ESP, мы не можем передавать их через наши компоненты. Поэтому я создал новый модуль Mailchimpify, чтобы решить эту проблему специально для MailChimp. Это мой первый модуль с открытым исходным кодом для электронной почты! Он преобразует любую строку HTML с атрибутами `data-mc-edit` в` mc: edit` Mailchimp.

Для второй проблемы - копирования и вставки HTML в ESP - нам нужно что-то для передачи наших писем в Mailchimp. Курьер спешит на помощь. Courier оптимизирует наш процесс электронной почты, отправляя настраиваемые динамические электронные письма с сервера: этот модуль интегрируется с любой платформой электронной почты и позволяет вам обходить графический интерфейс Mailchimp для отправки электронных писем.

Вы просто передаете ему объект своих шаблонов. Он работает независимо от того, выполняете ли вы рендеринг с сервера, компилируете локально для тестирования или отправляете электронное письмо напрямую пользователям.

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 it
init()
  .then(() => console.log(‘done sending campaign’))
  .catch((error) => console.log(error));

HTML визуализирован:

<!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>

В Mic мы часто отправляем нашим пользователям push-уведомления с последними новостями и специальными отчетами через настраиваемую push-систему управления контентом, которую мы называем PAM (менеджер push-уведомлений). В настоящее время мы отправляем эти уведомления пользователям нашего приложения для iOS и через веб-push, и хотели бы распространить их по электронной почте.

Отчасти проблема заключается в том, что не у всех есть iPhone или не у всех есть браузеры, чтобы получать эти push-уведомления. Если кто-то редактирует эти электронные письма, это также вызывает некоторые опасения: есть место для человеческих ошибок и отнимает много времени. Courier помогает нам решить эту проблему, интегрируясь с нашим менеджером push-уведомлений и позволяя доставлять настраиваемые электронные письма прямо нашим пользователям.

При создании этого модуля есть несколько уроков.

Создание электронных писем является (и теперь было) обрядом для новых инженеров Mic. У меня было видение изменить направление создания электронных писем. У вас тоже будут видения. Произведите впечатление с помощью этих видений.

Выбирайте, чтобы оказывать влияние на то, что вы делаете. Если вам кажется, что это «отстой», это прекрасное время, чтобы оказать влияние и изменить ситуацию в будущем. Сделайте так, чтобы это было меньше для вас и для следующего человека.

Наслаждайся этим. Серьезно, я просто хотел фейспалм (и, вероятно, так и сделал), когда мне сказали: «Ты собираешься потратить Х-время на электронные письма». Мне нужно было сделать это более приятным и разумным для себя. Ты тоже можешь.

Делать вклад. До создания Courier и погружения в электронную почту я всегда хотел внести свой вклад в открытый исходный код. Я смотрел репозитории для модулей, которые использовал, и это казалось слишком сложным. Что я мог бы даже внести? С чего мне начать? Все сводилось к простой функции, которая мне нужна в response-html-email. Мне нужно было передать атрибуты data-компонентам, чтобы преобразовать атрибуты данных Mailchimp.

Также огромное спасибо Максу Гудману (@chromakode). Он потрясающий и невероятно открытый для идей для response-html-email. Не стесняйтесь читать нашу дискуссию об этом и о том, что привело к моему первому запросу и модулю с открытым исходным кодом.