Меня лично дико раздражает каптча, в особенности, когда великая и могучая гугля шесть раз подряд пытается у меня узнать как выглядят витрины и дороги, а если нужно вводить циферки написанные на тарабарском то вообще труба. Это меня как пользователя она раздражает. А как программиста — ее не всегда корректно впишешь в дизайн. Поэтому я искал решения, которые бы отсеивали спам, но при этом не использовали каптчу.

По сути было найдено два решения:

1) Скрытое поле и проверка на пустоту, но, к сожалению, роботы научились распознавать такие поля.
2) использовать сервис Akmist, который проверяет содержимое, но почему-то он отвалился и я так не сумел найти к нему подход.

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

Итак, от слов к делу.

Для eForm (evolutionCMS).

Создаем сниппет checkSpamTime, вставляем в него код:

<?php
if ($_SESSION['now'])
{
	$_SESSION['lt'] = $_SESSION['now'];	
}
$_SESSION['now'] = microtime(true);

if (!function_exists('checkSpamTime')) 
{
	function checkSpamTime(&$fields)	
	{			
		$time = $_SESSION['now'] - $_SESSION['lt'];		
		if (($time<2) or ($time>1440)) exit(); //Здесь проверяем сколько секунд прошло с момента точки входа. 5 - с запасом, можно ставить и единицу
	}
}


Далее делаем вызов сниппета над вызовом eForm (если используется несколько форм, необходимо поставить ОДИН раз над самой верхней), и в самом сниппете пишем &eFormOnBeforeMailSent=`checkSpamTime`

В итоге у нас получается что-то вроде такого:

[!checkSpamTime!]
[!eForm? 
/*...*/
&eFormOnBeforeMailSent=`checkSpamTime`
/*...*/
!]


Для formLister (evolutionCMS)

Создаем сниппет checkSpamTimeFL, вставляем в него код

<?php
if ($FormLister->isSubmitted())
{
    $flag = false;
    $now = microtime(true);
	
if ((isset($_SESSION['now'])) && ((($now - $_SESSION['now']) > 2) && (($now - $_SESSION['now']) < 1440)))
    {		
        $flag = true;
    }
    $FormLister->setValid($flag);
}
else 
{   
	$_SESSION['now'] = microtime(true);
}


и вызываем его в prepare.
В итоге у нас получается что-то вроде такого:
[!FormLister? 
/*...*/
&prepare=`checkSpamTimeFL`
/*...*/
!]


За обновление решения спасибо Pathologic

Для FormIt (Modx Revolution)

Создаем сниппет checkSpamTime, вставляем код:
<?php
if (count($_POST))
{
    $flag = false;
    $now = microtime(true);
  
if ((isset($_SESSION['now'])) && ((($now - $_SESSION['now']) > 2) && (($now - $_SESSION['now']) < 1440)))
    {	
        $flag = true;
    }
    return $flag;
}
else 
{   
	$_SESSION['now'] = microtime(true);
}

Замечание. Я с Ревой знаком поверхностно, поэтому может кто подскажет: на что заменить проверку count($_POST)? Я че-та не нашел ничего более изящного((

И вписываем его первым в хук и пре хук, т.е.

[ [ !FormIt? 
/*...*/
&hooks=`checkSpamTime,email`
&preHooks=`checkSpamTime`
/*...*/
] ]


Все три варианта проверены — работают)

P.S. Спасибо руководству сайта за блокировку моего предыдущего аккаунта)