PHP: пишем почтовую форму "попроще"
Код частично из архивов, но, вроде бы, ничего особо "страшного" в нём нет. Здесь я не отправлял письмо с вложением, а просто организовывал более-менее простую и безопасную форму для программной отправки электронной почты, то, что называют mailer. Только нужен был достаточно простой.
Применяя подобные вещи, следует всегда иметь в виду изобретательность спамеров, которые могут подделать заголовки HTTP и использовать вашу форму для своих целей.
С другой стороны, если код не выложен в открытый доступ или хотя бы содержит уникальные настройки, его можно использовать.
В отличие от множества других подобных скриптов, доступных в сети, этот скрипт состоит всего из одного файла, имеет простую текстовую капчу и загружает форму только после загрузки всей страницы, что "обрубает" большинство известных ботов. На отключённый Javascript выдаётся сообщение-предупреждение, а если в браузере клиента отключены Cookie, письмо также не получится отправить. Настройки URL скрипта и сайта также прописываются в коде "ручками", так и проще, и надёжней. Также в заголовок X-Mailer и в текст письма включается IP-адрес отправителя.
Через POST никаких кодов не передаётся, только сохраняется в сессии "сдвинутый" с помощью настройки SECRET
и при этом зашифрованный код капчи. При показе пользователю капча "зашумляется" случайными тегами.
Исключив из начала файла вызов session_start (наверняка он у Вас делается где-то в другом месте) и настроив форму "под себя" Вы легко сможете встроить такой простой mailer в существующий проект.
Код не снабжён HTML-обрамлением, предполагается, что оно будет там, куда вставляется программа.
Можно снабдить такую форму javascript-активизацией кнопки "Отправить", которая срабатывает только тогда, когда пользователь заполнил нужные поля (так сделано у меня в блоге), но опыт показывает, что если заполняемых полей более двух, это только сбивает с толку.
Предполагается, что скрипт будет работать и отправлять письмо в кодировке Юникод (UTF-8). Вот код файла .htaccess
, размещённого в папке с мейлером:
AddDefaultCharset utf-8 php_flag magic_quotes_gpc off php_flag magic_quotes_runtime off php_flag magic_quotes_sybase off
Вот код самого мейлера, на реальном хостинге сработал, и, вроде бы, "живёт" на паре сайтов:
<?php //Следующие 2 строки, возможно, будут Вами удалены error_reporting (E_ALL); //для отладки session_start (); //должно быть выполнено до выдачи любого контента в браузер //Настройки define ('SECRET','1234'); //уникальное целое число для дополнительной защиты, смените на своё define ('MAINURL','localhost'); // Главный URL сайта без черты в конце, смените на свой define ('MYURL','index.php'); //URL скрипта, смените на свой define ('MAXWORDLENGTH','32'); //Максимальная длина слова в письме define ('EOL',"\r\n"); //Разделитель строк, некоторые почтовые сервера требуют \n - подобрать опытным путём define ('SUBJECT','Сообщение от '); //Начало темы письма $fields = Array ( //поля формы, заполните по образцу //имя, тип, подпись, значение, длина Array ('name', 'text', 'Ваше имя', '', 32), Array ('email', 'text', 'Ваш адрес E-mail', '', 32), Array ('text', 'textarea', 'Сообщение', '', 1024), Array ('list', 'select', 'Адресат', 'default@mail.ru', Array('default@mail.ru'=>'Дирекция','buh@mail.ru'=>'Бухгалтерия')), Array ('code', 'captcha', 'Код подтверждения', '', 4) ); $params = array ('name','email','text','list','code','action'); //разрешённые имена параметров POST //Код while (list($num,$var) = each($params)) { //приём параметров POST if (!empty($_POST[$var])) { $$var = trimall(htmlspecialchars($_POST[$var],ENT_COMPAT,'utf-8')); for ($i=0; $i<count($fields); $i++) { if ($fields[$i][0]==$var) { $type = $fields[$i][1]; if ($type=='text' || $type=='textarea' || $type=='select') { $fields[$i][3]= $$var; //сохранить ранее введённое, кроме кода } } } } else $$var = ''; //если величина не передана - будет создана пустая } echo '<div id="sform"></div>'."\n"; //сюда будет вставлена форма после загрузки страницы $error = ''; $valid=''; if (isset($_SESSION['valid'])) $valid=$_SESSION['valid']; if (!empty($action)) { if (!empty($code)) { $code = strval(intval($code)-intval(SECRET)); if (md5($code) == $valid) { if (!empty($name) and !empty($email) and !empty($text) and !empty($list)) { //Поля заполнены $name_len = mb_strlen($name,'utf-8'); $email_len = mb_strlen($email,'utf-8'); $text_len = mb_strlen($text,'utf-8'); if ($name_len > 3 and $email_len > 6 and $text_len > 6) { if ($name_len <= 32 and $email_len <= 32 and $text_len <= 1024) { $words = preg_split("/[\s]+/",$text); $goodwords = true; for ($i=0; $i<count($words); $i++) { if (mb_strlen($words[$i],'utf-8') > MAXWORDLENGTH) { $goodwords = false; break; } } if ($goodwords) { if (filter_var($email, FILTER_VALIDATE_EMAIL)) { if ($_SERVER['SERVER_NAME'] == MAINURL) { $subj = SUBJECT.$name.' <'.$email.'>'; $ip=get_ip(); $headers = 'From: '.$email.EOL. 'To: '.$list.EOL. 'Reply-To: '.$email.EOL. 'Subject: '.$subj.EOL. 'Content-type: text/plain; charset=utf-8'.EOL. 'X-Mailer: PHP/'.phpversion().' (IP='.$ip.')'.EOL.EOL; if (mail($email,$subj,$text.EOL.EOL.$name.' (E-mail: '.$email.', IP-адрес: '.$ip.')',$headers)) { echo '<p>Спасибо, Ваше сообщение успешно отправлено</p>'; } else { $error.="<br>Ошибка при отправке почты функцией mail, обратитесь к администратору"; } } else { $error.="<br>Форма заполнена на другом сайте, отправка почты недоступна"; } } else { $error.="<br>Введённый адрес E-mail некорректен"; } } else { $error.="<br>Обнаружено слишком длинное слово, пожалуйста, введите корректный текст письма"; } } else { $error.="<br>Введённый в одно из полей текст - слишком длинный, пожалуйста, введите корректные данные"; } } else { $error.="<br>Введённый в одно из полей текст - слишком короткий, пожалуйста, введите корректные данные"; } } else { $error.="<br>Заполнены не все поля письма"; } } else { $error.="<br>Введён неверный код подтверждения или отключён приём Cookie-файлов в браузере"; } } else { $error.="<br>Не указан код сообщения или отключён приём Cookie-файлов в браузере"; } } if (empty($action) or !empty($error)) { if (!empty($error)) { echo '<p>Извините, Ваше письмо не может быть отправлено. Причины:'.$error.'</p>'."\n"; } echo form ($fields); } function form ($fields) { $form = '<form name="guestForm" action="'.MYURL.'" method="post"><table border="0" width="90%" align="center">'."\n"; for ($i=0; $i<count($fields); $i++) { $form .= '<tr>'."\n"; $field = $fields[$i]; $name = $field[0]; $type = $field[1]; $msg = $field[2]; $value = $field[3]; $maxlen = $field[4]; $form .= '<td><p>'.$msg.':</p></td>'."\n".'<td>'."\n"; switch ($type) { case 'text': $form .= '<input type="text" name="'.$name.'" maxlength="'.$maxlen.'" size="'.($maxlen+2).'" value="'.$value.'">'."\n"; break; case 'textarea': $form .= '<textarea name="'.$name.'" maxlength="'.$maxlen.'" rows="12" cols="86">'.$value.'</textarea>'."\n"; break; case 'select': $form .= '<select name="'.$name.'" size="1">'."\n"; foreach ($maxlen as $key=>$val) { $form .= '<option value="'.$key.'"'.($key==$value?' selected':'').'>'.$val."\n"; } $form .= '</select>'."\n"; break; case 'captcha': $form .= '<input type="text" name="'.$name.'" maxlength="'.$maxlen.'" size="'.($maxlen+1).'" value="">'. ' ('.visible_code(generate_code()).')'."\n"; break; } $form .= '</td></tr>'."\n"; } $form .= '<tr><td> </td><td><input name="action" type="submit" value="Отправить"></td></tr></table></form>'."\n"; $form = '<script type="text/javascript"> window.addEventListener("load", function() { document.getElementById("sform").innerHTML = \''.trimall($form).'\'; }); </script> <noscript> <form> <table border="0" width="90%" align="center"> <tr> <td> <p> Извините, для отправки сообщений нужен включённый в Вашем браузере Javascript. </p> </td> </tr> </table> </form> </noscript>'."\n"; return $form; } function visible_code ($s) { $tags = Array ( Array ( '<span>','</span>' ), Array ( '<b>','</b>' ), Array ( '<i>','</i>' ), Array ( '<u>','</u>' ), Array ( '<s>','</s>' ), Array ( '<sub>','</sub>' ), Array ( '<sup>','</sup>' ), Array ( '<big>','</big>' ), Array ( '<small>','</small>' ) ); $len = mb_strlen ($s,'utf-8'); $res = ''; for ($i = 0; $i < $len; $i++) { $c = substr ($s, $i, 1); $n = rand(0, count($tags)-1); $res .= $tags[$n][0].$c.$tags[$n][1]; } return $res; } function generate_code() { srand (time()); $valid = mt_rand(1000,9999); $_SESSION['valid'] = md5 ($valid - intval(SECRET)); return $valid; } function trimall ($string) { return preg_replace("/\s+/"," ",trim($string)); } function get_ip () { if( getenv('HTTP_X_FORWARDED_FOR') != '' ) { $client_ip = ( !empty($_SERVER['REMOTE_ADDR']) ) ? $_SERVER['REMOTE_ADDR'] : ( ( !empty($_ENV['REMOTE_ADDR']) ) ? $_ENV['REMOTE_ADDR'] : $REMOTE_ADDR ); $entries = explode(',', getenv('HTTP_X_FORWARDED_FOR')); reset($entries); while (list(, $entry) = each($entries)) { $entry = trim($entry); if ( preg_match("/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/", $entry, $ip_list) ) { $private_ip = array('/^0\./', '/^127\.0\.0\.1/', '/^192\.168\..*/', '/^172\.((1[6-9])|(2[0-9])|(3[0-1]))\..*/', '/^10\..*/', '/^224\..*/', '/^240\..*/'); $found_ip = preg_replace($private_ip, $client_ip, $ip_list[1]); if ($client_ip != $found_ip) { $client_ip = $found_ip; break; } } } } else { $client_ip = ( !empty($_SERVER['REMOTE_ADDR']) ) ? $_SERVER['REMOTE_ADDR'] : ( ( !empty($_ENV['REMOTE_ADDR']) ) ? $_ENV['REMOTE_ADDR'] : $REMOTE_ADDR ); } return $client_ip; } ?>
Стили и прочее нетрудно дописать. Также на хостинге должна быть разрешена функция mail, чтобы работало.
12.05.2018, 13:19 [2037 просмотров]