Перейти к основному содержимому

Верстка писем с использованием React

· 3 мин. чтения

React Email

Сверстать письмо хорошо, так чтобы оно корректно отображалось во всех почтовых клиентах, на десктопе и мобильных устройствах, не так просто.

Для надо знать нюансы того как почтовые клиенты возможности CSS и HTML. Чтобы не выяснять это на практике, можно пользоваться сайтом Can I email, где можно посмотреть поддержку различных тегов и атрибутов в различных почтовых клиентах. Вот, например, Gmail отбрасывает аттрибут style целиком, если встречает в нем цвет заданный как rgb.

В итоге даже в 2025 году верстка писем сводится к использованию таблиц и аттрибутов align, valign, bgcolor и т.д.

Ну а еще отправив письмо, вы не можете его поправить, как страницу на сайте.

Поэтому я оценил библиотеку React Email, которая позволяет создавать письма с использованием React. Она предоставляет компоненты, которые генерируют HTML и CSS, корректно отображающиеся во всех почтовых клиентах. Письмо можно посмотреть в браузере и отправить на почту. Да, под капотом все равно используются таблицы, но зато вам не придется их писать руками, а можно использовать более высокоуровневые абстракции.

Установка

Для начала установите библиотеку @react-email/components и клиент для работы с почтовым сервисом AWS SESv2, потому что Postbox поддерживает именно эту версию клиента.

npm install @aws-sdk/client-sesv2 @react-email/components

Создание письма

Создайте компонент, который будет генерировать письмо. Например, так:

email.tsx
import * as React from 'react';
import { Button, Html } from '@react-email/components';

export function Email(props) {
const { url } = props;

return (
<Html lang="en">
<Button href={url}>Click me</Button>
</Html>
);
}

Больше компонентов можно посмотреть в документации.

Создание сервисного аккаунта

  1. Создайте сервисный аккаунт в том же каталоге, в котором находится адрес. Если вы создадите сервисный аккаунт и адрес в разных каталогах, при попытке отправить письмо возникнет ошибка.
  2. Назначьте сервисному аккаунту роль postbox.sender.
  3. Для отправки письма с помощью SDK создайте статический ключ доступа. Надежно сохраните идентификатор и секретный ключ. После того как вы закроете окно, параметры секретного ключа станут недоступны.

Отправка письма

Для отправки письма используйте Postbox. Он позволяет отправлять письма, созданные с помощью React Email, через AWS SESv2 SDK.

Ключи доступа можно передать в конструктор SESv2Client явно, как показано ниже, указать их в переменных окружения или использовать конфигурацию AWS CLI.

import { render } from '@react-email/components';
import type { SendEmailCommandInput } from '@aws-sdk/client-sesv2';
import { SendEmailCommand, SESv2Client } from '@aws-sdk/client-sesv2';
import { Email } from './email';
import React from 'react'


const sesClient = new SESv2Client({
region: 'ru-central1',
endpoint: 'https://postbox.cloud.yandex.net',
});

const emailHtml = await render(<Email url="https://example.com"/>);
const emailText = await render(<Email url="https://example.com"/>, {
pretty: true,
plainText: true,
});

const email: SendEmailCommandInput = {
Content: {
Simple: {
Headers: [
{
Name: 'List-Unsubscribe',
Value: `<https://example.com/unsubscribe/subscriptionId>`,
},
{
Name: 'List-Unsubscribe-Post',
Value: 'List-Unsubscribe=One-Click',
}
],
Body: {
Html: {
Data: emailHtml,
},
Text: {
Data: emailText,
},
},
Subject: {
Data: 'Тестовое письмо',
},
},
},
Destination: {
ToAddresses: [
'bob@example.com'
],
},
FromEmailAddress: 'Alice <alice@example.com>',
}

const command = new SendEmailCommand(email);

const result = await sesClient.send(command);
console.log(result);

Чтобы удобно запускать скрипт установите tsx loader:

npm install --save-dev tsx

Теперь запустите скрипт, передав в переменные окружения ключи сервисного аккаунта:

AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... node --import @nodejs-loaders/tsx index.tsx

В консоли вы увидите ответ от Postbox. Если письмо отправлено успешно, то в ответе будет MessageId.

{
'$metadata': {
httpStatusCode: 200,
requestId: undefined,
extendedRequestId: undefined,
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
},
MessageId: 'D8BT2CX3IDK2.2HZQ4CE0E8CRL@ingress1-sas'
}

Если вы хотите отправить несколько писем в цикле, то рекомендую добавить в код задержку между отправками, чтобы не превысить квоту на скорость отправки писем.