Hello,

So I am a php novice. The company I work for has been getting a lot of spam via our contact form lately so I need to secure it, which I have done with adding a hidden field that if the form is autofilled it will not send. But since it is hidden if a real person uses autofill there message will not go through. I tried putting in captchas, but could never get any of them to work.

Here is the form on the contact page

<form method="post" action="mailer">

        <div class="form">Name:<input class="input" type="text" name="name" /></div>
        <br>
        <div class="form">Organization:<input class="input" type="text" name="company" /></div>
        <br>
        <div class="form">E-Mail:<input class="input" type="email" name="email" /></div>
        <br>
        <div class="form">Phone:<input class="input" type="tel" name="phone" /></div>
        <br>
        <div class="form">Preference:<select class="input" size="1" name="contact_preference">
          <option class="input" selected="selected">E-Mail</option>
          <option class="input" >Telephone</option>
        </select>
      </div>
      <br class="antispam">
      <div class="form antispam" >Leave this blank<input class="input" type="text" name="url" /></div>
      <br>
      <div class="form">Subject:<input class="input" type="text" name="subject" /></div>
      <br>
      <div class="form">Message:<textarea class="textarea" style="resize:none;" name="message" ></textarea></div>
      <br>
      <div class="form"><input class="submit" type="submit" value=" SUBMIT " name="submit" /></div>
    </form>

and here is the code on the mailer page

if(isset($_POST['url']) && $_POST['url'] == ''){

  $youremail = 'name@company.com';

  $body = "CompanyName contact form submission:
  Name:  $_POST[name]
  Company: $_POST[company]
  E-Mail: $_POST[email]
  Phone Number: $_POST[phone]
  Contact Preference: $_POST[contact_preference]
  Subject: $_POST[subject]
  Message: $_POST[message]";

  if( $_POST['email'] && !preg_match( "/[\r\n]/", $_POST['email']) ) {
    $headers = "From: $_POST[email]";
  } else {
    $headers = "From: $youremail";
  }

  mail($youremail, $subject, $body, $headers);
  echo "The form you entered has been submitted. Thank you, " . $_POST[name] .", for your interest in <CompanyName>. ";
  echo "Contact <a href=\"mailto:name@company.com\"><name></a> if you would like further assistance.";
}else {
  echo "There was an error sending the data.<br /> ";
  echo "Please contact <name> at <a href=\"mailto:name@company.com\">name@company.com</a> with your information.";
}

This form does what it is supposed to for the most part, but anything can be in the fields or they can be left blank. Also, the subject will not populate the email subject field.

Here is what I need help with in a convinient list
1) Get subject from form to populate email subject field
2) Make fields required (and potentially validate them to what they should be)
3) More effective way to stop spam

Keep in mind I am a PHP novice, I only use the include function, everyhting else Ive used has been found online but can't get a lot of it to work properly.

Thank you for your help!

Recommended Answers

All 16 Replies

Member Avatar for diafol

A captcha is your best bet, but you could set up a 'prove that you're human' DIY field.

Probably the easiest way would be to show a simple calculation and ask for the answer. The actual answer could be stored in a hidden field and the results compred on the server after form submission. This is extremely easy to break or spoof, but it should stop automated spamming.

So you could do something like this:

<?php
$limits = range(0,9);
$num1 = array_rand($limits, 1);
$num2 = array_rand($limits, 1);

$show = $num1 . " + " . $num2 . " = ";
$ans = $num1 + $num2;
?>

<label for="calc"><?php echo $show;?></label><input id="calc" name="calc" />
<input type="hidden" name="calc_check" value="<?php echo $ans;?>" />

Then in your form handling routine, something like:

if(intval($_POST['calc']) === intval($_POST['calc_check']))...

Alternatively, you could store the answer in a session variable and compare with that. Simple but remember the caveats.

commented: Sir please use proper captcha for the same with Image support +0

I'm assuming I would remove the other hidden input I have then and replace it with this block of code?

But I really prefer to use something that isn't easily spoof, otherwise I might as well stick with what I already have.

And like I said, I would like to use a captch, but I could never get them to work. Don't know enough about php to be able to integrate it properly.

Member Avatar for diafol

@sinhaksaurabh

I appreciate why you downvoted the post, as this lightweight solution is not ideal and not one that I would normally recommend, but the OP did state that captcha solutions were proving problematic. I only suggested this as a stopgap until such a solution would become viable - and pointed out the limitations of a 'calculation-based' approach.

@Aiedail
Do you have a specific captcha solution in mind, e.g. reCaptcha ? If so, post the code you used to try to get it to work and we can have a look at what went wrong.

reCaptcha: http://www.google.com/recaptcha/whyrecaptcha
All you need are public and private keys and a file to accept form data (e.g. verify.php).
If you have a google account, you can get the keys, otherwise, sign up for a Google account.

For using reCaptcha with PHP: https://developers.google.com/recaptcha/docs/php

reCaptcha was the one I tried to load. I put the code in and I get "Input error: Invalid referer" above my submit button.

heres the form code

form method="post" action="mailer">
        <input name="subject_prefix" type="hidden" id="subject_prefix" value="Contact Form: " />
        <div class="form">Name:<input class="input" type="text" name="name" required/></div>
        <br>
        <div class="form">Organization:<input class="input" type="text" name="company" required/></div>
        <br>
        <div class="form">E-Mail:<input class="input" type="email" name="email" required/></div>
        <br>
        <div class="form">Phone:<input class="input" type="tel" name="phone" required/></div>
        <br>
        <div class="form">Preference:<select class="input" size="1" name="contact_preference">
          <option class="input" selected="selected">E-Mail</option>
          <option class="input" >Telephone</option>
        </select>
      </div>
      <br class="antispam">
      <div class="form antispam" >Leave this blank<input class="input" type="text" name="url" /></div>
      <br>
      <div class="form">Subject:<input class="input" type="text" name="inquiry" required/></div>
      <br>
      <div class="form">Message:<textarea class="textarea" style="resize:none;" name="message" required></textarea></div>
      <br>
      <div class="captcha">
        <?php
          require_once('includes/recaptchalib.php');
          $publickey = "my public key here";
          echo recaptcha_get_html($publickey);
        ?>
      </div>
      <br>
      <div class="form"><input class="submit" type="submit" value=" SUBMIT " name="submit" /></div>
    </form>

and then my mailer code is

?php

  require_once('includes/recaptchalib.php');
  $privatekey = "my private key here";
  $resp = recaptcha_check_answer ($privatekey,
                                $_SERVER["REMOTE_ADDR"],
                                $_POST["recaptcha_challenge_field"],
                                $_POST["recaptcha_response_field"]);

  if (!$resp->is_valid) {
    // What happens when the CAPTCHA was entered incorrectly
    die ("The reCAPTCHA wasn't entered correctly. Go back and try it again." .
         "(reCAPTCHA said: " . $resp->error . ")");
  } else {
      $youremail = 'myemail@company.com';

      $body = "TSD contact form submission:
      Name:  $_POST[name]
      Company: $_POST[company]
      E-Mail: $_POST[email]
      Phone Number: $_POST[phone]
      Contact Preference: $_POST[contact_preference]
      Subject: $_POST[inquiry]
      Message: $_POST[message]";

     $subject = $subject_prefix . $inquiry;
     $header = "From: \"" . $name . "\" <" . $email . ">\n";

      mail($youremail, $subject, $body, $header);
      echo "The form you entered has been submitted. Thank you, " . $_POST[name] .", for your interest in MyCompany. ";
      echo "Contact <a href=\"mailto:myemail@company.com\">MyName</a> if you would like further assistance.";
?>

Okay, my apologies. Ignore the error message I was getting. I set up the reCaptcha keys for my companys domain, but am doing my testing on my personal server due to the lack of space they have available on theirs.

I created keys for my domain, and I get the reCaptcha to show up, but upon form subbmission I am getting this error message

Parse error: syntax error, unexpected $end in /homepages/3/d288413952/htdocs/s-m/previews/contactTest/mailer.php on line 125

Line 125 is the blank line that follows my <?php include('includes/footer.php'); ?>

My Mailer page is set up like this

<?php
    if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip'))
        ob_start("ob_gzhandler");
    else
        ob_start();
?>
<?php $value = "Contact"; ?>
<?php include('includes/header.php'); ?>

Bunch of html content

<?php
  require_once('includes/recaptchalib.php');
  $privatekey = "my private key here";
  $resp = recaptcha_check_answer ($privatekey,
                                $_SERVER["REMOTE_ADDR"],
                                $_POST["recaptcha_challenge_field"],
                                $_POST["recaptcha_response_field"]);
  if (!$resp->is_valid) {
    // What happens when the CAPTCHA was entered incorrectly
    die ("The reCAPTCHA wasn't entered correctly. Go back and try it again." .
         "(reCAPTCHA said: " . $resp->error . ")");
  } else {
      $youremail = 'myemail@company.com';
      $body = "TSD contact form submission:
      Name:  $_POST[name]
      Company: $_POST[company]
      E-Mail: $_POST[email]
      Phone Number: $_POST[phone]
      Contact Preference: $_POST[contact_preference]
      Subject: $_POST[inquiry]
      Message: $_POST[message]";
     $subject = $subject_prefix . $inquiry;
     $header = "From: \"" . $name . "\" <" . $email . ">\n";
      mail($youremail, $subject, $body, $header);
      echo "The form you entered has been submitted. Thank you, " . $_POST[name] .", for your interest in MyCompany. ";
      echo "Contact <a href=\"mailto:myemail@company.com\">MyName</a> if you would like further assistance.";
?>

more html content

<?php include('includes/footer.php'); ?>
Member Avatar for diafol

OK. So I assume you've placed your unique public key in the appropriate place:

  <div class="captcha">
    <?php
      require_once('includes/recaptchalib.php');
      $publickey = "my public key here"; //HERE!!!!
      echo recaptcha_get_html($publickey);
    ?>
  </div>

If you are signed into Google, go here:

https://www.google.com/recaptcha/admin/create

Check that the URL that you've specified for your site is correct. If not, it won't work. I'm assuming that the recaptchalib.php file is in the right place or it should flag an error.

All the keys are correct, and the recaptchalib is in the appropriate place.

The onyl way my key would be correct is if I need to set it up for the subfolder my test sights are in.

I created the keys for myurl.com

but the contact form is at myurl.com/previews/contactTest/contact.php

would that be the source of my problem?

Member Avatar for diafol

OK, so from what I gather everything is fine on the form, but when you submit your get the $end error. This is probably due to a missing brace in a conditional statement:

if (!$resp->is_valid) {
    // What happens when the CAPTCHA was entered incorrectly
    die ("The reCAPTCHA wasn't entered correctly. Go back and try it again." .
         "(reCAPTCHA said: " . $resp->error . ")");
  } else {
      $youremail = 'myemail@company.com';
      $body = "TSD contact form submission:
      Name:  $_POST[name]
      Company: $_POST[company]
      E-Mail: $_POST[email]
      Phone Number: $_POST[phone]
      Contact Preference: $_POST[contact_preference]
      Subject: $_POST[inquiry]
      Message: $_POST[message]";
     $subject = $subject_prefix . $inquiry;
     $header = "From: \"" . $name . "\" <" . $email . ">\n";
      mail($youremail, $subject, $body, $header);
      echo "The form you entered has been submitted. Thank you, " . $_POST[name] .", for your interest in MyCompany. ";
      echo "Contact <a href=\"mailto:myemail@company.com\">MyName</a> if you would like further assistance.";
?>

Add a '}' just before the close php tag:

      echo "Contact <a href=\"mailto:myemail@company.com\">MyName</a> if you would like further assistance.";
  }
?>

Beautiful, it now submits fine.

Just need to fix two more things and it will be ready for upload.

If you submit the form with the invalid captcha, can I just have that validate as wrong and the user can try again without having to reinput all of their info?

Currently it just loads the page up until i get the

The reCAPTCHA wasn't entered correctly. Go back and try it again.(reCAPTCHA said: incorrect-captcha-sol)

error message, and then does not load any of the rest of the page.

and as for the actual form, how can I get the email that is sent to populate the from field and the subject field.

The emails received have blanks for those values.

And I appreciate the assistance. You have been a fantastic help.

Member Avatar for diafol

If you submit the form with the invalid captcha, can I just have that validate as wrong and the user can try again without having to reinput all of their info?
Currently it just loads the page up until i get the
The reCAPTCHA wasn't entered correctly. Go back and try it again.(reCAPTCHA said: incorrect-captcha-sol)
error message, and then does not load any of the rest of the page.

Sure, all you need to do is to have a header() redirect back to the original form page:

  <?php
  require_once('recaptchalib.php');
  $privatekey = "...";
  $resp = recaptcha_check_answer ($privatekey,
                                $_SERVER["REMOTE_ADDR"],
                                $_POST["recaptcha_challenge_field"],
                                $_POST["recaptcha_response_field"]);

  if (!$resp->is_valid) {
    // What happens when the CAPTCHA was entered incorrectly
    header("Location: formpage.php"); //whatever the page is called
  }
  ?>

However, if you want your data in tact in the form, that's a little more tricky. You have certain options. You can use cookies to store the data or use session variables. I'm more of a session kind of guy, BUT, be aware that sessions must be registered on EVERY page. This is quite straight forward though. Simply add this line:

<?php
session_start();

To the top of EVERY page. This is especially important if you have a login system.

Now that you have session data available, we can begin storing and then retrieving the form data:

STORING
  <?php
  session_start();
  require_once('recaptchalib.php');
  $privatekey = "6Le4feYSAAAAAB4ORq0ciN1Q-7CbOPy-tKzfpR2C";
  $resp = recaptcha_check_answer ($privatekey,
                                $_SERVER["REMOTE_ADDR"],
                                $_POST["recaptcha_challenge_field"],
                                $_POST["recaptcha_response_field"]);

  if (!$resp->is_valid) {
      $_SESSION['bad_data'] = $_POST; //simple store
      header("Location: untitled.php");
      exit();
  }
  //carry on here with processing email
RETRIEVING

This is a bit more involved.

<?php
session_start();
    if(isset($_SESSION['bad_data'])){
        //Set last known values for form on failed reCaptcha
        $field1 = $_SESSION['bad_data']['field1'];  
        $field34 = $_SESSION['bad_data']['field34'];
        if(isset($_SESSION['bad_data']['checkbox3'])){
            $checkbox3 = 'checked="checked"';   
        }else{
            $checkbox3 = '';
        }
        unset($_SESSION['bad_data']); //kill off - no longer req'd
    }else{
        //set up default values for the form if not redirected from failed reCaptcha
        $field1 = '';
        $field34 = '';
        $checkbox3 = 'checked="checked"';   
    }
?>

The fields above are made up, but I hope you get the idea. All text fields are sent on submission, but checkbox POST variables only exist if they are checked, so you must check for their existence directly.

Your html for will then need to look something like this:

  <form method="post" action="verify.php">
    <input name="field1" value="<?php echo $field1;?>" />
    <input name="field34" value="<?php echo $field34;?>" />
    <input name="checkbox3" type="checkbox" <?php echo $checkbox3;?> />
    <?php
      require_once('recaptchalib.php');
      $publickey = "...";
      echo recaptcha_get_html($publickey);
    ?>
    <input type="submit" />
  </form>

That's the simplest way I can think of to do it. Let's look at that first. Come back to the mailing issue later. It can be done easily enough.

Alright. Followed your instructions added the code. Here is what the php portion looks like (I didn't change the form at all so not reposting it)

<?php
  if(isset($_SESSION['bad_data'])){
      //Set last known values for form on failed reCaptcha
      $name = $_SESSION['bad_data']['name'];
      $company = $_SESSION['bad_data']['company'];
      $email = $_SESSION['bad_data']['email'];
      $phone = $_SESSION['bad_data']['phone'];
      $inquiry = $_SESSION['bad_data']['inquiry'];
      $message = $_SESSION['bad_data']['message'];

      echo "<p style=\"color: red;\">*Values do not match. Please try again. </p>";

      unset($_SESSION['bad_data']); //kill off - no longer req'd
  }else{
      //set up default values for the form if not redirected from failed reCaptcha
      $name = '';
      $company = '';
      $email = '';
      $phone = '';
      $inquiry = '';
      $message = '';
  }
?>

Everything repopulates except the message portion, but I'm assuming that is because it is a textarea not an input?

Member Avatar for diafol

Ok, it depends how you're passing the data to the field:

Incorrect:

<div class="form">Message:<textarea class="textarea" style="resize:none;" name="message" value="<?php echo $message;?>" required></textarea></div>

Correct:

<div class="form">Message:<textarea class="textarea" style="resize:none;" name="message" required><?php echo $message;?></textarea></div>

If you still can't get any joy, echo the $message variable somewhere - or the $_POST['message'] in the verify.php file (this will probably stop redirect, but at least you can see what's there). Also echo the $_SESSION['bad_data']:

print_r($_SESSION['bad_data']);

That will give you all the contents of the $_SESSION['bad_data'] array.

Also be aware that you need to clean this input from scripts and any other html tags if you intend on storing it in a DB. All data input should be regarded as suspect. If using a DB, mysqli and PDO utilise 'parameterised binding', whereas the soon-to-die mysql depends upon mysql_real_escape_string().

Thanks. That worked. I don't plan on doing anything with a database until I can actually learn php more indepth. Adding databases adds a lot of security issues if you don't know what your doing.

All that's left is populating the from and subject field of the email.

Member Avatar for diafol

OK, it that it or is there something else? If not, 'Mark Question Solved'

The last thing from the original question is I need to get the subject and email from the form to populate the from and subject fields of the email that is sent.

Member Avatar for diafol
$body = "CompanyName contact form submission:
Name:  $_POST[name]
Company: $_POST[company]
E-Mail: $_POST[email]
Phone Number: $_POST[phone]
Contact Preference: $_POST[contact_preference]
Subject: $_POST[subject]
Message: $_POST[message]";

Will not work as you need to use braces for array items within double quotes:

$body = "CompanyName contact form submission:
Name:  {$_POST['name']}
Company: {$_POST['company']}
E-Mail: {$_POST['email']}
...

Which issues are you having with sending email? You can retrieve all the fields from the form, right? So you can clean them up and create an email script can't you? There are examples in the php.net manual if you're not sure on how to do this.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.