Question
I created a simple contact form on index.html that submits to a separate thankyou.php page. The PHP code runs and the form submits successfully, but no email is actually sent.
Here is the code:
<?php
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
$from = 'From: yoursite.com';
$to = 'contact@yoursite.com';
$subject = 'Customer Inquiry';
$body = "From: $name\nE-Mail: $email\nMessage:\n$message";
if ($_POST['submit']) {
if (mail($to, $subject, $body, $from)) {
echo '<p>Your message has been sent!</p>';
} else {
echo '<p>Something went wrong, please go back and try again.</p>';
}
}
?>
Why would the form submit correctly but the email never be sent, and how can this be fixed?
Short Answer
By the end of this page, you will understand how PHP's mail() function works, why a form can submit successfully even when no email is delivered, and how to fix common issues such as missing server mail configuration, invalid headers, unchecked form input, and weak validation.
Concept
PHP's mail() function only asks the server to hand off an email. It does not guarantee that the email will actually arrive in the inbox.
That is the key idea behind this problem.
A contact form can appear to work because:
- the browser successfully sends a POST request
thankyou.phpruns without a syntax errormail()returnstrueif the server accepts the handoff request
But email delivery can still fail later because of:
- missing mail server configuration on the hosting environment
- invalid
Fromheaders - spam filtering
- incorrect recipient address
- server restrictions on sending mail
- unvalidated or missing form fields
In your example, there are two separate concerns:
- Form submission: the user sends data to
thankyou.php - Email delivery: the server must be configured to send mail
If the first works but the second does not, the problem is usually not the HTML form itself. It is often one of these:
- the server does not support
mail() - the
Fromheader is not formatted correctly - the email is being blocked or marked as spam
- the script does not validate the request before sending
Mental Model
Think of mail() like handing a letter to a mailroom clerk.
- Your HTML form is the person writing the letter.
- PHP builds the envelope and contents.
mail()gives it to the server's mail system.- The mail server tries to deliver it.
If the clerk accepts the letter, your script may think everything is fine. But the letter can still fail later if:
- the address is wrong
- the envelope is badly labeled
- the mailroom is closed
- the letter is rejected by the receiving building
So mail() is not the same as "the email arrived." It is closer to "the server attempted to send it."
Syntax and Examples
The basic syntax of mail() is:
mail($to, $subject, $message, $headers);
Parameters
$to: recipient email address$subject: email subject line$message: message body$headers: optional headers such asFromandReply-To
Beginner-friendly example
<?php
$to = 'contact@example.com';
$subject = 'Test Email';
$message = "Hello, this is a test email.";
$headers = "From: no-reply@example.com\r\n";
if (mail($to, $subject, $message, $headers)) {
echo ;
} {
;
}
Step by Step Execution
Consider this example:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email'] ?? '');
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo 'Invalid email';
exit;
}
$sent = mail(
'contact@example.com',
'Hello',
'Test message',
"From: no-reply@example.com\r\nReply-To: $email\r\n"
);
if ($sent) {
echo 'Sent';
} else {
echo 'Failed';
}
}
?>
What happens step by step
- The browser submits the form using
POST. - PHP checks
$_SERVER['REQUEST_METHOD'] === 'POST'. - The script reads the
emailfield from .
Real World Use Cases
Email sending from PHP forms is common in many real applications.
Contact forms
A visitor fills out a contact form, and the site owner receives the message by email.
Support request forms
A customer sends a problem report, and the support team gets notified.
Account notifications
A system sends password reset links, welcome emails, or verification emails.
Admin alerts
A website emails administrators when errors, payments, or new registrations happen.
Internal business tools
A company dashboard can send approval requests, status updates, or reminders.
In all of these cases, developers must think about more than just calling mail():
- Is the mail server configured?
- Are email headers valid?
- Are addresses verified?
- Could messages be marked as spam?
- Should a library or SMTP service be used instead?
Real Codebase Usage
In real projects, developers usually wrap email logic in safer patterns rather than writing everything inline.
Common patterns
Validate before sending
Check required fields first.
if (empty($name) || empty($email) || empty($message)) {
exit('Missing required fields.');
}
Use guard clauses
Stop early when input is bad.
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
exit('Invalid email address.');
}
Use a server-owned From address
Many mail servers reject messages that pretend to come from arbitrary user emails.
$headers = "From: no-reply@yoursite.com\r\n";
$headers .= "Reply-To: $email\r\n";
Separate form handling from display
Developers often keep email logic in a dedicated handler file or controller.
Log failures
Common Mistakes
Here are some frequent mistakes beginners make when using mail().
1. Assuming form submission means email delivery
A successful page submission does not prove the email was sent.
2. Using an invalid From header
Broken example:
$from = 'From: yoursite.com';
This is not a proper email address. A better version is:
$headers = "From: no-reply@yoursite.com\r\n";
3. Not validating the request method
Broken example:
if ($_POST['submit']) {
// send mail
}
Problems:
submitmight not exist- this can cause notices
- it depends on a specific form field name
Better:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
Comparisons
Here is how mail() compares with related approaches.
| Approach | Best for | Pros | Cons |
|---|---|---|---|
mail() | Simple learning examples, basic hosting | Built into PHP, easy to start | Weak debugging, depends on server config |
| PHPMailer | Real contact forms and production apps | SMTP support, better errors, more features | Requires installation |
| Symfony Mailer | Modern PHP applications | Clean architecture, strong framework support | More setup than mail() |
| API-based email services | High deliverability apps | Reliable delivery, analytics, templates | Requires external service |
$_POST['submit'] vs request method check
Cheat Sheet
mail($to, $subject, $message, $headers);
Safe contact form pattern
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
if (!$name || !$email || !$message) exit('All fields are required.');
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) exit('Invalid email.');
$to = 'contact@yoursite.com';
$subject = 'Customer Inquiry';
= ;
= ;
.= ;
((, , , )) {
;
} {
;
}
}
FAQ
Why does PHP mail() return true but no email arrives?
mail() returning true usually means the server accepted the request to send. It does not guarantee final delivery to the inbox.
Does mail() work on localhost?
Usually not without extra configuration. Your local machine needs a mail server or SMTP setup.
What should I put in the From header?
Use a real email address from your own domain, such as no-reply@yoursite.com.
Should I use the visitor's email in From?
Usually no. Use it in Reply-To after validating it.
Why is checking $_POST['submit'] not ideal?
It depends on a specific form field existing. Checking $_SERVER['REQUEST_METHOD'] === 'POST' is more reliable.
How do I validate an email address in PHP?
Use filter_var($email, FILTER_VALIDATE_EMAIL).
Why is my email going to spam?
Common reasons include weak headers, missing domain authentication, suspicious server setup, or generic message content.
Mini Project
Description
Build a small PHP contact form handler that validates input and attempts to send an email safely. This project demonstrates the difference between receiving form data and actually preparing a valid email request for the server.
Goal
Create a working PHP mail handler that validates form input, uses proper headers, and gives clear success or failure messages.
Requirements
- Accept
name,email, andmessagefrom a POST form. - Reject the request if any field is empty.
- Validate that the email address has a correct format.
- Use a domain-owned
Fromheader and aReply-Toheader. - Show a clear message for success or failure.
Keep learning
Related questions
Are PDO Prepared Statements Enough to Prevent SQL Injection in PHP?
Learn how PDO prepared statements prevent SQL injection in PHP, what they protect, and the mistakes that still leave MySQL apps vulnerable.
Can You Bind an Array to an IN Clause in PHP PDO?
Learn how PDO handles placeholders in IN() clauses, why arrays cannot be bound directly, and the safe PHP pattern to build dynamic queries.
Choosing the Right MySQL Collation for PHP and UTF-8
Learn how MySQL character sets and collations work with PHP, and how to choose a practical UTF-8 setup for web applications.