Question

I have a simple contact form where users input their data and the form sends it to 'mail.php' to be passed onto the email account there. The 'mail.php' file is in my root directory alongside 'index.html' and the problem I'm having is that I don't want users to be able to access http://mydomain.com/mail.php directly through their browser as this will just send a blank form and could be used to spam me. I'm getting really stressed trying to figure out a way that will only allow 'mail.php' to be accessed by the form. This is how I have the form set up:

<form method="post" action="mail.php">
    <div class="row half">
        <div class="6u"><input type="text" required autocomplete="off" name="name" placeholder="Name" /></div>
        <div class="6u"><input type="email" required autocomplete="off" name="email" placeholder="Email" /></div>
    </div>
    <div class="row half">
        <div class="12u"><textarea name="message" required placeholder="Message" rows="6"></textarea></div>
    </div>
    <div class="row">
        <div class="12u">
            <ul class="actions">
                <li><input type="submit" class="button" value="Send Message" /></li>
            </ul>
        </div>
    </div>
</form>

Then my 'mail.php' file is set up like so, and the success header is an html page with a few lines of text that lets the user know their email has sent, then redirects them back to http://mydomain.com after 5 seconds.

<?php
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
$formcontent=" From: $name \n Message: $message";
$recipient = "me@email.com";
$subject = "Contact Form";
$mailheader = "From: $email \r\n";
mail($recipient, $subject, $formcontent, $mailheader) or die("Error!");
header("Location: success");
exit;
?>

I've fiddled around with .htaccess and countless other things but nothing I do seems to work - it will either block the page completely (so that the form can't access it either) or not block it at all. I've also had a look at this https://stackoverflow.com/a/409515/3366954 but couldn't figure out how to get that to work either. I'm quite new to html and php but everything else until now I've managed to figure out. What am I missing this time?

Was it helpful?

Solution

Just add some validation to your PHP script. For example:

<?php
if(isset($_POST['name'], $_POST['email'], $_POST['message'])) {
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $formcontent=" From: $name \n Message: $message";
    $recipient = "me@email.com";
    $subject = "Contact Form";
    $mailheader = "From: $email \r\n";
    mail($recipient, $subject, $formcontent, $mailheader) or die("Error!");
    header("Location: success");
    exit;
}
?>

This will prevent any blank submissions, without requiring you to filter by the referring page. As a general rule, you should always validate user input, anyway, because it is a source of all sorts of trouble (hacking, errors, generally unexpectedly behavior).

OTHER TIPS

You cannot block the browsers from accessing the page - when a browser submits a form, it navigates to the .php file just as if the user entered its URL directly, with the only difference being that there is POST data submitted as well.

If you want to prevents spam, you need to make sure your input is correct. Make sure the required fields are set. (Yes, Ed Cottrell was faster, see his answer)

What you need to do is validate your inputs and if they aren't correct, don't send the form.

if (empty($_POST['name'])) {
    $errors[] = "You need to enter your name";
}
if (empty($_POST['email'])) {
    $errors[] = "You need to enter your email";
}
if (empty($_POST['message'])) {
    $errors[] = "You need to enter a message";
}

if (isset($errors)) {
    echo "There were errors sending your email:";
    echo "<ul>";
    foreach ($errors as $error) {
        echo "<li>$error</li>";
    }
    echo "</ul>";
}
else {
    // send message
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top