Honeypot processor

Hi,

will you please go over this mailer code, and see if it’s ok, and secure.
I tested it, and instead of receiving the mail with the data on the form I got the message that was intended for the submitter.

I used one email to receive the mail, and used another email as the sender of the form, but both got the messahe intended for the sender.

I know I have to hide the honeypot address field, I left it visible for testing.

Thank you

The html form

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
    <div class="row">
        <div class="col-md-9">
            <div class="well well-sm">
                <form method="POST" action="mailer.php" onsubmit="return validate_2()">
                <div class="row">
                    <div class="col-md-6">
                        <div class="form-group">
                            <label for="name">Name</label>
                            <input type="text" class="form-control" id="name" name="name" maxlength="19" placeholder="Nome" required="required" />
                        </div>
                        <div class="form-group">
                            <label for="lastname">Last Name</label>
                            <input type="text" class="form-control" id="lastname" name="lastname" maxlength="27" placeholder="Last Name" required="required" />
                        </div>
                        <div class="form-group">
                            <label for="address">Address</label>
                            <input type="text" class="form-control" id="address" name="address" maxlength="27" placeholder="address" />
                        </div>
                        <div class="form-group">
                            <label for="email">Email</label>
                            <div class="input-group">
                                <span class="input-group-addon"><span class="glyphicon glyphicon-envelope"></span>
                                </span>
                                <input type="email" class="form-control" id="email" name="email" maxlength="54" placeholder="Email" required="required" />
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="phone">Phone</label>
                            <input type="text" class="form-control" id="phone" name="phone" maxlength="19" placeholder="Phone - land or mobile" required="required" />
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="form-group">
                            <label for="message">Message</label>
                            <textarea id="message" name="message" class="form-control" rows="6" cols="25" required="required" placeholder="Message"></textarea>
                        </div>
                        <div class="form-group">
                            <label for="solutioncon">Please write the total of 9+7+3</label>
                            <input type="text" class="form-control" id="solutioncon" name="solutioncon" maxlength="2" placeholder="type solution" required="required" />
                        </div>
                    </div>
                    <div class="col-md-12">
                        <button type="submit" class="btn btn-primary pull-right" id="btnContactUs">Send Message</button>
                    </div>
                </div>
                </form>
            </div>
        </div>
    </div>
  </body>
</html>

The mailer.php file

<?php
//MAIL HEADER INFORMATION
$EmailFrom = "site.com";
$EmailTo = "info@site.com";
$Subject = "message from site";
 
// NOW TEST FOR FIELDS THAT ARE REQUIRED
$required = array(); // ADD YOUR FIELDS AS NEEDED
$all_okay = TRUE;
foreach ($required as $key) {
   if ($clean_post["$key"] == '') {
      echo "<br/>$key is a required field\n";
      $all_okay = FALSE;
   }
}
 
// TEST FOR MISSING INPUT
if (!$all_okay) {
   $referer = $_SERVER['HTTP_REFERER'];
   echo "<br /><strong><a href=\"$referer\">Please click to go back, and fill the required fields!</a></strong>\n";
   die();
}
 
// PREPARE THE DATA 
$name = Trim(stripslashes($_POST['name']));
$lastname = Trim(stripslashes($_POST['lastname']));
$address = Trim(stripslashes($_POST['address']));//honeypot checking
$email = Trim(stripslashes($_POST['email']));
$phone = Trim(stripslashes($_POST['phone']));
$message = Trim(stripslashes($_POST['message']));
$solutioncon = Trim(stripslashes($_POST['solutioncon']));


// PREPARE EMAIL BODY TEXT
$body = '';
$body .= "Dear " . $name . " " . $lastname . " this is copy of your message. \n
We will reply asap." . "\n \n"; // THIS IS TO HAVE PERSONALIZED MESSAGE
foreach ($clean_post as $key => $value) {
   $body .= $key . ': ' . $value . "\r\n";//aggiunto \r
}

$submitter = $_POST["email"];
$site = "no-reply@site.com";

/////////
if($address)
    $error = "Your message could not be sent. It has been flagged as spam. If error, please <a href='javascript:history.back(1)'>go back and try again</a>.";
    else {
// send email 
$success = mail($EmailTo, $Subject, $body, "From: <$EmailFrom>");
           mail($submitter, $Subject, $body, "From: <$site>");
    }

// redirect to success page
if ($success){
header( "Location: http://site.com/thankyou_con.php" );
}

else
{print "There has been a technical problem, please resend, thank you."; }
?>

Emails from your site should always be sent FROM a domain email address, so in both case it should be from $site. You can add Reply-To headers so when you click reply in your email client, the address is correct for each type of email. Something like this.

/////////
    $Admin_headers = "From: \"$EmailFrom\" <$site>\r\n";
    $Admin_headers .= "Reply-To: \"$name\" <$submitter>\r\n";
    
    $Submitter_headers = "From: \"$EmailFrom\" <$site>\r\n";
    $Submitter_headers .= "Reply-To: \"$EmailTo\" <$EmailTo>\r\n";
 
if($address){
    $error = "Your message could not be sent. It has been flagged as spam. If error, please <a href='javascript:history.back(1)'>go back and try again</a>.";
} else {
// send email 
$success = mail($EmailTo, $Subject, $body, $Admin_headers);
           mail($submitter, $Subject, $body, $Submitter_headers);
}

Looking again at your code I see a number of things missing like your required array values or the clean post array being built or any other validation, so there was quite a bit missing. I also thought it would be nice to make two different body sections of the email. Anyway you will notice a number of changes to this version.

<?php
//MAIL HEADER INFORMATION
$EmailFrom = "site.com";
$EmailTo = "info@site.com";
$Subject = "message from site";

if(isset($_POST['name'])):

    // NOW TEST FOR FIELDS THAT ARE REQUIRED
    $required = array('name','lastname','email','phone','message','solutioncon'); // ADD YOUR FIELDS AS NEEDED
    $all_okay = TRUE;
    $clean_post = array();
    $error = '';
    foreach($required as $key) {
        if (empty($_POST[$key])){
            $error .= "<br/>$key is a required field\n";
            $all_okay = FALSE;
        }else{
            $clean_post[$key] = $_POST[$key];
        }
    }
        
    // TEST FOR MISSING INPUT
    if (!$all_okay){
    $error .= "<br /><strong>Please click to go back, and fill the required fields!</strong>\n";
            
    //Name
    }elseif(!preg_match("/^[a-zA-Z' -]{2,}/", trim($_POST['name']))){
    $error .= "<br /><strong>Name does not pass validation</strong>\n";
    
    //Lastname
    }elseif(!preg_match("/^[a-zA-Z' -]{2,}/", trim($_POST['lastname']))){
    $error .= "<br /><strong>Lastname does not pass validation</strong>\n";
    
    //Email
    }elseif(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)){
    $error .= "<br /><strong>Please enter a valid email!</strong>\n";
    
    //Solution 
    }elseif(!is_numeric($_POST['solutioncon']) || $_POST['solutioncon'] != 17){
    $error .= "<br /><strong>Please enter a correct total amount.</strong>\n";
    
    //Phone
    }elseif(!preg_match('/^[0-9 \-]+$/i', $_POST['phone'])){
        $error .= "<br /><strong>Phone number can only have numbers, dashes and spaces.</strong>\n";
    
    //Message    
    }elseif(empty($_POST['message']) || strlen($_POST['message']) < 2){
        $error .= "<br /><strong>Please add a message.</strong>\n.";
        
    //honeypot checking    
    }elseif(!empty($_POST['address'])){
        $error .= "Your message could not be sent. It has been flagged as spam.";
    
    //Continue if no error
    }elseif(empty($error)){ 
        
        // PREPARE THE DATA 
        $name = Trim(stripslashes($_POST['name']));
        $lastname = Trim(stripslashes($_POST['lastname']));        
        $email = Trim(stripslashes($_POST['email']));
        $phone = Trim(stripslashes($_POST['phone']));
        $message = Trim(stripslashes($_POST['message']));
                    
                    
        // PREPARE EMAIL BODY TEXT
        $body = '';
        $Admin_body = '';
        
        $body .= "Dear " . $name . " " . $lastname . ",\r\nThis is copy of your message. \n
        We will reply asap." . "\r\n\r\n"; // THIS IS TO HAVE PERSONALIZED MESSAGE
        
        $Admin_body .= "Dear Admin,\r\n
        This email is to inform of a contact us message from " . $EmailFrom . ".\r\n\r\n"; // THIS IS TO HAVE PERSONALIZED MESSAGE
        foreach ($clean_post as $key => $value) {
            if($key != "solutioncon"):
                $body .= ucfirst($key) . ': ' . $value . "\r\n";//aggiunto \r
                $Admin_body .= ucfirst($key) . ': ' . $value . "\r\n";//aggiunto \r 
            endif;
        }
        
        $submitter = $_POST["email"];
        $site = "no-reply@site.com";
        
        /////////
        $Admin_headers = "From: \"$EmailFrom\" <$site>\r\n";
        $Admin_headers .= "Reply-To: \"$name\" <$submitter>\r\n";
        
        $Submitter_headers = "From: \"$EmailFrom\" <$site>\r\n";
        $Submitter_headers .= "Reply-To: \"$EmailTo\" <$EmailTo>\r\n";
        
        
        // send email 
        $success = mail($EmailTo, $Subject, $Admin_body, $Admin_headers);
                   mail($submitter, $Subject, $body, $Submitter_headers);
        
        // redirect to success page
        if (isset($success) && $success === true){
            header( "Location: http://site.com/thankyou_con.php" );
            exit;
        }else{
            $error .= "<br />There has been a technical problem, please resend, thank you."; 
        }
    }
    // Add the go back link if error
    if(!empty($error)){
        $error .= "<br /><br />If error, please <a href='javascript:history.back(1)'>go back and try again</a>.<br />";
    }        
endif;
?>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
    <div class="row">
        <div class="col-md-9">
            <div class="well well-sm">
            <?php
                if(isset($error)){echo $error;}
                //if(isset($Admin_body)){echo nl2br($Admin_body);}
                //if(isset($body)){echo nl2br($body);}
            ?>
            </div>
        </div>
    </div>
  </body>
</html>

Another thing you might want to consider adding is measuring how long it takes for someone to complete and submit the forum, if the form is filled in and submitted in say less then 10 seconds then chances are it’s a bot and so they’d need to be shown a “something went wrong” error, perhaps with flood control so that the session they used can’t submit again for say 30 seconds.

For the threshold time for the bot detection you need to decided in what time you feel a human couldn’t fill the form in and submit it quicker then.

Thank you both.

@SpacePhoenix
Yes I had thought of that, but wanted to go step by step, that would have been my next question in how adding that measure too to the same, as having both the hidden field, and the time restriction.

@Drummin
Thanks for the revised code.
I have rechecked it few times, in editing the lines concerning the site, putting the actual site info:

$EmailFrom = "site.com";
$EmailTo = "info@site.com";
$Subject = "message from site";

and here

header( "Location: http://site.com/thankyou_con.php" );

leaving only the $site variable as it is

$submitter = $_POST["email"];
$site = "no-reply@site.com";

/////////
$Admin_headers = "From: \"$EmailFrom\" <$site>\r\n";
$Admin_headers .= "Reply-To: \"$name\" <$submitter>\r\n";

$Submitter_headers = "From: \"$EmailFrom\" <$site>\r\n";
$Submitter_headers .= "Reply-To: \"$EmailTo\" <$EmailTo>\r\n";

1 - when clicking submit it goes to the mailer file (browser address bar > site.com/mailer.php), and is a blank (white) screen, and no message is received in either of the mailboxes.
2 - I have put

    <div class="well well-sm">
    <?php
        if(isset($error)){echo $error;}
        //if(isset($Admin_body)){echo nl2br($Admin_body);}
        //if(isset($body)){echo nl2br($body);}
    ?>

right after the div as per your code, and before the opening form tag; did I do it correctly?
3 - Am I correct to edit this piece

$Admin_body .= "Dear Admin,\r\n
This email is to inform of a contact us message from " . $EmailFrom . ".\r\n\r\n"; // THIS IS TO HAVE

like this

        $Admin_body .= "Dear Admin,\r\n
        This email is to inform of a contact us message from " . $EmailFrom . ".\r\n
some extra customization of the message \r\n"; // THIS IS TO HAVE

I apologize I might have omitted some info:
the html has a js in the head section for the solutioncon field verification, might that be in conflict with your code?
Although I removed it, and tested without it, and get the same blank page.
The js is:

<script>
function validate_2() { 
  if (document.getElementById('solutioncon').value.replace(/\s/g, "").toLowerCase() != "19") { 
   alert("Please type correct result - psss ... need a hint? First digit 1 second digit 9"); 
   return false; 
  } 
} 
</script>

Thank you

Haa, I see I put 17 instead of 19 for the solution… Please change that. Still you should have seen the error message.

$_POST['solutioncon'] != 19

Besides replacing a few values, is mailer.php the same as I posted?

[quote=“keneso, post:5, topic:112426”]
2 - I have put

&lt;div class="well well-sm"&gt;
&lt;?php
    if(isset($error)){echo $error;}
    //if(isset($Admin_body)){echo nl2br($Admin_body);}
    //if(isset($body)){echo nl2br($body);}
?&gt;

right after the div as per your code, and before the opening form tag; did I do it correctly?
[/quote]You’ll notice on my copy I added the <html lang="en"> etc so messages are echoed on mailer.php in a proper page. This echo code was not intended to go on the form page.

The only other thing I can see is maybe changing the success condition line from

// redirect to success page
        if ($success) && $success === true){ 

To simply

// redirect to success page
        if ($success){

As far as adding other checks, the time check is good. I also like saving number of attempts to session. A bot can hit this form say 100 times but if you limit the number of times to say 5 attempts (for someone that really has a problem filling out the form), then that will also stop a lot of that.

MAN I don’t like the fact that they have added the edit post time limit to this forum!!!

I meant to correct my post above to read

if (isset($success) && $success === true){

To simply

// redirect to success page
        if ($success){

Thank you for your patience.

Besides replacing a few values, is mailer.php the same as I posted?

Yes I only changed the site infos.

It seems the problem is with the number verification.
I tried both with the former js in the head, and onsubmit in the form tag, and also removing them; in both cases when inputting the correct value the form is processed, else it brings up the mailer blank page.

Another peculiarity I noticed is that on my previous trials I had removed the “phone” field from the required fields array, and when leaving it blank no warning came out.
Now it keeps asking for the phone no matter what.
I have removed the required from the input in the form as well like this.

<input type="email" class="form-control" id="email" name="email" maxlength="54" placeholder="Email" required="required" />
<input type="text" class="form-control" id="phone" name="phone" maxlength="19" placeholder="Phone - land or mobile" />

Some extra info for you: I am using bootstrap.js in the page.

To sum it up, I have no problem in removing the number verification field, and would love to add the time, and attempts to it, if you kindly would help me with it.

Thanks again.

edit
I have not tried
if (isset($success) && $success === true){

To simply

// redirect to success page
if ($success){

Yes you saw my post regarding the error I made. I trust you’ve corrected that. Also I hope you are now echoing errors on mailer.php, not the form page.

Does your form page have a php extension, e.g. ContactUs.php? It would need to be if you were to track TIME.

Thank you.

I meant to say that the problem is there even after the correction from 17 to 19.
No errors are echoed if I input the wrong number, just the blank page.

Originally page was html, but by putting the error echo in it by mistake I had made it into php, so now is php.

If you’d like I have put it online here
holytablets dot org/gallery_test/index.php
and there is a zip package of it here
holytablets dot org/gallery_test/gallery_test.zip

edit

Sorry I just put it up w/o testing, and now I did, and while the bootstrap required field message does not show for the phone (removed the require from input in form), if you leave it blank it returns the blank page.
Also I have forgotten the than you page in the zip file is thanks.php (practically copy of the index.php with thank you)

You are missing this at the bottom of contact-process.php after closing php tag, e.g. ?> Add this and you should see messages.

<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
    <div class="row">
        <div class="col-md-9">
            <div class="well well-sm">
            <?php
                if(isset($error)){echo $error;}
                //if(isset($Admin_body)){echo nl2br($Admin_body);}
                //if(isset($body)){echo nl2br($body);}
            ?>
            </div>
        </div>
    </div>
  </body>
</html>

I hope you don’t mind, but I had a little fun making this modification.

  • First I modified contact-process.php so instead of showing a blank
    page, your full template is loaded so it looks like you didn’t leave
    the site. Looks much better. I added the anchor #contact to the
    form action line so when you click submit, you are viewing the
    message section (where the form would be on index.php).

  • I made it so your solutioncon numbers are randomly generated, the
    total is saved to session and the numbers are displayed in the form.
    Processing is adjusted to check for the session value for
    comparison. Each time the form reloads these numbers are randomly
    generated again.

  • POST values are saved to session and echoed in the form on retry, not
    counting solutioncon as that will be different each time.

  • I added a “number of attempts” count saved to session, that gets
    upped each time the form loads. Currently set to 5. The form will
    not be shown if this limit is reached. User would need to close
    browser, clear cache to clear the session. As I mentioned it is set
    to 5 attempts so adjust amount to your liking. Note: There is a line
    commented out that resets this count to 1 to be used for testing so
    this doesn’t hamper development.

  • I added a time check of 15 seconds for first attempt and 2 seconds
    thereafter. There are a fair number of form fields to fill out, plus
    the math so 15 seconds seemed like a reasonable amount of time to set
    the minimum for the first attempt. Regardless of the form field that
    might need to be fixed, they will need to do the math, so a 2 second
    minimum for retry’s seemed good. Again adjust to your liking.

  • I edited the validation for phone, so if not empty, do the check, if
    empty don’t worry about it.

Anyway that’s generally the scope of the changes made.

Note: You really need to adjust the label font color as it is hard to read those numbers.
contact-process.php (12.6 KB)
index.php (10.8 KB)

Sure I mind you improving it, and going out of your way to help me! :wink:

Seriously, thank you very much.

I loaded your files, but it doesn’t go thru, it keeps giving error:

Please enter a correct total amount.
If error, please go back and try again.

And I tried it several times (closing and clearing browser to be sure), I am not a math genius, but I think that at least a couple of times I must have got the sum right.

Also when clicking the go back link the form is cleared, would it be possible to keep the good fields without clearing them?

Note: There is a line
commented out that resets this count to 1 to be used for testing so
this doesn’t hamper development.

Not sure if I have to uncomment it for testing, or leave it commented; anyhow I tried both ways, and keep getting the error.

Note: You really need to adjust the label font color as it is hard to read those numbers.

Yes, sorry for the trouble, being a test I didn’t bother, but now I fixed it.

It sounds like you didn’t replace the index page or maybe contact-process as the POST values are set to session on contact-process then echoed on the index form so you should be seeing whatever values you entered.

As I mentioned, those numbers are hard to read because of the font color. I highlight them with my mouse so I can see them.

Now if one of these two pages was not replaced, then it is doubtful you will get the correct answer as the new number is generated on the index page, saved to session then compared on the processing page.

The line I was talking about is

            //****Reset for testing****\\
            //$_SESSION['attempts']=1;

By uncommenting $_SESSION['attempts']=1; the number of attempts will always be set to one when you reload the page.

Thank you for your patience.

It sounds like you didn’t replace the index page or maybe contact-process

Like said I uploaded both your files without any change whatsoever; unless an ftp fail (no such warning from ftp client) the files are the same.
Did you revisited the test page, as I had changed the color for seeing the label, it’s orange now.

To be sure I just re-downloaded the both files, and uploaded them again, but still can’t go thru.
Will you please revisit the page:
holytablets dot org/gallery_test

Thanks for the uncommenting confirmation, indeed I had done so, just wanted to be sure I had not misunderstood.

I did visit the page and from what I can see on the index, input fields now have the attribute value=“” so it looks like the updated version. Can you either post contact-process or zip up a new copy to holytablets dot org/gallery_test/gallery_test.zip? It would be helpful to see both pages you are currently using.

Sure.

new (yours)
holytablets dot org/gallery_test/gallery_test_sitepoint.zip
old one
holytablets dot org/gallery_test/gallery_test.zip

Thank you

Ahhh those files worked including echoing values to the form on retry and number check.
Maybe you need to remove your copies from the site and upload the new ones.

Thank you.

I had deleted the old files, and the zip is all there is there, save th bootstrap js folder.

I also tried a new subdirectory, same result; I will try directly in the root to see what happens, I’ll report back.

FYI I just copied the gallery_test_sitepoint folder to my server and ran index and it worked fine.