I have a simple contact form for a restaurant that's then emailed when submitted. What are some things I can do to ensure the form isn't abused? Such as a user sending multiple emails over and over, or it being hijacked to send spam elsewhere.

Here's the php script:


    $name = $_POST['name'];
    $organization = $_POST['org'];
    $phone = $_POST['phone'];
    $email = $_POST['email'];
    $date = $_POST['datepicker'];
    $guests = $_POST['guests'];
    $comments = $_POST['comments'];
    $events = $_POST['events'];

    // A copy of this event email will go to the user who made the request
    $recipient = "$email";
    // Email address of who this email will appear to be from
    // This email address must exist on the server or it may not be sent through
    $from      = "no-reply@website.com";
    // Email subject line
    $subject   = "Private Event";
    // The name that will show for the 'from' address above
    $headers   = "From: Restaurant <$from>\r\n";
    // Address of the event planner. Who this form should be sent to.
    $headers  .= "Bcc: mgmt@website.com \r\n";
    $headers  .= "MIME-Version: 1.0\r\n";
    $headers  .= "Content-Type: text/html; charset=ISO-8859-1\r\n";

    $msg = '<style type="text/css">body{background:#cccccc;}table{width:400px;font-family: verdana;font-size:11px;color:#333333;border-width:1px;border-color:#666666;border-collapse: collapse;}'.
        'table td{width:50%;border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #eeeeee;}'.
        '<center><div style="width:440px;background:black;"><br/><h1>3 Fires Lounge<h1><h3> - Private Event - </h3>'.
        '<tr><td><b>Date of Event</b></td><td>'.$date.'</td></tr>'.
        '<tr><td><b>Guest Count</b></td><td>'.$guests.'</td></tr>'.
        '<tr><td><b>Event Type</b></td><td>'.$events.'</td></tr>'.
        '<tr><td colspan="2"><b>Additional Comments:</b><br/><br/>'.$comments.'</td></tr></table><br/><br/></div></center>';

    //Address in last parameter should match the $from address above
    $success = mail($recipient, $subject, $msg, $headers, '-f no-reply@website.com');

    // Redirect to home page after 5 seconds
    header( "refresh:5;url=../" );


You can store the IP address of the user who is using the form and the time at which the form is submitted. When the form is then submitted again, you can check the time difference between now and the last time the form was submitted, and if that time is too short (and if the same user is again submitting the form), you can show an error for example.

You could also try to find and download a captcha generator, or just ask some simple random questions like "what is the color of the sun?" to ensure that a live person is filling in the form. Spam systems do get smarter and smarter though, so you may have to come up with some weird questions to ensure no spam robot is using your form.

Did this help? :)

Well, for one, don't put the POST data directly into the HTML message without so much as HTML escaping it. Otherwise anybody can put anything they want into this form and send it to anybody. I could easily use this script as spamming platform, which would no doubt end up getting your domain flagged and promptly spam-filtered by everybody. - Make sure that what you are getting is what you are expecting, and sanitize and filter out harmful things like HTML links and images.

As for ensuring that the form isn't abused by spam bots and such, you can't really "ensure" it, but you can do things to make it damn difficult to do. A very popular solution is to use a Captcha check; a simple test to determine if the user is in fact a human. The reCAPTCHA project is a fairly simple way to implement that.

Other methods often include things like using sessions/cookies/IP-addresses to force a delay, but those are all easily overcome by any half-way decent spammer. May not be a bad idea to implement a session or cookie variant of that, but don't rely on it.

I've used reCAPTCHA before, I can use that. I'll use a cookie as an extra layer of security against spamming (even if it's easily bypassed).

The problem when I use htmlspecialchars is that my output then has backslashes to escape any apostrophes. This makes the email look messy. So instead I'm using this:

$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_SPECIAL_CHARS);

Would this be sufficient?

The problem when I use htmlspecialchars is that my output then has backslashes to escape any apostrophes.

That's odd. That function shouldn't do anything like that. At worst it would replace the apostrophes with their equivalent HTML entity, but it woudldn't escape them. In any case, you can control how it handles quotes and apostrophes through the second parameter of the function. See the doc entry for the function. You may also want to consider using htmlentities instead. It's the same thing, but escapes all the HTML entities, not just a chosen few.

The filter_input line you suggested should have the very same effect htmlspecialchars has, although I'm not sure exactly what the differences in implementation is behind the scenes. (I doubt there is; it's most likely just run through that function with the default params.)