Backend / Forms / практический материал

Как отправлять заявки с сайта на почту через свой сервер

Настраиваем отправку заявок со статического сайта через свой сервер: HTML-форма, PHP-обработчик, Postfix, SPF, DKIM, DMARC и защита от спама.

  • Дмитрий Лаврушин
  • 23 августа 2026
  • 4 минуты

Форма собирает только нужные поля и объясняет следующий шаг.

Рабочая модель

HTML-форма → Проверка на сервере → Почтовый узел

Форма собирает только нужные поля и объясняет следующий шаг.

Статический сайт не может сам отправить письмо. HTML показывает форму, а JavaScript передает данные. Для отправки нужен небольшой серверный обработчик. Он принимает заявку, проверяет поля и передает письмо локальному почтовому серверу.

Рабочая схема выглядит так:

форма на сайте → /api/send-form.php → проверка → Postfix → почта менеджера

В этой схеме нет внешнего сервиса заявок и ежемесячной платы. Данные не уходят в стороннюю CRM. Но ответственность за доставляемость, безопасность и журнал ошибок остается на владельце сервера.

Форма и отправка данных

html
<form id="lead-form" action="/api/send-form.php" method="post">
  <input name="name" autocomplete="name" required>
  <input name="email" type="email" autocomplete="email" required>
  <textarea name="message" maxlength="3000" required></textarea>
  <input name="company" class="hidden" tabindex="-1" autocomplete="off">
  <button type="submit">Отправить</button>
</form>

<script>
const form = document.querySelector('#lead-form');
form.addEventListener('submit', async (event) => {
  event.preventDefault();
  const response = await fetch(form.action, {
    method: 'POST',
    body: new FormData(form)
  });
  if (!response.ok) throw new Error('Заявка не отправлена');
  form.reset();
});
</script>

Скрытое поле company работает как простая ловушка для ботов. Это не полная защита. На сервере дополнительно нужны ограничение частоты запросов, проверка длины полей и журналирование ошибок.

Минимальный PHP-обработчик

php
<?php
header('Content-Type: application/json; charset=utf-8');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  http_response_code(405); exit;
}
if (!empty($_POST['company'] ?? '')) {
  http_response_code(204); exit;
}

$name = trim($_POST['name'] ?? '');
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
$message = trim($_POST['message'] ?? '');

if (!$email || $name === '' || $message === '' || mb_strlen($message) > 3000) {
  http_response_code(422); exit;
}

$body = "Имя: $name\nEmail: $email\n\n$message";
$headers = [
  'From: Site <forms@example.com>',
  'Reply-To: ' . $email,
  'Content-Type: text/plain; charset=UTF-8'
];

if (!mail('hello@example.com', 'Новая заявка с сайта', $body, implode("\r\n", $headers))) {
  http_response_code(500); exit;
}
echo json_encode(['ok' => true]);

Адреса forms@example.com и hello@example.com нужно заменить. Функция mail() не доставляет письмо сама. Она передает его локальному MTA, например Postfix.

Что настроить на сервере

Для прямой отправки нужны Postfix, доменное имя почтового узла, статический IP и обратная PTR-запись. В DNS добавляются SPF, DKIM и DMARC. Владелец IP обычно настраивает PTR через панель хостинга. Без аутентификации письма могут попадать в спам или отклоняться.

Postfix можно закрыть для внешних подключений и принимать письма только локально. Это снижает риск превратить сервер в открытый почтовый ретранслятор. Форму также нужно принимать только по HTTPS.

Что проверить, если письма не приходят

Сначала убедитесь, что обработчик вернул успешный код и письмо появилось в очереди Postfix. Затем проверьте почтовый журнал, DNS-записи и ответ сервера получателя. Ошибка формы, отказ локального MTA и отклонение письма внешней почтой являются тремя разными проблемами.

Не подставляйте email посетителя в поле From. Письмо должно отправляться от адреса вашего домена, например forms@example.com. Адрес клиента указывается в Reply-To. Иначе SPF и DMARC могут не совпасть с доменом отправителя.

Также не показывайте пользователю сообщение «Спасибо» до ответа сервера. При временной ошибке сохраняйте заявку локально и повторяйте отправку. Такая резервная запись важнее красивой анимации формы.

Если провайдер блокирует исходящий порт 25 или у IP слабая репутация, практичнее использовать SMTP-реле. Подойдут Resend, Postmark, Mailgun, Brevo или SMTP2GO. Код формы не меняется. Меняется только способ доставки письма.

Собственный сервер подходит для небольшого потока заявок и полного контроля. Для критичных уведомлений я дополнительно сохраняю заявку в локальный журнал или базу. Тогда обращение не потеряется даже при временной ошибке почты.

Доказательная база

Источники, на которые можно опереться