Frequently Asked Questions About Traversy PHP Contact Form Build
20 answers covering everything from basics to advanced usage.
// Basics
What is the correct parameter order for PHP's mail() function?
The parameter order is: mail(to, subject, message, headers). Specifically: $mail_to (recipient email), $subject (email subject line), $txt (message body), and $headers (optional but recommended, containing at minimum 'From: ' followed by the sender's email). Missing the headers parameter means the email arrives with no sender identity.
Why do I need to separate the HTML form from the PHP processor?
Separating the form (index.php) from the processor (contact_form.php) follows the principle of separating presentation from logic. It keeps your code organized, makes debugging easier, enables the redirect-after-post pattern that prevents duplicate submissions, and allows you to modify the form's appearance without touching email logic. Mixing both in one file creates maintenance headaches and breaks the post-redirect-get pattern.
What hosting do I need for a PHP contact form?
You need any web hosting plan that supports PHP and has a configured mail transfer agent (MTA). Most shared hosting providers like Bluehost, SiteGround, HostGator, and A2 Hosting meet these requirements out of the box. VPS or dedicated servers may require manual MTA configuration. Static hosting platforms like Netlify, Vercel, or GitHub Pages do not support PHP and cannot run mail().
What does \n\n do in a PHP email message body?
The double newline \n\n inserts a visible blank line in the plain-text email body. In the Traversy method, it separates the greeting line ('You have received an email from [name]') from the actual message content. Using a single \n only creates a line break without spacing, causing the email to appear as one dense block of text that is hard to read.
What is the From header in PHP mail() and why is it important?
The From header is a string like 'From: user@example.com' passed as the fourth parameter to mail(). It tells the recipient's email client who sent the message. Without it, the email may show no sender, display the server's default address, or be flagged as spam. In a contact form, set it to the submitter's email so the recipient can see who contacted them and reply directly.
// How To
How do I show a success message after the PHP contact form sends?
After mail() executes, redirect with header('Location: index.php?sent'). On index.php, check for the query string with if(isset($_GET['sent'])) and display a confirmation banner or message like 'Your message has been sent!' This avoids building a separate thank-you page and keeps the user on the main page.
How do I prevent duplicate form submissions in PHP?
Use the redirect-after-post pattern: immediately after calling mail(), execute header('Location: index.php?sent') to redirect the browser. This replaces the processor URL in the browser's history, so pressing refresh reloads index.php instead of resubmitting the form data. Without this redirect, every page refresh triggers another mail() call and sends a duplicate email.
How do I handle errors in PHP mail()?
PHP's mail() returns true if the email was accepted for delivery and false if it was not. Wrap the call in a conditional: if(mail($mail_to, $subject, $txt, $headers)) { redirect to success } else { redirect to error page }. Note that a true return only means the server accepted the message—it does not guarantee delivery. For delivery confirmation, you would need SMTP with delivery status notifications.
// Troubleshooting
Can I use PHP mail() on localhost with XAMPP?
Technically yes, but it requires editing php.ini to configure an SMTP relay, which is complex and unreliable. PHP's mail() on XAMPP silently fails by default because there is no local mail server. The recommended approach is to skip localhost email testing entirely and upload your files to a live hosted server where the mail transfer agent is already configured.
Why does my PHP contact form email go to spam?
Emails sent via PHP mail() often lack proper authentication records. The hosting server may not have SPF, DKIM, or DMARC records configured for the sending domain, which causes email providers to flag messages as spam. Additionally, omitting the From header or using a From address that doesn't match the server domain raises red flags. Configure your domain's DNS with SPF records and ensure the From address belongs to the hosted domain.
What happens if I forget the isset() check in my PHP contact form?
Without the isset() gate, visiting contact_form.php directly in a browser triggers the mail logic with empty or undefined variables. This produces PHP undefined index notices, may attempt to send a blank email, and creates a poor user experience. The isset($_POST['submit']) wrapper ensures the code only executes after an actual form submission.
Why can't I send PHP mail() directly to Gmail?
Google's mail servers enforce strict authentication checks including SPF, DKIM, and DMARC. Emails sent via PHP's mail() from a shared hosting server typically fail these checks because the sending server lacks proper authentication records for Gmail's domain. Google either silently drops or bounces these messages. The workaround is to send to a hosted-domain mailbox and configure that mailbox to forward to Gmail.
// Comparisons
What is the difference between PHP mail() and PHPMailer?
PHP's native mail() function is a simple wrapper that hands an email to the server's mail transfer agent—no authentication, no SMTP support, minimal configuration. PHPMailer is a library that connects to an external SMTP server with authentication, supports HTML emails, attachments, and TLS/SSL encryption. Use mail() for simple text contact forms on shared hosting; use PHPMailer when you need SMTP authentication, HTML formatting, or more reliable delivery.
How does a PHP contact form compare to using WordPress Contact Form 7?
A custom PHP contact form gives you complete control over markup, processing logic, and email formatting without any CMS dependency. Contact Form 7 is a WordPress plugin that provides a GUI for building forms, handles validation, and integrates with WordPress's wp_mail() function. Use the custom PHP approach for non-WordPress sites or when you want minimal overhead; use Contact Form 7 when you are already on WordPress and want quick setup with plugin-managed spam filtering.
Should I use PHP mail() or an API like SendGrid for a contact form?
Use PHP mail() for simple, low-volume contact forms on shared hosting where you want zero external dependencies and no API keys. Use SendGrid, Mailgun, or similar APIs when you need reliable high-volume delivery, detailed analytics, HTML templates, or when your hosting does not support mail(). API services handle SPF/DKIM automatically, reducing spam folder issues, but add a third-party dependency and often have costs at scale.
// Advanced
How do I add form validation to a PHP contact form?
Add server-side validation inside the isset() block before calling mail(). Check that required fields are not empty with empty(), validate the email format with filter_var($mail_from, FILTER_VALIDATE_EMAIL), and sanitize inputs with htmlspecialchars() or filter_input(). If validation fails, redirect back with an error query string like index.php?error=invalid_email instead of calling mail(). Client-side validation with HTML5 required attributes adds a first layer but should never replace server-side checks.
Is PHP mail() secure for contact forms?
PHP's mail() is functional but has security considerations. Without input sanitization, it is vulnerable to email header injection—an attacker can insert additional headers (like BCC) through form fields. Always sanitize and validate all POST inputs before using them in mail(). Use filter_var() for email validation and strip newline characters from any field used in headers. For higher-security needs, consider PHPMailer with SMTP authentication.
Can I add a file attachment to a PHP mail() contact form?
PHP's native mail() function supports attachments but requires manually constructing multipart MIME headers, which is complex and error-prone. You need to set Content-Type to multipart/mixed, define a boundary string, encode the file in base64, and assemble the message body with proper MIME sections. For attachments, PHPMailer is strongly recommended over raw mail() because it handles MIME encoding automatically.
How do I add a CAPTCHA to my PHP contact form?
Integrate Google reCAPTCHA by adding the reCAPTCHA JavaScript widget to your HTML form and verifying the response token server-side in contact_form.php. After the isset() check, send a POST request to Google's verify endpoint with your secret key and the token. Only proceed to call mail() if the verification succeeds. This significantly reduces spam submissions without requiring a third-party form service.
Can I send HTML emails with PHP mail()?
Yes, but you must set the Content-Type header to 'text/html; charset=UTF-8' in the $headers parameter. Then construct $txt with HTML markup instead of plain text. However, the Traversy method uses plain-text emails for simplicity and reliability. HTML emails via mail() can render inconsistently across email clients, so PHPMailer is generally preferred for HTML email formatting.