Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

WordPress

use wp_mail for my contact forms

Hi,

I would like to use the wp_mail() function to send my contact form details. i know that there are awesome plugins for just this but I would like to create my own before I use a plugin.

So I have it working but I dont know if its good practice so I was hoping I could get an experts opinion.

so far I have this which I place into my functions file

function send_my_awesome_form(){

    if (!isset($_POST['submit'])) { return; }

    // get the info from the from the form
    $form = array();
    $form['fullname'] = $_POST['fullname'];
    $form['company'] = $_POST['company'];
    $form['email'] = $_POST['email'];

    // Build the message
    $message  = "Name :" . $form['fullname'] ."\n";
    $message .= "Company :" . $form['company']  ."\n";
    $message .= "Email :" . $form['email']     ."\n";

    //set the form headers
    $headers = 'From: Contact form <your@contactform.com>';

    // The email subject
    $subject = 'you got mail';

    // Who are we going to send this form too
    $send_to = 'me@myemailaddress.com';

    if (wp_mail( $send_to, $subject, $message, $headers ) ) {
         wp_redirect(home_url()); exit;
     }

}

add_action('wp_head', 'send_my_awesome_form');

at the moment its really basic, i would still need to validate the fields to make sure the email is an email but the basics are here.

So as you can see I add an action to the wp_head so that it can use the wp_redirect function. So basically this function will 'fire' when any page is loaded so you would be able send this form from any page (which scares me a little). I placed this in the wp_head because the form in question is going to be a widget that is on several pages.

and lastly on my form I am using

<form action="" method="POST">

to send the form to the page.

So my question, is this safe? If not is there a way to make this safer and lastly if this is not a good way to do it is there a better way that I should look into?

Raphael Lomotey
Raphael Lomotey
2,587 Points

Hi , hoping someone is still checking this , how are you sending the form to your page, what actions location are you sending it to ?

3 Answers

Randy Hoyt
STAFF
Randy Hoyt
Treehouse Guest Teacher

Yes, it's definitely safe to use wp_mail! That's exactly what you should use, and that's what any good contact form plugin would use. (If at some point you need to install and SMTP plugin, for example, that will hook onto wp_mail and everything will just work.)

You definitely want more validation in place. I would recommend you watch my videos on setting up a contact form. (You don't need the PHPMailer library I use because you are using wp_mail, but most of the other details will be the same.)

Instead of wp_head, I would probably put it further up in the stack. If you take a look at the Action Reference in the codex (link), you can see the order that the actions run. I think I would add this action to wp instead of wp_head; it runs much earlier.

Thanks Randy!

I will most definitely watch the videos

Thank for the lesson Randy!

really helped with the form validation.

I have juiced up the code and everything is working so I thought I would post the result so if anyone else wants to use wp_mail to handle their contact forms they can modify this to fit their needs.

Since my form is in a widget(will be used on several pages) and has a separate thank you page i put in some hidden fields with the current URL and the thank you URL. I did this because if there is an error I want to display it on the form so the user can make the corrections on that page and not have to go back.

The form submission function

add_action('wp', 'send_my_awesome_form'); function send_my_awesome_form(){

if ( $_POST['form'] != "contactform") { return; }

    // get the info from the from the form
    $fullname = trim($_POST['fullname']);
    $company = trim($_POST['company']);
    $email = trim($_POST['email']);
    $honeypot = trim($_POST['address']);
    $currenturl = trim($_POST['currenturl']);
    $redirect = trim($_POST['redirect']);

    //Do all my required fields have a value?
    if ( $fullname == '' AND $email == '' AND $company == '' ) {
        $error = $currenturl.'?status=emptyvalues';
        wp_redirect($error); exit;
    }

    //Email header injection exploit prevention
    foreach ( $_POST as $value ){
        if (stripos($value, 'Content-Type:') != FALSE ) {
            $error = $currenturl.'?status=tryagain';
            wp_redirect($error); exit;
        }
    }

    //the spam honey pot
    if ($honeypot != '') {
        $error = $currenturl.'?status=tryagain';
        wp_redirect($error); exit;
    }

    //validate the email addess
    if ( !is_email( $email )) {
        $error = $currenturl.'?status=email';
        wp_redirect($error); exit;
    }


    // Build the message
    $message  = "Name :" . $fullname ."\n";
    $message .= "Company :" . $company  ."\n";
    $message .= "Email :" . $email     ."\n";

    //set the form headers
    $headers = 'From: Contact form <some@email.com>';

    // The email subject
    $subject = 'you got mail';

    // Who are we going to send this form too
    $send_to = 'your@email.com';


    if ( wp_mail( $send_to, $subject, $message, $headers ) ) {
        wp_redirect( $redirect ); exit;
    }

}

If anything is invalid it will send the user to their current page with a status. So I made a function that will retrieve this value and will echo out a message depending on the error status.

function awesome_form_errors() {

    if ( !$_SERVER['REQUEST_METHOD'] == 'GET') { return; }

    $status = $_GET['status'];

    if ($status == 'emptyvalues') {
        echo 'Please fill in all the fields and try again';
    } 

    elseif ($status == 'tryagain') {
        echo 'Oops we had a problem formatting your form, please try again';
    }

    elseif ($status == 'email') {
        echo 'Please enter in a valid email address';
    }
}

I do hope I nailed it this time, but if you spot room for improvement please post a comment.

Raphael Lomotey
Raphael Lomotey
2,587 Points

can this be tested in local development ?