На почту приходит спам с формы обратной связи
У меня на сайте существует форма обратной связи следующего вида:
<form action="sendmail.php" method="POST" id="form">
<div> <!--Таких дивов 5 штук-->
<label>
<input>
</div>
<div> <!--Тут у меня капча от яндекса--> </div>
<button action="submit"> Отправить! </button>
</form>
JavaScript файл:
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('form');
form.addEventListener("submit", formSend);
async function formSend(e) {
e.preventDefault();
let error = formValidate(form)
let formData = new FormData(form);
if (error === 0) {
form.classList.add('_sending')
let response = await fetch('sendmail.php', {
method: 'POST',
body: formData
});
if (response.ok) {
let result = await response.json();
alert(result.message);
form.reset();
form.classList.remove('_sending');
location.reload();
} else {
console.log('Ошибка')
form.classList.remove('_sending')
}
}
}
В нём ещё есть код валидации полей, проверки капчи и прочее, я их намеренно не добавил, т.к. вопрос не об этом.
И сам файл sendmail.php:
<?php
require 'phpmailer/src/Exception.php';
require 'phpmailer/src/PHPMailer.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$mail = new PHPMailer(true);
$mail -> CharSet = 'UTF-8';
$mail -> setLanguage('ru', 'phpmailer/language/');
$mail -> IsHTML(true);
$mail -> Port = 465;
// Кому пиьмо
$mail -> addAddress('[email protected]');
// Тема письма
$mail -> Subject = 'Заявка из формы обратной связи!';
// Содержимое письма
if(trim(!empty($_POST['name']))) {
$body.='<p><strong>Имя:</strong> '.$_POST['name'].'</p>';
}
if(trim(!empty($_POST['phone']))) {
$body.='<p><strong>Номер телефона:</strong> '.$_POST['phone'].'</p>';
}
if(trim(!empty($_POST['email']))) {
$body.='<p><strong>Почта:</strong> '.$_POST['email'].'</p>';
}
if(trim(!empty($_POST['message']))) {
$body.='<p><strong>Сообщение:</strong> '.$_POST['message'].'</p>';
}
$mail -> Body = $body;
// Отправляем
if (!$mail ->send()) {
$message = 'Ошибка';
} else {
$message = 'Данные отправлены!';
}
$response = ['message' => $message];
header('Content-type: application/json');
echo json_encode($response)
?>
Суть в том, что несмотря на мои старания отсеять ботов - 25% гарантированно пишут на почту спам. Конечно, я пробовал разные методы защиты:
- Перво-наперво форма спрятана в поп-ап, что мне казалось отсеит часть роботов;
- У меня есть невидимое пустое поле, при заполнении в которое чего-либо форма выдаёт ошибку;
- У меня стоит капча от Яндекса (Гугл и того больше ботов пропускает), при незаполнении которой форма так же не работает; Кому интересно, можете проверить: в самом низу каждой страницы лежит форма
В конце концов я совсем отчаялся и бросил кнопку <button> в комментарий, чтобы прверить что я всё делаю правильно и проблема точно не во мне, а в капче или невидимом поле - но как же я был удивлён когда в течение дня, на почту, мне всё-равно пришло 3 спам-сообщения с моей формы:
И да - я в конце-концов вообще удалил <button> из кода, но спам-сообщения это не особо волнует, спам как приходил, так и по сей день приходит. В интернет пространстве пытался узнать технологию работы спам-роботов, спрашивал у ChatGPT что можно добавить в форму, искал ролики на ютубе - всё бестолку, дальше капчи и пустого невидимого поля никто ничего не предлагает.
Люди добрые, дайте пожалуйста наводку что я делаю не так. Я бы не задавал сюда вопрос если бы всё не перепробовал и совсем не опустились руки - у меня в голове не укладывается, БАНАЛЬНО - как можно отправить собщение на почту без триггера submit в кнопке?? Если представляется возможным - напишите какой код можно изменить или добавить. Заранее спасибо!
Ответы (1 шт):
Напишу как использовали google recaptcha, после чего спама не стало (уже более 7 месяцев):
- в head:
<script src="https://www.google.com/recaptcha/api.js?render=[TOKEN]"></script>
<script>
const grecaptcha_exec = function(f) {
grecaptcha.execute('[TOKEN]', {action: 'homepage'}).then( f );
};
grecaptcha.ready(function() {
grecaptcha_exec( function(token) {
// console.log(token);
});
});
</script>
- отправка формы:
<form method="post" action="/sendForm" id="contactForm">
<input name="g-token" type="hidden" value="">
...
<input type="button" value="Send" id="submit" onclick="return sendMail();">
</form>
<script type="text/javascript">
function sendMail() {
// сперва проверка полей формы
grecaptcha_exec( function(token) {
$('#contactForm').find('input[name="g-token"]').val(token);
sendMailNext();
});
}
function sendMailNext(){
$.post('/app.php?module=mail&action=send', {
name: name, // поля с формы
email: email, // поля с формы
message: message, // поля с формы
'g-token': $('#contactForm [name="g-token"]').val()
}, function (response) {
// проверка ответа
$('#contactForm [name="g-token"]').val('');
});
}
</script>
- обработчик формы (/app.php?module=mail&action=send):
$ip = $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'];
$token = trim($_POST["g-token"]);
$secretKey = '[SECRET]';
$url = "https://www.google.com/recaptcha/api/siteverify?secret=".urlencode($secretKey)."&response=".urlencode($token)."&remoteip=".urlencode($ip);
$request = file_get_contents($url);
$response = json_decode($request);
if ( !$response->success ) {
log("grecaptcha validation failed, bad token: $ip");
echo json_encode(false);die;
}
elseif ($response->score < 0.5) {
log( sprintf("grecaptcha validation failed: score=%s, ip=%s", $response->score, $ip));
echo json_encode(false);die;
}
log(sprintf("grecaptcha validation success: score=%s, ip=%s", $response->score, $ip));
// отправка email
echo json_encode(true);die;
