Form to email code for WordPress
Wednesday, December 14th, 2005
Categorized as Internet and Coding, PHP and mySQL, WordPress
Here's how to add a form to your WordPress site that uses the power of PHP to allow people to send you private emails.
This article is written for those new to WordPress and PHP. It's meant to teach you a number of WordPress and PHP tricks rather than to solve your immediate problem immediately.
First, why use a form? Why not a link with a mailto: URL? That's because spammers have robots that search for email addresses in web pages. When they find yours, they reward you with unending offers to enlarge your body parts. But let's be clear, Jasoose readers don't need bigger body parts.
So we want a way for our readers to send us private emails without divulging our email addresses to the spammers. Here's how.
First, we're going to set up a page (not a post) in WordPress called Contact Me. Then we're going to create a PHP file that will both:
- display our contact form and
- process the info in our contact form when it is submitted, including:
- capture the submitted info
- email the info where ever we like
- display a Thank You message
Step One: Understanding WordPress Pages
WordPress provides two ways to display information. Posts are for regular blog entries. Pages are for more permanent information that doesn't change.
Although WordPress was designed as blogging software, it's easy enough to use it as a web site content management system by putting all your information in pages and not using posts at all.
Compared to posts, pages have a feature that makes a form to email project easier. More on this later.
For now, the main question is whether the WordPress theme you're using displays a Page menu. So next we're going to create a page, then we'll make sure your users can link to it.
Step Two: Create the Contact-Me page
In your WordPress Admin section, click on Write in the top menu, then on Write Page in the submenu. Name the page Contact Me and uncheck Allow Comments and Allow Pings.
In the edit box, put a thank you message that will appear after the form is submitted. For now, a simple, Thanks for contacting me will do - you can make this more elaborate later. Now click the Create New Page button.
Step Three: A link to your Contact Me page
Now look at your site. Do you see a link to your Contact Me page anywhere? If not, the WordPress theme you've chosen isn't displaying a page menu.
Here's how to fix that. At an approprate spot in your chosen theme's sidebar.php file, add the following code:
<?php wp_list_pages('title_li='); ?>
If you want a title above your Page Menu, insert it right after the equal sign in the code. There are other ways you can modify the Page Menu, but I'll let you read about those in the WordPress Codex entry on wp_list_pages.
Step Four: Make a PHP template file
Next we're going to create the file that makes the magic happen. Start by finding the folder that holds the theme for your site (it's in wp-content/themes). In that folder there's a file called page.php. Make a copy of that file and name the copy contact-me.php.
At the top of the contact-me.php file, before anything else, add this:
<?php
/*
Template Name: Contact-Me
*/
?>
/*
Template Name: Contact-Me
*/
?>
Save the file and ftp it over to the equivalent folder on your server.
Now let's make a small change to your Contact Me page in WordPress. Click the WordPress Manage menu, then the Pages submenu, then the Edit link for this page.
Down the page, under the edit box, is a dropdown called Page Template. You should now have a choice called Contact-Me in the drop down box. Select it and click Save.
What you've just done gets WordPress to run the PHP code in the contact-me.php file whenever anyone clicks your Contact Me link. This is the trick I mentioned earlier that makes this project easier. This trick works with WordPress pages but not with WordPress posts.
Although WordPress does use the PHP template files in the folder for your chosen theme when a user looks at your posts, you can't select the template on a post-by-post basis as you can for pages.
Your Contact Me page should be the only page on your site that uses the contact-me.php template.
Step five: Add structure to contact-me.php
Here's how the magic works. When a user goes to your Contact Me page the first time, it will display a form. We'll set up the form so that when a user clicks the Send Message button, WordPress will go right back to our Contact Me page. This time we'll display the Thank You message and send an email with the user's information to ourselves.
First let's put this structure in contact-me.php. Locate the PHP code for the WordPress loop. If you don't know how to do that, the WordPress Codex page on the loop will help you.
Immediately above the loop, put this:
Surprise<br />
<?php if (true) { ?>
<p>Form goes here.</p>
<?php if (true) { ?>
<p>Form goes here.</p>
Just below the loop, put this:
<?php } ?>
Save the page, ftp it to your server, and take a look. You should see the words Surprise and Form goes here followed by the Thank You message you wrote earlier, which is provided courtesy of the loop.
If these changes break your chosen theme, you have to try different spots above or below the various <div> and </div> tags you'll see in the page. These tags control what appears where for your theme.
Step six: Make a form
When that part looks ok, replace the Form goes here line with a simple form:
<form id="contact-me" method="POST" action="../contact-me/">
<p>Your name: <input name="cm_name" size=25 /></p>
<p>Your e-mail address: <input name="cm_email" size=25 /></p>
<p>Subject: <input name="cm_subject" size=25 /></p>
<p>Your message:</p>
<textarea name="cm_message" cols=45 rows=10 wrap=hard></textarea>
<p><input name="cm_submit" type="submit" value="Send Message" /></p>
</form>
<p>Your name: <input name="cm_name" size=25 /></p>
<p>Your e-mail address: <input name="cm_email" size=25 /></p>
<p>Subject: <input name="cm_subject" size=25 /></p>
<p>Your message:</p>
<textarea name="cm_message" cols=45 rows=10 wrap=hard></textarea>
<p><input name="cm_submit" type="submit" value="Send Message" /></p>
</form>
Transfer contact-me.php to your server again and see how it looks now. If you don't like the look of the form, you can fix it with style sheet classes, which we're not touching today.
Note that if you fill in the form and click the Send Message button, the page refreshes. The reason WordPress is bringing us back to this same page is because in our <form> tag, we included the parameter action="../contact-me/".
This parameter tells the web server what program to run when it receives the form's data and we're telling the server to send it right back to us.
If you get an error at this step, it's probably because you're not using the WordPress permalink feature. No problem. Right click on the link to the Contact Me page that we added to your blog earlier and copy the URL. Then insert that URL in the action parameter in place of ../contact-me/.
Step seven: the $_POST superglobal variable
The <form> tag has another interesting parameter, method="POST". There are two methods for forms, POST and GET.
GET makes the information part of the URL; that's where those long URLs with the question marks and ampersands come from.
POST sends the data back to the server as a hidden message rather than in the URL.
So now the question is, how do we access the form's posted data? PHP has what's called a superglobal, which is a variable that's always available, that makes this very easy. For POST data, the variable is $_POST.
To see how this will work, let's display the contents of this superglobal above the form. Replace the Surprise line we inserted earlier with this:
<?php print_r($_POST) ?>
The PHP command print_r is useful here because it will show you what's inside an array variable like $_POST, whereas echo will tell you that it's an array, but won't tell you what's inside it.
Upload contact-me.php to your server, refresh the page, fill out the form with some test data, and submit it.
Now you should see the data you sent above the form, courtesy of print_r.
Step eight: digging form info out of $_POST
In PHP, to get at the contents of data stored in an array variable like $_POST, you use brackets. Inside the brackets you put the key to the data you want, inside single quotes.
The key to $_POST data is the name you used in the form. For example, what's the key to the sender's email address?
<p>Your e-mail address: <input name="cm_email" size=25 /></p>
Since we assigned the name cm_email to this <input> in the form, we can grab what the user actually entered in our PHP code with this:
$_POST['cm_email']
Let's use this variable to decide whether to display our form or our Thank You. If the email address is blank, the user will get the form. If it's filled in, they'll get a Thank You and we'll get an email.
In your contact-me.php file, replace this:
<?php print_r($_POST) ?>
<?php if (true) { ?>
<?php if (true) { ?>
with this:
<?php if (""==$_POST['cm_email']) { ?>
In addition, insert this in between the end of the form and the beginning of the the loop:
<?php } else { ?>
This tells PHP to compare the email address to an empty string. If they are the same, show the form. If they are different, show the Thank You.
You can also reverse the test, putting the double-equal and double-quotes after the $_POST. This will make more sense six months from now when you're trying to figure out how this code works.
However, if statements that use one equal sign instead of two create a common error that is hard to find. When you put the double quotes first, one equal sign will give you an immediate syntax error (you can't make double quotes equal something else). When you put the variable first, on the other hand, one equal sign makes the variable blank and the if comparison always true.
Now transfer the file to your server and test it to make sure it's working. When you fill in the email address with something, you should get the thank you. When it's blank you should get the form.
Step nine: delivering the mail
Are you sweating bullets yet? As complicated as this has been so far, you must suspect actually sending the email is going to be the hardest part of all.
In fact, there's not much to it. PHP has a command that sends simple emails called mail(). In between mail()'s parentheses you need to put - in this order - the email address where you want the email to go, the subject, and the message.
Uh, wait a minute. We collected four items of information, not three. And we want to send the email to ourselves, not to the the submitted email address. So we're going to have to cram the submitter's name, email address, and message into mail()'s message field. I knew this was going to be hard.
Actually, it's not hard at all. The hardest part is going to be to get you to replace the you@your-domain.com with your own email address in the following code:
Copy and paste this part in your contact-me.php code between the } else { we inserted earlier and the loop.
<?php
$cm_to="you@your-domain.com";
$cm_subject="WebPost - ".$_POST['cm_subject'];
$cm_message="From: ".$_POST['cm_name']." at ".$_POST['cm_email']."\n\n";
$cm_message.=$_POST['cm_message'];
if (mail($cm_to, $cm_subject, $cm_message)) {
?>
$cm_to="you@your-domain.com";
$cm_subject="WebPost - ".$_POST['cm_subject'];
$cm_message="From: ".$_POST['cm_name']." at ".$_POST['cm_email']."\n\n";
$cm_message.=$_POST['cm_message'];
if (mail($cm_to, $cm_subject, $cm_message)) {
?>
Use this part to replace the <?php } ?> we inserted earlier.
<?php
} else {
echo "<h2>Sorry, there was a problem sending your message.</h2>";
}
}
?>
} else {
echo "<h2>Sorry, there was a problem sending your message.</h2>";
}
}
?>
New tricks: the first section uses two different PHP methods to make longer strings from shorter strings. In the first line that begins with $cm_message, the dots between the strings and the variables tell PHP to string it all together. Likewise, the dot-equals (.=) in the second line that begins with $cm_message means append what follows to what this variable is already equal to.
The "\n\n" puts a blank line between the user's name and message in the email we'll receive.
Upload it. Go to your form and submit something. Look in your mail box for an email.
Nothing there? Did you remember to put your own email address where the code says you@your-domain.com? Is it correct? Believe it or not, when I wrote this myself, I used a dash where I should have used a dot in my own email address and it took three test emails before I figured out what the error was!
Does your hosting company allow you to send emails via PHP? When you installed WordPress, it tried to send you an email about the Admin account's password. It will send you another email if you register as a user under a different name. If you're not getting these emails, talk to your hosting company.
Otherwise, check your mail again. Some systems take awhile to deliver the mail. If it's still not there, check your code and make it match exactly what's here but with your own email address and it will work.
Step ten: where you can go from here
Once you've received an email, click on Reply in your email program and take a look at the email address the reply would be sent to, if you sent it, which you're not going to do.
That's right, it goes back to your server or your web host or maybe even to you. Remember it was contact-me.php that sent you the actual email, not the person who filled out the form.
Nonetheless, it would improve contact-me.php a lot if Reply used the email address of the person who submitted the form. This is possible, but it involves using an additional parameter in the mail() command.
The problem is that when you use that parameter you open up your form to spammers, who can use an email injection attack to send an unlimited amount of spam through your form.
If your email program will let you look at an email's headers, you'll learn a lot by taking a look at what your form sends you. You'll probably find some anti-abuse headers added by your hosting company, among other things that you didn't put there with the mail() command.
It's not all that hard to build a form that defeats email injection attacks, but that's beyond where we're going today. It involves validating the input we receive from the spammer's robot, er…, our user.
For example, currently we're not checking to see whether what we received as an email address is really an email address. We're not checking to see whether the submitter actually entered a message.
So another way we could enhance contact-me.php would be to check the content of the $_POST variables. If the content wasn't right, we could send the form back to the user, rather than the Thank You, with a message about what's wrong.
It's also possible to build more complex forms and to use PHP to do other tricks with email. If you're interested in getting deeper into sending mail from PHP, you should take a look at PHPMailer, which is a free open-source library that makes things like HTML mail or mail with attachments easier than you might think.

Someone out there seems to think the above code is susceptible to an email insertion attack.
At least they keep trying the trick on my contact page, filling my mailbox with emails that have email commands in the subject line.
On the assumption that this attack must work on some systems, or they wouldn't be wasting their time, I recommend changing the following lines:
to: