Спам-боты (пока) не выполняют JS. При показе формы пишите в сессию код, передавайте на клиент в любом виде, на клиенте пишите из JS в скрытое поле. Пока оно не оформлено в массово используемый плагин, будет работать =)
Вот наивная реализация в 40 строчек. Здесь генерируется два числа - секретное значение и множитель, в атрибут формы пишется множитель и произведение чисел, в JS вычисляется частное и подставляется в скрытое поле.
<?php
session_start();
$secret_error = false;
$is_sent = count($_POST);
if (
$is_sent &&
(
!isset($_POST['secret']) ||
!isset($_SESSION['secret']) ||
$_POST['secret'] !== $_SESSION['secret']
)
) {
$secret_error = true;
}
if ($is_sent && !$secret_error) {
// обрабатываем, шлем письмо
?>
Ваш звонок очень важен для нас!
<?php
} else {
if ($secret_error) {
?>
<p>Вы бот или у вас не включен JavaScript, сделайте с этим что-нибудь!</p>
<?php
}
$multiplier = rand(10, 99);
$secret = (string) rand(1000,9999);
$_SESSION['secret'] = $secret;
?>
<form action="" method="post" data-secret="<?= $secret * $multiplier ?>" data-multiplier="<?= $multiplier ?>">
<label>Ваше имя <input name="name" /></label>
<input type="hidden" name="secret" />
<input type="submit" />
</form>
<!-- вот это можно вынести в отдельный файл -->
<script type="text/javascript">
document.querySelectorAll('form[data-secret]').forEach(function(form) {
var secret = form.getAttribute('data-secret') / form.getAttribute('data-multiplier');
form.querySelector('[name="secret"]').value = secret;
});
</script>
<?php
}
В принципе можно с тем же успехом написать
<script type="text/javascript">
document.querySelector('[name="secret"]').value = "<?= $secret ?>";
</script>
Скорее всего кодеру, который делает бота, будет лень разбираться, как оно у вас работает, если оно работает только у вас (то есть не является тиражным решением). Магия со множителями или чем-то таким просто не позволяет вытащить значение одной регуляркой, еще немного снижая шансы заинтересовать злодея =)