Ставим надёжную защиту от спама на сайте своими силами


07-11-2018
Денис Л.
Php
6
6987
Ставим надёжную защиту от спама на сайте своими силами

Замучил спам? Я написал скрипт, который защитит Ваc от ненужных писем через формы обратной связи Вашего сайта.

Раньше я пользовался reCAPTCHA от Google. Но после того, как посмотрел на его исходный код, а в частности его вес (314 Кб в несжатом виде для версии v3), а также количество инициируемых им запросов, я отказался от этой идеи и написал всё сам. Работа скрипта проверена на многих сайтах, никакого спама не прошло.

В целях безопасного сохранения всех заявок через формы связи предусмотрена запись логов.

Ниже привожу php скрипт, с подробными комментариями.

Для начала делаем форму. Среди полей формы вставляем скрытый input с логичным для понимания атрибутом name. Представим что наша форма следующего вида:

<form action="адрес_php_скрипта" method="POST">
    <fieldset>
        <legend>Все поля ввода обязательны для заполнения</legend>
        <div>
            <p>Имя</p>
            <input name="surname"> <!-- здесь находится наш скрытый input -->
            <input name="name" required="" pattern="^[а-яА-ЯёЁ\s]+$">
        </div>
        <div>
            <p>Телефон</p>
            <input name="tel" required="">
        </div>
        <div>
            <p>E-mail</p>
            <input name="email" type="email" required="">
        </div>
        <div>
            <p>Комментарии</p>
            <textarea rows="7" name="question" required=""></textarea>
        </div>
    </fieldset>
    <button type="submit">Отправить!</button>
</form>	

Важные замечания:

  • Не нужно давать атрибуту name значение "spam"! Роботы это увидят и не заполнят это поле.
  • Не нужно прописывать атрибут style данному инпуту! Сделайте всё через CSS. Роботы увидят атрибут style и не заполнят это поле.

Форму отправляем методом POST (в теге form указываем атрибут method со значением POST).


Ниже привожу код для обработчика на php.

<?
// в переменную $badIP мы можем со временем вписать IP-адреса некоторых спамеров (например тех, которые заполнят Вашу форму вручную)
// IP будет указано в log файле. IP-адреса указываем в кавычках, через запятую, пример: ['185.189.114.123', '185.212.171.99',]
$badIP    = []; 
$to       = "ваш_email";
$from     = "mail@адрес_вашего_сайта";
$spam     = $_POST["surname"]; // принимаем данные из скрытого спам-поля
$ipAddr   = $_SERVER['REMOTE_ADDR']; // определяем IP-адрес пользователя
$today    = date('d-m-Y_H-i');
$name     = strip_tags(trim($_POST["name"])); // обрабатываем input "name"
$tel      = strip_tags(trim($_POST["tel"])); // обрабатываем input "tel"
$email    = strip_tags(trim($_POST["email"])); // обрабатываем input "email"
$question = strip_tags(trim($_POST["question"])); // обрабатываем textarea с комментариями 
$subject  = "!!! Новая заявка !!!";
$message  = "Вопрос с формы \"Задать вопрос с сайта\"<hr>"."\n";
$message .= "<b>Имя:</b><br>{$name}<hr>"."\n"."<b>Телефон:</b><br>{$tel}<hr>"."\n"."<b>E-mail:</b><br>{$email}<hr>"."\n"."<b>Комментарии:</b><br>{$question}<hr>"."\n";
$subject  = "=?utf-8?B?".base64_encode($subject)."?=";
$headers  = "From: $from\r\nReply-to: $from\r\nContent-type: text/html; charset=utf-8\r\n";

if(!in_array($ipAddr, $badIP) && empty($spam)) { // если не заполнено скрытое поле и если IP-адрес не находится в нашем чёрном списке

	$logText = strip_tags($message); // обрезаем лишние теги для log файла 

	// если в поле с именем нет ни одной цифры и ни одной латинской буквы
	// а также если в поле с комментариями нет ни одного соответствия адресам сайтов
	// можем добавить любые другие сочетания букв, по аналогии, через пайп, например (\.ua) и прочее
	if(!preg_match("/[a-z0-9]/i", $name) && !preg_match("/(www)|(http)|(@)|(\.ru)|(\.com)/i", $question)) {

		// записываем логи в файл (если файла нет, то он будет создан автоматически)
		file_put_contents("mail.log", "\n{$today}\n{$logText}\n", FILE_APPEND); chmod("mail.log", 0600);

		// если всё ок - отправляем письмо администратору сайта
		if(mail($to, $subject, $message, $headers)) {
			$subj  = "Ваш вопрос получен такой-то компанией"; // формируем письмо-отбойник клиенту, что его заявка принята
			$subj  = "=?utf-8?B?".base64_encode($subj)."?=";
			$mess  = "{$name}, Ваш вопрос принят в работу в такой-то компании.\n<br>С Вами свяжутся в ближайшее время по телефону {$tel}.\n\n<br><br>С уважением,\n<br>такая-то компания\n<br>+7 (000) 000-00-00\n0<br>https://адрес_вашего_сайта";
			mail($email, $subj, $mess, $headers);
		}

	}
	else { // если в поле с именем были латинские буквы, либо были указаны признаки сайтов - записываем логи
		file_put_contents("spam.log", "\n{$today}\nIP:{$ipAddr}\n{$logText}\n", FILE_APPEND); chmod("spam.log", 0600);
		echo "Вы некорректно заполнили форму связи. Пожалуйста, свяжитесь с нами по e-mail или телефону.<br>";
		$message .= "<br><b>Это письмо попало в спам</b>"; mail("электронная_почта_администратора_сайта", $subject, $message, $headers);
	}
}
else { // если роботом было заполнено скрытое поле или если IP-адрес в чёрном списке
	exit(); // сразу выходим
} 
?>

Подписывайтесь на группу в ВКонтакте, вступайте в сообщество на Facebook, чтобы всегда быть в курсе актуальных выпусков
Web development blog!

Читайте также:

Форма на PHP с безопасной загрузкой файлов на сервер

PHP скрипт, определяющий сколько лет организации

Отправка писем через SMTP Яндекса, Google, Mail, используя Swift Mailer