Как стать автором
Обновить
0.3

Верстка писем *

Все, что сложнее plain text

Сначала показывать
Порог рейтинга

Верстаем письмо на React, чтобы оно корректно отображалось во всех почтовых клиентах

Чтобы свёрстанные письма хорошо выглядели на десктопе и мобильных, нужно знать, как почтовые клиенты поддерживают возможности CSS и HTML. И на практике это не всегда просто. Например, Gmail отбрасывает атрибут style целиком, если встречает в нём цвет, заданный как rgb. В итоге даже в 2025 году вёрстка писем нередко сводится к написанию таблиц и атрибутов наподобие align, valign, bgcolor и т.д.

Вдобавок, после отправки письмо нельзя поправить, как страницу на сайте, и это тоже добавляет сложности.

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

На примере отправки через сервис Yandex Postbox покажем, как это работает.

Начало работы. Установим библиотеку @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 создадим статический ключ доступа. Важно надёжно сохранить идентификатор и секретный ключ. После того как вы закроете окно, параметры секретного ключа станут недоступны.

Отправка письма. Ключи доступа можно передать в конструктор 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: { 
           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'
}

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

Теги:
+8
Комментарии0