Простой механизм обратной связи
Misha v.3 [16 апреля 2004]
С помощью приведенного примера кода вы можете реализовать простой механизм обратной связи на вашем сайте, однако основное его назначение — показать начинающим, как можно работать с формами, т.к. пример содержит больше комментариев, чем парсерного кода.
Следует иметь ввиду, что данный код включает в себя несколько больший функционал, чем требуется обычно (например возможность приаттачить файл к сообщению), поэтому после копирования его не забудьте удалить то, что вам не нужно.
Весь механизм обратной связи будет находиться в одном файле /feedback.html который сначала будет показывать формочку, а в случае поста на него выполнять действия по отправке письма. Если у вас данный код будет находиться по иному пути, не забудьте поправить action в <form />
@main[]
<html>
<body>
^rem{ *** на какой адрес будет отправляться письмо *** }
$sTo[to@email.ru]
^rem{ *** от какого адреса будет отправляться письмо *** }
$sFrom[robot@$env:SERVER_NAME]
^if($form:action eq "done"){
^rem{ *** сюда мы попадём после внешнего редиректа когда всё уже успешно отправилось *** }
^rem{ *** тут пишем посетителю что-нить доброе за то, что он отправил нам пожелание *** }
$bShowForm(0)
<p>Спасибо, что отправили нам свое пожелание.</p>
}{
^rem{ *** устанавливаем флаг, что надо показывать форму *** }
$bShowForm(1)
}
^if(def $form:do){
^rem{ *** если что-то пришло к нам в элементе 'do' - значит форма сабмитится *** }
^if(^isOk[]){
^rem{ *** если данные валидные, то пробуем отправить письмо *** }
^try{
^send[$sTo;$sFrom]
^rem{ *** делаем _внешний_ редирект на себя, чтобы защититься от Reload *** }
^rem{ *** правда от Back все равно таким образом не защититься *** }
^rem{ *** для того, чтобы редирект был внешним не забываем начать адрес с http:// *** }
^Lib:location[$request:uri^if(^request:uri.pos[?]>=0){&}{?}action=done;$.bExternal(1)]
}{
^rem{ *** использовали try т.к. в отправке письма может возникнуть ошибка *** }
^rem{ *** и тут мы окажемся, если эта ошибка таки возникла *** }
^rem{ *** говорим парсеру, что с этой ошибкой мы разберёмся сами *** }
$exception.handled(1)
^rem{ *** ну и надо что-нить сообщить пользователю в связи с ошибкой *** }
^rem{ *** конечно хорошо-бы ещё записать что-нить в лог файл про эту ошибку *** }
<p>Сожалеем, но при отправке письма возникла неизвестная ошибка.</p>
}
^rem{ *** сбрасываем флаг, что нужно показывать форму *** }
$bShowForm(0)
}{
^rem{ *** не заполнены какие-то поля формы. ругаемся. *** }
^rem{ *** при этом не сбрасываем флаг что нужно показывать форму. *** }
^rem{ *** т.е. после ругани у нас покажется форма *** }
^rem{ *** при этому уже заполненные ранее пользователям данные не будут потеряны *** }
<p>Не заполнены обязательные поля формы!</p>
}
}
^rem{ *** показываем форму, если установлен соответствующий флаг *** }
^if($bShowForm){
^rem{ *** если собираемся отправлять файлы то не забываем прописать указанный enctype!!! *** }
<form
method="post"
action="/feedback.html"
enctype="multipart/form-data"
>
^rem{ *** именно по этому элементу мы будем определять, постится форма или нет *** }
^rem{ *** если вы хотите анализировать это по элементу 'action', то вашу форму невозможно... *** }
^rem{ *** ...будет запостить с помощью нажатия клавиши enter или с помощью js события *** }
<input type="hidden" name="do" value="do" />
Ваше имя:<br />
<input type="text" name="name" value="$form:name" /><br />
E-mail:<br />
<input type="text" name="email" value="$form:email" /><br />
Ваш комментарий:<br />
<textarea name="comment">$form:comment</textarea><br />
Дополнительный файл:<br />
<input type="file" name="attach" /><br />
<input type="submit" name="action" value="Отправить" />
</form>
}
</body>
</html>
#end @main[]
# метод проверяет заполненность полей формы. если все хорошо - возвращает true
@isOk[]
$result(def $form:name && def $form:comment)
#end @isOk[]
# метод отправки сообщения
@send[sTo;sFrom][dtNow]
$dtNow[^date::now[]]
^mail:send[
$.to[$sTo]
$.from[^if(^Lib:isEmail[$form:email]){$form:email}{$sFrom}]
^rem{ *** кодировка, в которой отправляется письмо *** }
$.charset[$response:charset]
$.subject[Обратная связь с сайта http://$env:SERVER_NAME/]
$.text[Пользователь: $form:name
^if(def $form:email){E-mail: $form:email^#0A}Комментарий:
$form:comment^#0A^#0AСообщение отправлено: ^dtNow.sql-string[]]
^rem{ *** если посетитель приаттачил файл - отправляем и его *** }
^if($form:attach is "file"){
$.file[$form:attach]
}
]
$result[]
#end @send[]
Данный код использует класс Lib.p, поэтому необходимо скачать и подключить его.
В код включены простейшие средства защиты для того, чтобы если после постинга формы посетитель нажал кнопку Reload броузера то повторной отправки письма не происходило-бы. Однако этот механизм не спасает от нажатия Back в броузере. И если сообщение, которое постит посетитель не шлется электронной почтой, а добавляется в БД то проверку можно делать средствами БД или как описано в примере про защиту от дублирования.