Обновлено 2026-10-08

Как отправлять почту из Node.js через Nodemailer и SMTP

Чтобы отправлять почту из Node.js через Nodemailer, вызовите nodemailer.createTransport с host smtp.bulko.io, port 587, secure: false и auth.user и auth.pass из переменных окружения; Nodemailer сам включит шифрование через STARTTLS. secure: true ставьте только для порта 465.

Серверsmtp.bulko.io
Порт587 · 465 · 2525
ШифрованиеSTARTTLS · SSL
Логин и парольиз кабинета

Что указать в Nodemailer

ПолеЗначение
hostsmtp.bulko.io
port587 (или 2525 при блокировке; 465 вместе с secure: true)
securefalse для 587 и 2525, true только для 465
requireTLStrue (необязательно, запрещает отправку без STARTTLS)
auth.userprocess.env.SMTP_USERNAME (вида smtp_xxxxxxxxxxxxxxxx)
auth.passprocess.env.SMTP_PASSWORD
fromАдрес на вашем домене, например "Your App" <[email protected]>

Настройка по шагам

  1. Купите SMTP-пакет на странице Bulko SMTP Relay и скопируйте логин и пароль в разделе Dashboard -> SMTP Access.
  2. Установите библиотеку: npm install nodemailer. Она подключается и через import nodemailer from "nodemailer" (ESM), и через require("nodemailer") (CommonJS).
  3. Храните доступы в переменных окружения SMTP_USERNAME и SMTP_PASSWORD (в менеджере процессов, контейнере или в файле .env, который подключается через node --env-file=.env).
  4. Создайте один transporter с host: "smtp.bulko.io", port: 587, secure: false и объектом auth. Используйте его повторно, а не создавайте новый на каждое письмо.
  5. Про secure: true означает TLS с первого байта и подходит только для порта 465. При false Nodemailer подключается без шифрования и поднимает TLS через STARTTLS, если сервер его предлагает. Добавьте requireTLS: true, чтобы сделать это обязательным.
  6. В from укажите адрес на своём домене. Для выровненных SPF, DKIM и DMARC подтвердите домен в разделе Sending Domains личного кабинета Bulko.
  7. Вызовите await transporter.verify() при старте, чтобы сразу поймать ошибку порта или пароля, а письма отправляйте через await transporter.sendMail({...}).

Если хостинг блокирует исходящие 587 и 465 (так делают некоторые облачные платформы), используйте port: 2525 с тем же secure: false. Разница между портами описана в статье о SMTP-портах.

send-test.mjs

// send-test.mjs  (npm install nodemailer)
import nodemailer from "nodemailer";

const transporter = nodemailer.createTransport({
  host: "smtp.bulko.io",
  port: 587,
  secure: false,      // false для 587 и 2525 (STARTTLS), true только для 465
  requireTLS: true,   // ошибка вместо отправки без TLS
  auth: {
    user: process.env.SMTP_USERNAME,
    pass: process.env.SMTP_PASSWORD,
  },
});

// Порт 465 (неявный TLS):
// const transporter = nodemailer.createTransport({
//   host: "smtp.bulko.io",
//   port: 465,
//   secure: true,
//   auth: { user: process.env.SMTP_USERNAME, pass: process.env.SMTP_PASSWORD },
// });

try {
  await transporter.verify(); // проверяет DNS, TLS и логин без отправки письма
  const info = await transporter.sendMail({
    from: '"Your App" <[email protected]>',
    to: "[email protected]",
    subject: "Nodemailer SMTP test",
    text: "It works.",
    html: "<p>It works.</p>",
  });
  console.log("Sent:", info.messageId, info.response);
} catch (err) {
  console.error("SMTP error:", err.responseCode, err.message);
  process.exitCode = 1;
}

Проверка

Запустите SMTP_USERNAME=smtp_xxx SMTP_PASSWORD=yourpass node send-test.mjs, указав в скрипте реальный адрес получателя. При успехе скрипт выведет messageId и response, начинающийся с 250: релей принял письмо. Проверьте ящик через минуту-две.

Если verify() падает, у ошибки будет code вроде EAUTH, ETIMEDOUT или ESOCKET, а у ошибок SMTP есть ещё responseCode. Сверьтесь с таблицей ниже.

Ошибки и решения

ПроблемаРешение
Error: Invalid login: 535 (code EAUTH)Неверный логин или пароль, либо переменные окружения не заданы в запущенном процессе. Проверьте Boolean(process.env.SMTP_PASSWORD). Подробнее: https://bulko.io/ru/smtp-errors/535/
SSL routines: wrong version numbersecure: true указан для порта 587 или 2525. Для этих портов нужен secure: false, либо перейдите на 465 с secure: true.
Greeting never received или зависание на 465Для порта 465 указан secure: false, и Nodemailer ждёт открытого приветствия, которого не будет. Поставьте secure: true.
ETIMEDOUT или ECONNREFUSEDИсходящие SMTP-порты закрыты хостингом или фаерволом. Попробуйте порт 2525 с secure: false.
554 5.7.1 в err.responseПисьмо отклонил ИИ-фильтр контента (фишинг, вредоносное ПО, имитация бренда, мошенничество). Проверьте текст и ссылки, правила: https://bulko.io/ru/acceptable-use/

Частые вопросы

Когда в Nodemailer нужен secure: true?

Только для порта 465, где TLS начинается сразу. Для 587 и 2525 оставьте secure: false: соединение всё равно шифруется через STARTTLS, а requireTLS: true делает это обязательным.

Нужен ли пул соединений для массовой отправки?

Для большого числа писем можно добавить pool: true, чтобы переиспользовать соединения. Учитывайте лимит по умолчанию: 2 000 писем в сутки на SMTP-аккаунт, увеличить его можно через [email protected].

Можно ли читать входящую почту через Nodemailer и этот сервер?

Нет. Nodemailer только отправляет, а Bulko SMTP работает только на исходящую почту, без IMAP. Ответы приходят на ваш адрес From или Reply-To.

Работает ли это в Next.js, Express или NestJS?

Да, в любом серверном коде на Node.js. Не запускайте отправку в браузере и не включайте SMTP-доступы в клиентский бандл.

Сколько это стоит?

Разовые пакеты: $5 за 5 000 писем, $15 за 20 000, $30 за 50 000, $60 за 150 000. Неиспользованные письма не сгорают, бесплатного пробного периода для SMTP нет.

Получить SMTP-доступ для Nodemailer

Разовая оплата картой или криптой, без подписки. Неиспользованные письма не сгорают. Лимит 2 000 писем в сутки на один доступ.

SMTP Relay 5K: $5 · 5000SMTP Relay 20K: $15 · 20000SMTP Relay 50K: $30 · 50000SMTP Relay 150K: $60 · 150000
Тарифы SMTP-релея

Что можно отправлять: правила использования.