Типичная форма заявки на WordPress делает одно действие: отправляет письмо. Если почта не ушла — заявки нет нигде, а посетитель уже увидел «спасибо». На этом сайте порядок другой: сначала заявка записывается в базу, и только потом рассылается по каналам.
Это десятая часть цикла «WordPress на кэшируемом сайте».
Каналы падают, и падают независимо
- почта — пароль ящика сменили, а в настройках сайта старый; почтовый сервер отверг письмо от чужого адреса отправителя; письмо ушло, но попало в спам;
- Telegram — у нас сервер ходит к нему через прокси, и запросы иногда обрываются по таймауту. В журнале крона это выглядит так:
[tg-bot] getUpdates: cURL error 28: SSL connection timeout
Это сообщение из нашего журнала. Если бы заявка в этот момент существовала только как сообщение в Telegram, её бы не было.
Порядок: проверка → база → каналы
$leadId = wp_insert_post([
'post_type' => 'lead',
'post_status' => 'private',
'post_title' => wp_date('d.m.Y H:i') . ' — ' . ($name !== '' ? $name : $contact),
'post_content' => $text,
], true);
if (is_wp_error($leadId)) {
// даже сохранить не смогли — честно говорим посетителю
wp_send_json(['ok' => false, 'message' => 'не удалось сохранить заявку, напишите в Telegram']);
}
$mail = contact_form_send_mail($text, $who); // 'ok' или текст ошибки
$tg = contact_form_send_telegram($text); // 'ok', 'off' или текст ошибки
update_post_meta($leadId, 'lead_delivery', ['mail' => $mail, 'telegram' => $tg]);
wp_send_json(['ok' => true]);
Посетитель получает «спасибо» только после того, как заявка лежит в базе. Отказ канала доставки его уже не касается: заявка не потеряна, её увидят в админке.
Итог доставки — колонкой в списке
В админке у заявок есть колонка «Доставка»: по строке на канал, зелёным — ok, серым — off (канал не настроен), красным — текст ошибки. Одного взгляда на список хватает, чтобы понять, что почта перестала уходить неделю назад, — не дожидаясь, пока об этом скажет клиент.
Ошибку почты WordPress сам наружу не отдаёт: wp_mail возвращает только «да» или «нет». Текст достаём из хука wp_mail_failed на время отправки:
$error = '';
$catch = function ($e) use (&$error) { $error = $e->get_error_message(); };
add_action('wp_mail_failed', $catch);
$ok = wp_mail($to, $subject, $text, $headers);
remove_action('wp_mail_failed', $catch);
return $ok ? 'ok' : ($error ?: 'failed');
Тип записи для заявок
public => false— у заявок нет страниц на сайте, их не найти перебором адресов;show_in_rest => false— их нет в REST API;create_posts => do_not_allow— создать заявку руками в админке нельзя, только формой;- статус
private, и сохранение заявки не сбрасывает кэш страниц (девятая часть).
Заявки — это персональные данные. Закрыть тип записи от публичного доступа мало, нужно проверить и всё, что их читает: статистику, экспорт, отчёты. Как один такой отчёт отдавал заявки без входа — в 16-й части.
Одна мелочь про почту
Если в поле «контакт» посетитель оставил почту, она ставится в Reply-To письма. Кнопка «Ответить» в почтовике сразу пишет клиенту, а не на служебный ящик сайта.
Не уверены, что все заявки с сайта до вас доходят?
Пришлите адрес — сделаю так, чтобы заявка сохранялась до отправки, а сбои каналов были видны сразу.
// загружаю комментарии…