PHP E-mail
mail() parameters, header construction, and why production needs an SMTP library.
Key Points`mail()` depends on a local MTA and often fails; production uses PHPMailer over SMTP.
The four parameters
PHP
<?php
$to = "someone@example.com";
$subject = "测试邮件";
$message = "这是一封测试邮件。\n第二行。";
$headers = implode("\r\n", [
"From: noreply@example.com",
"Reply-To: support@example.com",
"Content-Type: text/plain; charset=UTF-8",
]);
$ok = mail($to, $subject, $message, $headers);
echo $ok ? "已提交给 MTA" : "发送失败", "\n";Output
已提交给 MTAtrue only means it was handed to the local MTA — not that it was delivered. Bounces and spam filtering happen later.
Most containers and cloud hosts have no MTA;
mail() returns false or silently drops. When the code looks right but no mail arrives, check this first.HTML email
PHP
<?php
$to = "someone@example.com";
$subject = "=?UTF-8?B?" . base64_encode("欢迎注册") . "?=";
$message = "<h1>欢迎</h1><p>感谢注册我们的服务。</p>";
$headers = implode("\r\n", [
"MIME-Version: 1.0",
"Content-Type: text/html; charset=UTF-8",
"From: 我的站点 <noreply@example.com>",
]);
echo "主题头: " . substr($subject, 0, 20) . "...\n";
echo "内容类型: text/html\n";
echo "正文长度: " . strlen($message) . "\n";Output
主题头: =?UTF-8?B?5q2m6L+O5rOo5YaM?=...
内容类型: text/html
正文长度: 40Non-ASCII subjects need MIME encoding or some clients show mojibake. =?UTF-8?B?...?= is Base64-encoded UTF-8.
Why production avoids mail()
| Problem | mail() | SMTP 库 |
|---|---|---|
| Needs local MTA | 是 | 否 |
| SMTP authentication | 不支持 | 支持 |
| TLS / SSL | 不支持 | 支持 |
| Error details | 几乎没有 | 异常与响应码 |
| Attachments | 手工拼 MIME | 一行代码 |
| Templates | 手工 | 内置 |
PHP
<?php
// composer require phpmailer/phpmailer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = "smtp.example.com";
$mail->SMTPAuth = true;
$mail->Username = "noreply@example.com";
$mail->Password = getenv("MAIL_PASSWORD");
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom("noreply@example.com", "我的站点");
$mail->addAddress("someone@example.com", "收件人");
$mail->Subject = "欢迎注册";
$mail->Body = "<h1>欢迎</h1>";
$mail->isHTML(true);
$mail->send();
echo "发送成功\n";Output
发送成功Never hardcode credentials — use environment variables or a config service. Keep
.env out of Git or your mailbox becomes someone's spam cannon.Deliverability
- Configure SPF, DKIM, DMARC —— these DNS records decide spam filtering
- Send from a subdomain —— protects the main domain's reputation
- Send both text and HTML —— HTML-only mail is filtered more aggressively
- Handle bounces —— prune hard bounces or reputation drops
- Never buy lists —— complaint rates blacklist the whole domain
mail() 的四个参数
PHP
<?php
$to = "someone@example.com";
$subject = "测试邮件";
$message = "这是一封测试邮件。\n第二行。";
$headers = implode("\r\n", [
"From: noreply@example.com",
"Reply-To: support@example.com",
"Content-Type: text/plain; charset=UTF-8",
]);
$ok = mail($to, $subject, $message, $headers);
echo $ok ? "已提交给 MTA" : "发送失败", "\n";Output
已提交给 MTAmail() 返回 true 只表示「交给了本机邮件服务」,不代表对方收到了。退信、进垃圾箱都发生在之后。
大多数容器、云主机没有装 MTA,
mail() 直接返回 false 或者静默丢弃。看到「代码没错但收不到邮件」,先查这个。HTML 邮件
PHP
<?php
$to = "someone@example.com";
$subject = "=?UTF-8?B?" . base64_encode("欢迎注册") . "?=";
$message = "<h1>欢迎</h1><p>感谢注册我们的服务。</p>";
$headers = implode("\r\n", [
"MIME-Version: 1.0",
"Content-Type: text/html; charset=UTF-8",
"From: 我的站点 <noreply@example.com>",
]);
echo "主题头: " . substr($subject, 0, 20) . "...\n";
echo "内容类型: text/html\n";
echo "正文长度: " . strlen($message) . "\n";Output
主题头: =?UTF-8?B?5q2m6L+O5rOo5YaM?=...
内容类型: text/html
正文长度: 40中文主题必须做 MIME 编码,否则在部分邮件客户端显示成乱码。=?UTF-8?B?...?= 是 Base64 编码的中文主题。
为什么生产环境不用 mail()
| 问题 | mail() | SMTP 库 |
|---|---|---|
| 需要本机 MTA | 是 | 否 |
| SMTP 认证 | 不支持 | 支持 |
| TLS / SSL | 不支持 | 支持 |
| 错误详情 | 几乎没有 | 异常与响应码 |
| 附件 | 手工拼 MIME | 一行代码 |
| 模板 | 手工 | 内置 |
PHP
<?php
// composer require phpmailer/phpmailer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = "smtp.example.com";
$mail->SMTPAuth = true;
$mail->Username = "noreply@example.com";
$mail->Password = getenv("MAIL_PASSWORD");
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom("noreply@example.com", "我的站点");
$mail->addAddress("someone@example.com", "收件人");
$mail->Subject = "欢迎注册";
$mail->Body = "<h1>欢迎</h1>";
$mail->isHTML(true);
$mail->send();
echo "发送成功\n";Output
发送成功密码不要写进代码,用环境变量或配置中心。
.env 文件也不能进 Git——一旦泄露,你的邮箱就成了别人的群发工具。投递率
- 配置 SPF / DKIM / DMARC —— 三项 DNS 记录决定是否被判垃圾邮件
- 用独立子域发信 ——
mail.example.com而不是主域,保护主域声誉 - 纯文本 + HTML 双版本 —— 只有 HTML 的邮件更容易被拦
- 退信处理 —— 硬退信地址要清理,反复投递会拉低声誉
- 别买邮件列表 —— 投诉率一高,整个域都进黑名单