【问题标题】:Contact form with anti-spam field, PHP or JS issue带有反垃圾邮件字段、PHP 或 JS 问题的联系表
【发布时间】:2015-08-09 21:01:11
【问题描述】:

我有一个引导联系表,我在其中添加了一个简单的数学公式来防止垃圾邮件。该表单使用contact_me.js 处理表单并调用contact_me.php 文件来验证和发送电子邮件。它还使用 jqBootstrapValidation.js 来验证表单。我使用了一个基本的引导模板并为我的网站修改了模板,所以我没有创建实际的表单或 php(或 js)。

表单可以正常发送电子邮件,但我添加的“人类”数学方程式字段不起作用,因为无论数学答案是否正确,它都会发送电子邮件。我对 PHP 或 JS 知之甚少,但我对 HTML 和 CSS 非常了解 - 所以我知道问题出在 PHP 或 JS 上。谁能帮助我解决问题所需的更新?

HTML 表单代码:

<div class="form-group col-xs-12 floating-label-form-group controls">
        <label>Email Address</label>
        <input type="email" class="form-control" placeholder="Email Address" id="email" required data-validation-required-message="Please enter your email address.">
        <p class="help-block text-danger"></p>
    </div>
</div>
<div class="row control-group">
    <div class="form-group col-xs-12 floating-label-form-group controls">
        <label>Phone Number</label>
        <input type="tel" class="form-control" placeholder="Phone Number" id="phone" required data-validation-required-message="Please enter your phone number.">
        <p class="help-block text-danger"></p>
    </div>
</div>
<div class="row control-group">
    <div class="form-group col-xs-12 floating-label-form-group controls">
        <label>Message</label>
        <textarea rows="5" class="form-control" placeholder="Message" id="message" required data-validation-required-message="Please enter a message."></textarea>
        <p class="help-block text-danger"></p>
    </div>
</div>
<div class="row control-group">
    <div class="form-group col-xs-12 floating-label-form-group controls">
        <label>Human</label>
        <input type="text" class="form-control" placeholder="2 + 3 = ?" id="human" required data-validation-required-message="Please solve math equation to prove you are human">
        <p class="help-block text-danger"></p>
    </div>
</div>
 <br>
<div id="success"></div>
<div class="row">
    <div class="form-group col-xs-12">
        <button type="submit" class="btn btn-success btn-lg">Send</button>
    </div>
</div>
</form>

Contact_Me.php 代码:

<?php
// Check for empty fields
if(empty($_POST['name'])        ||
empty($_POST['email'])      ||
empty($_POST['phone'])      ||
empty($_POST['message'])    ||
empty($_POST['human'])  ||
!filter_var($_POST['email'],FILTER_VALIDATE_EMAIL))
{
echo "No arguments Provided!";
return false;
}

//Check if simple anti-bot test is correct
if ($human !== 5) {
   $errHuman = 'Your anti-spam is incorrect';
}   

$name = $_POST['name'];
$email_address = $_POST['email'];
$phone = $_POST['phone'];
$message = $_POST['message'];
$message = $_POST['human'];

// Create the email and send the message
$to = 'info@mysite.com'; // Add your email address inbetween the '' replacing yourname@yourdomain.com - This is where the form will send a message to.
$email_subject = "Portfolio Website Message:  $name";
$email_body = "You have received a new message from your portfolio website contact form.\n\n"."Here are the details:\n\nName: $name\n\nEmail: $email_address\n\nPhone: $phone\n\nMessage:\n$message";
$headers = "From: noreply@mysite.com\n"; // This is the email address the generated message will be from. We recommend using something like noreply@yourdomain.com.
$headers .= "Reply-To: $email_address"; 
mail($to,$email_subject,$email_body,$headers);
return true;            
?>

Contact_me.js 代码:

$(function() {

$("input,textarea").jqBootstrapValidation({
    preventSubmit: true,
    submitError: function($form, event, errors) {
        // additional error messages or events
    },
    submitSuccess: function($form, event) {
        // Prevent spam click and default submit behaviour
        $("#btnSubmit").attr("disabled", true);
        event.preventDefault();

        // get values from FORM
        var name = $("input#name").val();
        var email = $("input#email").val();
        var phone = $("input#phone").val();
        var message = $("textarea#message").val();
        var human = $("textarea#human").val();
        var firstName = name; // For Success/Failure Message
        // Check for white space in name for Success/Fail message
        if (firstName.indexOf(' ') >= 0) {
            firstName = name.split(' ').slice(0, -1).join(' ');
        }
        $.ajax({
            url: "././mail/contact_me.php",
            type: "POST",
            data: {
                name: name,
                phone: phone,
                email: email,
                message: message,
                human: human
            },
            cache: false,
            success: function() {
                // Enable button & show success message
                $("#btnSubmit").attr("disabled", false);
                $('#success').html("<div class='alert alert-success'>");
                $('#success > .alert-success').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>&times;")
                    .append("</button>");
                $('#success > .alert-success')
                    .append("<strong>Your message has been sent. </strong>");
                $('#success > .alert-success')
                    .append('</div>');

                //clear all fields
                $('#contactForm').trigger("reset");
            },
            error: function() {
                // Fail message
                $('#success').html("<div class='alert alert-danger'>");
                $('#success > .alert-danger').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>&times;")
                    .append("</button>");
                $('#success > .alert-danger').append("<strong>Sorry " + firstName + ", it seems that my mail server is not responding. Please try again later!");
                $('#success > .alert-danger').append('</div>');
                //clear all fields
                $('#contactForm').trigger("reset");
            },
        })
    },
    filter: function() {
        return $(this).is(":visible");
    },
});

$("a[data-toggle=\"tab\"]").click(function(e) {
    e.preventDefault();
    $(this).tab("show");
});
});

// When clicking on Full hide fail/success boxes
$('#name').focus(function() {
$('#success').html('');
});

jqBootstrapValidation.js 是一个用于自动验证 Bootstrap 表单的插件,位于:http://ReactiveRaven.github.com/jqBootstrapValidation/

【问题讨论】:

  • 在“Contact_Me.php”中 - $human 最初设置在哪里?
  • @RamRaider 我对 PHP 了解不多 - 所以我不确定你在这里问什么,抱歉我是一个无知的新手!我应该如何/在哪里最初设置 $human?谢谢!

标签: javascript php jquery twitter-bootstrap


【解决方案1】:

为了防止 PHP 发送邮件,您需要在调用之前退出脚本。从您的代码看来,

if ($human !== 5) {
    $errHuman = 'Your anti-spam is incorrect';
}  

是告诉您数学答案是否正确的地方。因此,您需要将其替换为:

if ($_POST['human'] != 5) {
    $errHuman = 'Your anti-spam is incorrect';
    return false;
}

编辑

首先将die($_POST['human']); 添加到您的php 中(在哪里都无所谓)。

然后在您的 jquery 中将 data 参数添加到 successerror 函数中。后跟一个 console.log(data);喜欢:

function(data) { 
    console.log("Success: "+data);
    ...

请分别更改"Success: "

完成这些编辑后,运行它并查看您的日志。

【讨论】:

  • 不应该是 != 而不是 !== 吗?因为输入通常返回一个字符串而不是一个整数,你在这里检查它。
  • 感谢@Maximilian 和 szoszk 的建议。我尝试了这两个建议,但电子邮件仍然没有正确的数学答案。此外,当输入错误的数学答案并发送电子邮件时,不会显示错误消息。同样,我远非专家,但我想知道问题是否与与 PHP 通信的 contact_me.js 文件有关?另外,您在上面引用的我的 $human 验证代码的位置是否可以,还是应该放在 PHP 中的其他位置?再次感谢您。
  • 你能看到我的编辑,然后回复我它是否有效!?
  • @Maximilian 我尝试了您建议的编辑,即使我在数学方程式中输入了错误的答案,它仍然发送电子邮件而没有任何错误消息。还有其他想法吗?再次感谢您的帮助!
【解决方案2】:

在 html 表单中,我看不到名称字段,但它在 php 代码和 javascript 中都被引用。为了测试,我将此字段添加到我的表单版本中。下面的代码基于您的原始代码,除了发送实际邮件(没有本地邮件服务器!)之外,它按预期处理提交。但是,在某些地方,您会回显消息然后返回 false - javascript 是否使用此回显的内容?

<?php

    session_start();/* required if using session based captcha image */

    /* If the page is accessed by GET etc then display error, otherwise process form input */
    if( $_SERVER['REQUEST_METHOD']=='POST' ){


        function message( $message=false, $errors=array() ){
            if( $message ) return json_encode( array( 'message' => $message, 'errors'=>$errors ) );
        }

        $errors=array();
        $options = array( 'flags' => FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_ENCODE_HIGH );


        /* Filter all submitted fields */
        foreach( $_POST as $field => $value ){
            switch( $field ){
                case 'name': $name=filter_input( INPUT_POST, $field, FILTER_SANITIZE_SPECIAL_CHARS, $options ); break;
                case 'email': $email=filter_input( INPUT_POST, $field, FILTER_VALIDATE_EMAIL ); break;
                case 'phone': $phone=filter_var( filter_input( INPUT_POST, $field, FILTER_SANITIZE_NUMBER_FLOAT ), FILTER_VALIDATE_FLOAT ); break;
                case 'message': $message=filter_input( INPUT_POST, $field, FILTER_SANITIZE_SPECIAL_CHARS, $options ); break;
                case 'human': $human=filter_var( filter_input( INPUT_POST, $field, FILTER_SANITIZE_NUMBER_INT ), FILTER_VALIDATE_INT ); break;
                default:
                    $errors[]='Unknown field: '.$field;
                break;
            }
        }

        /* check each value is acceptable / has a value */
        $variables=array($name,$email,$phone,$message,$human);
        foreach( $variables as $value ){
            if( !isset( $value ) or empty( $value ) ){
                $errors[]='Missing parameter';
            }
        }

        /* Integer test */
        if( floatval( $human )!==floatval( $_SESSION['simple_maths_captcha'] ) ) {
            $errors[]='Anti-Spam verification failed';
        }

        if( !empty( $errors ) ) exit( message( 'Unable to send email', $errors ) );


        $to = 'info@mysite.com';
        $email_subject = "Portfolio Website Message: " . $name;
        $email_body = "You have received a new message from your portfolio website contact form.\n\n
            Here are the details:\n\n
            Name: ".$name."\n\n
            Email: ".$email_address."\n\n
            Phone:".$phone."\n\n
            Message:\n".$message;
        $headers = "From: noreply@mysite.com\n";
        $headers .= "Reply-To: ".$email_address; 

        /* should return either true or false */
        $result = @mail( $to, $email_subject, $email_body, $headers );


        exit( message( 'Your message has been sent: '.$result, $errors ) );


    } else {
        header( 'HTTP/1.0 405 Method Not Allowed', TRUE, 405 );
        $errors[]='Incorrect method';
        exit( message( 'Method not allowed', $errors ) );
    }         
?>

我还注意到您的 javascript 代码中有这一行:-

var human = $("textarea#human").val();

由于输入类型是标准文本字段,我不知道它是否会有所不同,但这应该是:-

var human = $("input#human").val();

关于实际的验证码挑战,除非这个数字发生变化,否则它对垃圾邮件发送者的保护非常少。通常会(或者至少我会)使用 PHP 创建包含挑战拼图的图像并设置会话变量,然后在提交表单后对其进行测试 - 因此每次都不同。

例如

<?php
    /* captcha.php */
    session_start();
    header('Content-type: image/png');



    function challenge( $full=false, $low1=1, $high1=20, $low2=1, $high2=20 ){
        /* Generate an arithmetic challenge with random numbers and a random method */
        $ops=array( '+','-' );
        if( $full==true ) $ops=array_merge( $ops, array( '/', 'x' ) );

        $numbers=array( rand( $low1, $high1 ), rand( $low2, $high2 ) );
        rsort( $numbers, SORT_NUMERIC );
        $key=rand( 0, count( $ops )-1 );

        $question="{$numbers[0]} {$ops[ $key ]} {$numbers[1]}";

        switch( $ops[ $key ] ){
            case '+': $answer=( $numbers[0] + $numbers[1] ); break;
            case '-': $answer=( $numbers[0] - $numbers[1] ); break;
            case '/': $answer=( $numbers[0] / $numbers[1] ); break;
            case 'x': $answer=( $numbers[0] * $numbers[1] ); break;
        }
        $obj=new stdClass;
        $obj->question=$question;
        $obj->answer=$answer;

        return $obj;
    }

    /* Calculate question and answer */
    $captcha=call_user_func( 'challenge', false, 1, 50, 1, 30 );
    $question=$captcha->question;
    $answer=$captcha->answer;

    /* Set the session variable that will be tested for */
    $_SESSION['simple_maths_captcha']=$answer;

    /* Render an image with this challenge */
    $oImg = @imagecreate( 80, 30 ) or die("unable to create image");
    $background = imagecolorallocate( $oImg, 255, 255, 255 );
    $colour = imagecolorallocate( $oImg, 0, 0, 0 );

    imagestring( $oImg, 4, 5, 5,  $question, $colour );
    imagepng( $oImg );
    imagedestroy( $oImg );
?>

如果您将上述代码保存为“captcha.php”,则可以使用标准图像标签在 html 中引用该图像。

<img src='captcha.php' alt='' width=80 height=30 />

( 或者,通过在您的 .htaccess 文件中使用类似于以下内容的重写规则 您可以将其称为标准 png 图像。有经验的编码人员可能会将此识别为 php 生成的图像,但是...)

htaccess rewrite
----------------
RewriteRule ^images/maths\.png$ /captcha.php [NC,L]

<img src='/images/maths.png' alt='' width=80 height=30 />

在您的 html 中,您仍然需要文本输入字段来接收答案,将图像添加到表单中的适当位置,然后在 php 中测试正确答案。所以,而不是:-

    if( intval( $human )!==5 ) {
        echo 'Anti-Spam verification failed';
        return false;
    }

你可以这样测试:-

    if( floatval( $human )!==floatval( $_SESSION['simple_maths_captcha'] ) ) {
        echo 'Anti-Spam verification failed';
        return false;
    }

我注意到在 jqBootstrapValidation.js 代码中,ajax 函数的数据类型设置为 json,而回调函数有一个数据参数。如果有错误,我将上面的代码更改为返回 json,如果表单处理正常,则返回 json 成功消息。我不使用 jQuery,所以也许我误解了 javascript 代码,但我想知道回调是否期望来自表单处理的 json 编码响应?毫无疑问,精通 jQuery 的人可以回答这个问题。

【讨论】:

  • 在这里再次感谢您的帮助。我尝试使用您的上述代码,并且电子邮件处理和发送都很好 - 但即使数学问题被错误地回答并且没有显示错误消息,它仍然会发送它。这让人相信问题出在 contact_me.js 文件中,而不是 php.ini 文件中。我知道一点js,但还不足以弄清楚这一点。看起来 js 是验证联系表单的东西,它是处理成功和错误消息的东西。我认为我们需要在本节中添加一些内容才能使其正常工作?还有其他想法吗?再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-23
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多