0

There's a lot of blank php email posts on here but none of them have solved this for me.

I tweaked this simple php code I found to simply email a specified email address (in this case, my client's email) with a feedback message from a customer on their website. Through testing, I could only get it to send emails when I didn't include the initial if statement as validation, but even then, the emails would have no subject or body.

contact.html

<form name="feedback" class="form-horizontal" role="form" action="send_form_email.php" method="post">
    <div class="form-group">
        <label for="inputName" class="col-sm-3 control-label">Name</label>
        <div class="col-sm-9">
            <input type="text" class="form-control" name="inputName" placeholder="Name"><br />
        </div>
    </div>

    <div class="form-group">
        <label for="inputEmail" class="col-sm-3 control-label">Email</label>
        <div class="col-sm-9">
            <input type="email" class="form-control" name="inputEmail" placeholder="Email"><br />
        </div>
    </div>

    <div class="form-group">
        <label for="inputMessage" class="col-sm-3 control-label">Message</label>
        <div class="col-sm-9">
            <textarea type="text" class="form-control" name="inputMessage" placeholder="Message"></textarea><br />
        </div>
    </div>

    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <input class="btn btn-default" type="submit" value="Submit">
        </div>
    </div>    
</form>

send_form_email.php

<?php

if($_SERVER['REQUEST_METHOD'] == "POST"){


// Contact subject
$name =$_POST['inputName']; 

// Details
$message=$_POST['inputMessage'];

// Mail of sender
$mail_from=$_POST['inputEmail']; 

// From 
$header="from: $name <$mail_from>";

// Enter your email address
$to ='test@gmail.com';
$send_contact=mail($to,$name,$message,$header);

// Check, if message sent to your email 
// display message "We've recived your information"
header("Location: http://wetzelscontracting.com/postcontact.html");
if($send_contact){
echo "We've recived your contact information";
}
else {
echo "ERROR";
}}
?>

Ok guys, long story, but Mailto isn't actually in the action attr, I removed it from the post.

Actually, I don't know what kind of frankenstein code I originally posted, but that was full of errors that are no longer there. Hopefully I posted the right code this time.

brttwrd
  • 47
  • 1
  • 9
  • 5
    Why do you have `MAILTO:send_form_email.php` as the `action` on the form? shouldn't it just be `send_form_email.php` – msturdy May 22 '14 at 00:01
  • 1
    textarea is missing a name add `name="inputMessage"` –  May 22 '14 at 00:03
  • 2
    Additionally, your if() statement output never gets seen by the client because the browser disappears off to /postcontact.html – Lee S May 22 '14 at 00:03
  • @LeeS yea, I just put the header there and never removed the if statement, the output is in postcontact.html – brttwrd May 22 '14 at 00:11
  • @brttwrd just checking :) – Lee S May 22 '14 at 00:12
  • This script works fine, I just tested your site and received `We've received your contact information` from the form input. [This is the link to OP's contact form](http://wetzelscontracting.com/contact.html). If you are not receiving the mail from here, you will need to contact your host, or post your mail logs OP. – Ohgodwhy May 22 '14 at 00:27

2 Answers2

3

Why is your form action MAILTO:?

<form name="feedback" class="form-horizontal" role="form" action="MAILTO:send_form_email.php" method="post">

It should just be a clean call to the PHP page like this:

<form name="feedback" class="form-horizontal" role="form" action="send_form_email.php" method="post">

The only time you would use MAILTO: is when constructing an <a href="mailto:someguy@someplace.somedomain">. For an HTML form using PHP like this the goal is to submit the form, and the the $_POST data gets parsed by the PHP which then acts on it to send an e-mail.

Additionally, you are not setting name values in any of the input fields & the names you have for id values dont even match what the PHP is attempting to do. So try this for the HTML:

<form name="feedback" class="form-horizontal" role="form" action="send_form_email.php" method="post">
    <div class="form-group">
            <label for="inputName" class="col-sm-3 control-label">Name</label>
        <div class="col-sm-9">
             <input type="text" class="form-control" id="inputName" placeholder="Name" name="inputName"><br />
        </div></div>

        <div class="form-group">
        <label for="inputEmail" class="col-sm-3 control-label">Email</label>
        <div class="col-sm-9">
            <input name="email" type="email" class="form-control" id="inputEmail" placeholder="Email" name="inputEmail"><br />
    </div></div>

        <div class="form-group">
        <label for="inputMessage" class="col-sm-3 control-label">Message</label>
        <div class="col-sm-9">
             <textarea type="text" class="form-control" id="inputMessage" placeholder="Message"  name="inputMessage"></textarea><br />
        </div></div>

        <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
        <input class="btn btn-default" type="submit" value="Submit">
        </div></div>    
</form>

Also here is the reworked PHP code.

The first thing I did was take all of your $_POST checks into a structure that uses one main array ($post_array) and then rolls through that array to process the values & assign them to similarly named variables. You had absolutely no input validation before. This is technically not even really great “validation” since isset() just checks to see if the $_POST value even exists. But this is step up.

Also I reworked your error checking logic at the end since it all happened after headers were sent. Meaning none of that the whole "We've recived your information" would never work. This is the best I can do with the info you’re providing, but I am doing this to convey the basic concepts:

<?php

if ($_SERVER['REQUEST_METHOD'] == "POST"){

  // Set the post values array.    
  $post_array = array('inputName','inputEmail','inputMessage');

  // Roll through the post values array.
  foreach($post_array as $post_key => $post_value) {
    $$post_key = isset($_POST[$post_key] ? $_POST[$post_key] : null; 
  }

  // From 
  $header="from: $name <$mail_from>";

  // Enter your email address
  $to ='test@gmail.com';
  $send_contact=mail($to,$name,$message,$header);

  // Check, if message sent to your email 
  // display message "We've recived your information"
  if($send_contact){
     header("Location: http://wetzelscontracting.com/postcontact.html");
  }
  else {
    echo "ERROR";
  }
}
?>
Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
  • 3
    Also, you're very vulnerable to having spam email sent out of your script. Please consider adding some security, as we don't need another contributor to the 83%. – Ohgodwhy May 22 '14 at 00:03
  • @Ohgodwhy You are correct. But if the original poster does not even understand how a basic HTML & PHP form works, then how will they understand the concept of validating form input to prevent misuse. – Giacomo1968 May 22 '14 at 00:05
  • But wouldn't that just prevent the form from working rather than somehow send blank emails? – Popnoodles May 22 '14 at 00:05
  • @Popnoodles I have’t experimented with the code, but my guess is the PHP form gets loaded, but because it is via `mailto:` the `$_POST` data does not get processed. – Giacomo1968 May 22 '14 at 00:07
  • @JakeGould that's actually a mistake, in my sloppy copy and pasting, that was something put into an older version of the site in my dreamweaver, the error isnt there on the live version – brttwrd May 22 '14 at 00:08
  • I have, this is not the solution to the problem. – Popnoodles May 22 '14 at 00:08
  • 1
    @JakeGould your right on the OP not understanding as it looks like a plain copy and paste from this answer http://stackoverflow.com/questions/22545312/php-form-firing-blanks Fred -ii- should know better, bad code spawns bad code, much like 83% of the tutorials on the net ;-s – Lawrence Cherone May 22 '14 at 00:08
  • @LozCherone Well, at least now anyone copying & pasting this answer will get a valid & working piece of starter code. It still has issues but those are out of scope of what is being asked or how I understand the overall code. – Giacomo1968 May 22 '14 at 00:20
  • Its still bad, where's the email and header injection validation? – Lawrence Cherone May 22 '14 at 00:21
  • @LozCherone The `isset()` I have in place is the best level of “validation” this script deserves at this point. Am I supposed to read the minds of someone who simply copied code & is now completely lost? – Giacomo1968 May 22 '14 at 00:22
1

As none of the other answers have covered the issue of validation apart from the one accepted, but if your going to do that you might as well just use the extract() function, (it also won’t protect from header injection or email validation).

It’s very important to validate user input and a layer of simple CSRF protection, else bots or spammers can directly POST to your PHP and it will send you a bombardment of emails, you won’t see the forest for the trees (legit emails), or worse inject headers into your inputEmail field and send their own emails using your server which is obviously something you don't want to happen.

Also I’ve added an easy way that you can pass errors from your PHP script that sends the user back to the form for you to echo out.

So for the send_form_email.php file.

<?php
session_start();

if($_SERVER['REQUEST_METHOD'] == "POST" && isset($_SESSION['csrf'])){
    //set error array to fill
    $errors = array();

    // Validate Contact subject
    if(!empty($_POST['inputName'])){
        $name = $_POST['inputName'];
    }else{
        $error['inputName'] = 'Required!';
    }

    // Validate Details
    if(!empty($_POST['inputMessage'])){
        $message = $_POST['inputMessage'];
    }else{
        $error['inputMessage'] = 'Required!';
    }

    // Validate Mail of sender
    if(!empty($_POST['inputEmail'])){
        if(filter_var($_POST['inputEmail'], FILTER_VALIDATE_EMAIL)){
            $mail_from = $_POST['inputEmail'];
        }else{
            $error['inputEmail'] = 'Invalid Email!';
        }
    }else{
        $error['inputEmail'] = 'Required!';
    }

    if(!isset($_POST['csrf']) || $_SESSION['csrf'] != $_POST['csrf']){
        $_SESSION['email_status'] = 'Invalid csrf token!';
        $error = true;
    }

    //stop multiple attempts - just remove csrf token
    unset($_SESSION['csrf']);

    //no errors send mail
    if(empty($error)){
        $headers ='MIME-Version: 1.0'."\r\n";
        $headers.='Content-type: text/html; charset=utf8'."\r\n";
        $headers.='From:<'.$mail_from.'>'."\r\n";
        $headers.="X-Mailer: PHP"."\r\n";

        if(mail('test@gmail.com', 'Website email form: '.$name, $message, $headers)){
            $_SESSION['email_status'] = "We've received your contact information";
            //send to success page
            exit(header("Location: http://wetzelscontracting.com/postcontact.html"));
        }else {
            $_SESSION['email_status'] = 'There was an error sending the mail';
            //backup to file
            file_put_contents('mail.log.txt',print_r($_POST, true).PHP_EOL, FILE_APPEND);
        }
    }else{

        //assuming its this url
        exit(header("Location: http://wetzelscontracting.com/contact.php"));
        $_SESSION['email_error'] = $error;
    }

}else{
    //stop multiple attempts
    unset($_SESSION['csrf']);

    //dont allow GET request/direct access
    exit(header("Location: http://wetzelscontracting.com/contact.php"));

}
?>

Then in your page with the form, start a session to read from the $_SESSION array, and then echo out your errors if any.

<?php 
session_start(); 
//make a session key that we will check against in send_form_email.php
$_SESSION['csrf'] = sha1(uniqid(true));
?>

<?php echo isset($_SESSION['email_status']) ? $_SESSION['email_status'] : null ?>
<form name="feedback" class="form-horizontal" role="form" action="send_form_email.php" method="post">

    <input type="hidden" name="csrf" value="<?php echo $_SESSION['csrf'];?>"/>
    <div class="form-group">
        <label for="inputName" class="col-sm-3 control-label">Name <?php echo isset($_SESSION['email_error']['inputName']) ? $_SESSION['email_error']['inputName'] : null?></label>
        <div class="col-sm-9">
             <input type="text" class="form-control" id="inputName" placeholder="Name" name="inputName"><br />
        </div>
    </div>

    <div class="form-group">
        <label for="inputEmail" class="col-sm-3 control-label">Email <?php echo isset($_SESSION['email_error']['inputEmail']) ? $_SESSION['email_error']['inputEmail'] : null?></label>
        <div class="col-sm-9">
            <input type="email" class="form-control" id="inputEmail" placeholder="Email" name="inputEmail"><br />
        </div>
    </div>

    <div class="form-group">
        <label for="inputMessage" class="col-sm-3 control-label">Message <?php echo isset($_SESSION['email_error']['inputMessage']) ? $_SESSION['email_error']['inputMessage'] : null?></label>
        <div class="col-sm-9">
             <textarea type="text" class="form-control" id="inputMessage" placeholder="Message"  name="inputMessage"></textarea><br />
        </div>
    </div>

    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <input class="btn btn-default" type="submit" value="Submit">
        </div>
    </div>    
</form>
<?php
//unset the errors so there only shown once
unset($_SESSION['email_status']);
unset($_SESSION['email_error']); ?>
Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
  • hmmm I got 2 errors, Failed to load resource: net::ERR_BLOCKED_BY_CLIENT http://cdn.dsultra.com/js/registrar.js and Uncaught ReferenceError: registrar_frameset is not defined – brttwrd May 22 '14 at 01:08
  • @brttwrd that's todo with your adblock, its unrelated to the code in answer. – Lawrence Cherone May 22 '14 at 01:12
  • @brttwrd Also you should change http://wetzelscontracting.com/contact.html to http://wetzelscontracting.com/contact.php note the php extension else php wont be parsed.. – Lawrence Cherone May 22 '14 at 01:17
  • what if the client has adblock though? wouldn't they get the same error? – brttwrd May 22 '14 at 01:17
  • I get all types of errors when pages try and push junk ads on me yes, that's why I use noscript, the error is not cause by the code in my answer but by something else on your page, the google ads in the JustHosts 404 error page perhaps, hence the `http://pagead2.googlesyndication.com/apps/domainpark/show_afd_ads.js` in the js code your receiving – Lawrence Cherone May 22 '14 at 01:20
  • testing on your site, and its working but throwing the csrf token error, make sure this line is correct in the send_form_email.php file `if(!isset($_POST['csrf']) || $_SESSION['csrf'] != $_POST['csrf']){` I made a typo in a last edit. – Lawrence Cherone May 22 '14 at 01:28
  • and remove the `name="email"` from the email form input. **Ive updated the answer with the right code and formatted your html also** – Lawrence Cherone May 22 '14 at 01:29
  • You will because your not using the updated code (I can see that from the source on your site) and **contact.html** must be **contact.php** and [CSRF](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29) is that I could make a 7 or 8 line of code script that will send you millions of emails, then your have so many emails you wont be able to find legit ones... email bomb from your own server, unless you check that the form was posted from your site, the only way todo that is to set a use-once token that is valid for 1 POST its set on your form page checked and then removed. – Lawrence Cherone May 22 '14 at 02:06
  • right I can see you now have both a `contact.html` and a `contact.php` page, remove the `contact.php` page and then rename the `contact.html` page to `contact.php` then change all your links from `contact.html` to `contact.php`, `contact.html` is no more its only there to confuse you ;p. – Lawrence Cherone May 22 '14 at 02:18
  • damn thats right haha I've been sick with the flu the past few days, my brain isnt all there – brttwrd May 22 '14 at 02:22
  • no probs ;p, though if I was you I might have a couple more days off, 8 to 10 days for the flu to pass ;p ... – Lawrence Cherone May 22 '14 at 02:25
  • yea, this is my 3rd time in like 6 months, so I'm used to it. Definitely going to see the doctor after I'm well again. – brttwrd May 22 '14 at 02:30
  • And I can confirm it now works! I was watching my inbox waiting for the test to come through and then it did, thank you very much haha – brttwrd May 22 '14 at 02:31