mail()
Today, we will discuss the mail() function in PHP. This function is used to send email messages from a PHP script.
The mail() function sends email messages directly from a PHP script. It is the simplest built-in way to send mail, and this guide covers its syntax and parameters, how headers work, sending HTML and multi-recipient messages, the security pitfalls to avoid, and when you should reach for a dedicated library instead.
What is the mail() Function?
The mail() function is a built-in PHP function that hands an email off to the system's mail transfer agent (MTA) — typically sendmail on Linux — or to the SMTP server configured in php.ini. Because it depends on that local configuration, mail() frequently returns false (or silently fails to deliver) on a development machine that has no MTA installed. It does not open an SMTP connection itself, so it cannot authenticate against an external provider like Gmail.
A true return value only means the message was accepted for delivery by the MTA — it is not a guarantee the email reached the recipient's inbox.
Syntax
mail(
string $to,
string $subject,
string $message,
array|string $additional_headers = [],
string $additional_params = ""
): bool| Parameter | Required | Description |
|---|---|---|
$to | Yes | Recipient address(es). Multiple addresses are comma-separated, e.g. "[email protected], [email protected]". |
$subject | Yes | The subject line. Must not contain newlines. |
$message | Yes | The body. Each line should be separated by \r\n and be no longer than 70 characters. |
$additional_headers | No | Extra headers such as From, Cc, Bcc, Content-Type. A string (CRLF-separated) or, since PHP 7.2, an associative array. |
$additional_params | No | Extra flags passed to the MTA's command line (e.g. -f to set the envelope sender). |
How to Use the mail() Function
Here is a complete, plain-text example that builds headers and checks the return value:
<?php
$to = '[email protected]';
$subject = 'Test email';
$message = 'This is a test email from PHP';
// Additional headers
$headers = 'From: [email protected]' . "\r\n"
. 'Reply-To: [email protected]' . "\r\n"
. 'X-Mailer: PHP/' . phpversion();
// Send the email and check the result
if (mail($to, $subject, $message, $headers)) {
echo "Email sent successfully.";
} else {
echo "Email delivery failed.";
}
?>We define the recipient, subject, and message, then construct the headers. Since mail() returns a boolean, it's best practice to check the return value rather than assume success. The From header matters: without it, many mail servers reject the message or mark it as spam.
Sending an HTML Email
To send HTML instead of plain text, add Content-Type: text/html to the headers. Without it, the client displays the raw tags as text.
<?php
$to = '[email protected]';
$subject = 'HTML email test';
$message = '<h1>Hello</h1><p>This message is <b>HTML</b>.</p>';
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
$headers .= "From: [email protected]\r\n";
mail($to, $subject, $message, $headers);
?>Multiple Recipients, Cc and Bcc
Put several addresses in $to (comma-separated) for the visible "To" line, and use Cc/Bcc headers for copies:
<?php
$to = '[email protected], [email protected]';
$subject = 'Team update';
$message = 'See attached agenda.';
$headers = "From: [email protected]\r\n";
$headers .= "Cc: [email protected]\r\n";
$headers .= "Bcc: [email protected]\r\n";
mail($to, $subject, $message, $headers);
?>Recipients in Bcc are hidden from everyone else, while Cc addresses are visible to all recipients.
Security: Avoiding Header Injection
If any part of the recipient, subject, or headers comes from user input — for example a contact form — an attacker can inject extra newlines to add their own Cc/Bcc headers and hijack your server into sending spam. Always validate addresses and strip line breaks before passing them to mail():
<?php
$email = $_POST['email'] ?? '';
// Reject anything that is not a valid email address
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
exit('Invalid email address.');
}
// Strip CR/LF so the value can't inject new headers
$email = str_replace(["\r", "\n"], '', $email);
?>Use filter_var() with FILTER_VALIDATE_EMAIL to validate, and see PHP Form Validation and Form URL/E-mail handling for safe form processing patterns.
Limitations and When to Use a Library
mail() is fine for simple, low-volume messages, but it has real limits:
- It cannot authenticate against an external SMTP server (no username/password, TLS handshake).
- It offers no native support for attachments — you must hand-build MIME parts.
- Error reporting is minimal: a
falsereturn tells you little about why delivery failed.
For production, transactional email, or anything with attachments, use a dedicated library such as PHPMailer or Symfony Mailer. They handle SMTP authentication, encoding, attachments, and far better error reporting.
Conclusion
The mail() function provides a quick way to send email straight from PHP and is well suited to simple notifications when a working MTA is available. Remember that its success depends on server configuration, that you must guard against header injection with user-supplied data, and that production systems are usually better served by PHPMailer or Symfony Mailer. For related reading, explore PHP Functions and the header() function.