Send Email from a Web Form with PHP
May 1, 2016
Sending the contents of an online form to an email address is one of the most useful applications of PHP. It’s not difficult; but it’s easy to make a mistake. In this article, I’ll show you how to avoid common pitfalls that arise when sending the contents of a form with PHP.
I assume you have a website that supports PHP. Although you can test part of the script locally, it’s simpler to test sending an actual email on a live website.
To keep things simple, I’m going to use a form with just three input fields and a submit button. The HTML looks like this:
The opening <form> tag contains two attributes: method and action. The method attribute tells the browser how to handle the data when the form is submitted. Always set it to post for email. Setting the form contents to the URL, which looks bad and risks exposing sensitive information. The action attribute tells the browser where to send the form data for processing. In this example, I’m sending it to a page called acknowledge.php.
The script that processes the form uses the name attribute of each input element to extract the data. Never use spaces in the name attribute. If you want to use multiple words, use camel case, such as productName, or an underscore (product_name).
Creating the page for the processing script
As well as processing the form data, the script will confirm whether the message has been sent. Create a web page with the following HTML in the <body> section, and save it as acknowledge.php in the same folder as the form:
The page will eventually use PHP logic to display the correct message.
Gathering the data from the form
To access the data from a field, just add its name attribute in quotes in a pair of square brackets after $_POST. For example,$_POST['email'] contains the value of the field named email.
To process the form, you need to check that it has been submitted, and then build the content of the email message.
1. Above the doctype in acknowledge.php, create a PHP code block like this:
The name of the submit button in my form is send, so this confirms that $_POST['send'] exists—in other words, the form has been submitted. If you use a different name for the submit button, change it to match. PHP variables are case-sensitive: $_post or$_Post won’t work. Also check that opening and closing parentheses match (there are two closing parentheses before the opening curly brace).
All the remaining code in this section goes between the curly braces, and will be executed only if the form has been submitted.
2. Create two variables for the address where the email will be sent and the subject of the email:
PHP uses a dot (period) to join strings (text) together, so this adds the value of the name field to the literal text ‘Name: ‘. The line finishes with two carriage returns and newline characters. Note that the \r\n\r\n is in double quotes. If you use single quotes, you’ll get \r\n\r\n as literal text.
4. The body of the email message must be a single string, so add the remaining fields by preceding the equals sign with a dot like this:
You don’t need the carriage returns and newline characters after the last field.
5. Test your code so far by adding the following line to display the body of the message:
6. Load the page with the form in a browser, type something in each field, and click the Send Message button. If everything goes well, you should see something similar to the following screenshot:
Figure 1: The contents of all form fields have been joined into a single string.
The carriage returns and newline characters are not displayed, but you can check their existence by viewing the source code in your browser.
Sending the email
Assuming all went well, you can try sending the email. PHP doesn’t send the mail. It acts as a go-between for the web server’s mail transport agent (MTA), so it’s best to do this on a live website.
- Delete echo $message; and replace it with the following code:
This passes three arguments to the mail() function: the address the email is being sent to, the subject line, and the <body> of the message. If the function succeeds in passing the message to the MTA, $success will be true.
2. Edit the body section of the page like this to display the appropriate message:
If $success has been set, and if it’s true, the “Thank You” message is displayed. Otherwise, the error message is displayed. The error message will also be displayed if someone tries to reach acknowledge.php without submitting the form.
3. Upload both the form and acknowledge.php to your website, and test the form again. If you get the “Thank You” message, check your mail inbox (and spam trap) to see if you get an email. If you do, congratulations. If not, don’t worry. The code so far is the absolute minimum for sending an email, and it doesn’t work on all servers.
Adding email headers
Even if you received an email from the existing script, you’ll almost certainly want to improve it by adding email headers. One of the most useful headers makes it easy to reply directly to the sender. But you need to do it correctly to avoid turning your online form into a spam relay.
1. Insert a new line in the script just before the line that sends the email, and create a header for the From address like this:
I’ve used double quotes because each header needs to be separated by a carriage return and newline character. Don’t put the sender’s email address in the From header. This header should be an address that uses your website’s domain name.
2. Most websites these days use UTF-8 encoding. So add a new header on the next line using the dot-equals operator:
I haven’t added a carriage return and newline character because the final header will be added only if the sender’s email address is valid.
3. Malicious attackers try to exploit the email field of online forms to inject dozens of email addresses and spam content, so you need to validate the sender’s email address before adding it to the headers:
The filter_input() function takes three arguments. The first one specifies that the input has been sent by the post method. The second is the name of the input field. The third argument specifies how to check the input. In this case, it validates that it’s a single email address. The first and third arguments are PHP constants, and are case-sensitive.
If the input doesn’t look like a valid email address, the function returns false. Otherwise, it returns the address, which is stored as$email. The Reply-To header is added only if the email looks OK. Putting the carriage return and newline character at the beginning has the same effect as adding it at the end of the previous header.
4. Now that you’ve defined the additional email headers, pass them as the fourth argument to the mail() function:
5. Save acknowledge.php, upload the revised version to your website, and test the form again. If you still don’t receive an email, check the next section.
Verifying that the email is from a trusted source
Many hosting companies require passing a fifth argument tomail() to verify that it comes from a trusted source. This is your own email address in quotes and preceded by -f (hyphen-f). If you still don’t get an email after adding the additional headers, change the line that sends the mail like this (using your own email address in the final argument):
Learning more about email and PHP
In this article, I’ve shown you how to create a basic PHP script to send input from an online form to an email address, and how to embed the sender’s email in the email headers without turning your form into a spam relay.